diff --git a/src/common/hooks/useGetSurplusFiatValue.ts b/src/common/hooks/useGetSurplusFiatValue.ts index 8c5727e0d2..05a2f70bfa 100644 --- a/src/common/hooks/useGetSurplusFiatValue.ts +++ b/src/common/hooks/useGetSurplusFiatValue.ts @@ -53,10 +53,10 @@ function shouldShowSurplus( ): boolean | null { if (fiatAmount) { // When there's a fiat amount, use that to decide whether to display the modal - return Number(fiatAmount.toFixed(3)) > MIN_FIAT_SURPLUS_VALUE_MODAL + return Number(fiatAmount.toFixed(fiatAmount.currency.decimals)) > MIN_FIAT_SURPLUS_VALUE_MODAL } else if (surplusAmount) { // If no fiat value, check whether surplus units are > MIN_SURPLUS_UNITS - return Number(surplusAmount.toFixed(3)) > MIN_SURPLUS_UNITS + return Number(surplusAmount.toFixed(surplusAmount.currency.decimals)) > MIN_SURPLUS_UNITS } // Otherwise, we don't know whether surplus should, return `null` to indicate that diff --git a/src/modules/appData/services/index.ts b/src/modules/appData/services/index.ts index fd2d61c9fa..b191f6e89a 100644 --- a/src/modules/appData/services/index.ts +++ b/src/modules/appData/services/index.ts @@ -25,5 +25,7 @@ export interface UploadAppDataProps { */ export const uploadAppDataDocOrderbookApi: UploadAppDataDoc = async (props) => { const { appDataKeccak256, fullAppData, chainId, env } = props - orderBookApi.uploadAppData(appDataKeccak256, fullAppData, { chainId, env }) + + const contextOverride = env ? { chainId, env } : { chainId } + orderBookApi.uploadAppData(appDataKeccak256, fullAppData, contextOverride) } diff --git a/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts b/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts index 26a850e36b..3186cbc225 100644 --- a/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts +++ b/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts @@ -34,7 +34,6 @@ export async function safeBundleEthFlow( spender, context, callbacks, - appDataInfo, swapConfirmManager, dispatch, orderParams, @@ -124,13 +123,10 @@ export async function safeBundleEthFlow( ) tradeFlowAnalytics.sign(swapFlowAnalyticsContext) - logTradeFlow(LOG_PREFIX, 'STEP 8: add app data to upload queue') - callbacks.uploadAppData({ chainId: context.chainId, orderId, appData: appDataInfo }) - - logTradeFlow(LOG_PREFIX, 'STEP 9: show UI of the successfully sent transaction') + logTradeFlow(LOG_PREFIX, 'STEP 8: show UI of the successfully sent transaction') swapConfirmManager.transactionSent(orderId) } catch (error) { - logTradeFlow(LOG_PREFIX, 'STEP 10: error', error) + logTradeFlow(LOG_PREFIX, 'STEP 9: error', error) const swapErrorMessage = getSwapErrorMessage(error) tradeFlowAnalytics.error(error, swapErrorMessage, swapFlowAnalyticsContext) diff --git a/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts b/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts index 315a8fa9d9..501598fc44 100644 --- a/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts +++ b/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts @@ -9,7 +9,7 @@ import { useSafeApiKit } from 'api/gnosisSafe/hooks/useSafeApiKit' import { fetchTwapOrdersFromSafe } from '../services/fetchTwapOrdersFromSafe' import { TwapOrdersSafeData } from '../types' -const PENDING_TWAP_UPDATE_INTERVAL = ms`10s` +const PENDING_TWAP_UPDATE_INTERVAL = ms`15s` export function useFetchTwapOrdersFromSafe({ safeAddress, diff --git a/src/modules/twap/services/fetchTwapOrdersFromSafe.ts b/src/modules/twap/services/fetchTwapOrdersFromSafe.ts index b007bc2ad3..8df0141a30 100644 --- a/src/modules/twap/services/fetchTwapOrdersFromSafe.ts +++ b/src/modules/twap/services/fetchTwapOrdersFromSafe.ts @@ -1,8 +1,11 @@ import { ComposableCoW } from '@cowprotocol/abis' import type SafeApiKit from '@safe-global/api-kit' +import type { AllTransactionsListResponse } from '@safe-global/api-kit' import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types' -import { isTruthy } from 'legacy/utils/misc' +import ms from 'ms.macro' + +import { delay, isTruthy } from 'legacy/utils/misc' import { SafeTransactionParams } from 'common/types' @@ -10,15 +13,64 @@ import { ConditionalOrderParams, TwapOrdersSafeData } from '../types' // ComposableCoW.createWithContext method const CREATE_COMPOSABLE_ORDER_SELECTOR = '0d0d9800' +// Each page contains 20 transactions by default, so we need to fetch 10 pages to get 200 transactions +const SAFE_TX_HISTORY_DEPTH = 10 +// Just in case, make a short delay between requests +const SAFE_TX_REQUEST_DELAY = ms`100ms` export async function fetchTwapOrdersFromSafe( safeAddress: string, safeApiKit: SafeApiKit, - composableCowContract: ComposableCoW + composableCowContract: ComposableCoW, + /** + * Example of the second chunk url: + * https://safe-transaction-goerli.safe.global/api/v1/safes/0xe9B79591E270B3bCd0CC7e84f7B7De74BA3D0E2F/all-transactions/?executed=false&limit=20&offset=40&queued=true&trusted=true + */ + nextUrl?: string, + accumulator: TwapOrdersSafeData[][] = [] ): Promise { - const allTxs = await safeApiKit.getAllTransactions(safeAddress) - const results = allTxs?.results || [] + const response = await fetchSafeTransactionsChunk(safeAddress, safeApiKit, nextUrl) + + const results = response?.results || [] + const parsedResults = parseSafeTranasctionsResult(safeAddress, composableCowContract, results) + + accumulator.push(parsedResults) + + // Exit from the recursion if we have enough transactions or there is no next page + if (accumulator.length >= SAFE_TX_HISTORY_DEPTH || !response?.next) { + return accumulator.flat() + } + + return fetchTwapOrdersFromSafe(safeAddress, safeApiKit, composableCowContract, response.next, accumulator) +} +async function fetchSafeTransactionsChunk( + safeAddress: string, + safeApiKit: SafeApiKit, + nextUrl?: string +): Promise { + if (nextUrl) { + try { + const response: AllTransactionsListResponse = await fetch(nextUrl).then((res) => res.json()) + + await delay(SAFE_TX_REQUEST_DELAY) + + return response + } catch (error) { + console.error('Error fetching Safe transactions', { safeAddress, nextUrl }, error) + + return { results: [], count: 0 } + } + } + + return safeApiKit.getAllTransactions(safeAddress) +} + +function parseSafeTranasctionsResult( + safeAddress: string, + composableCowContract: ComposableCoW, + results: AllTransactionsListResponse['results'] +): TwapOrdersSafeData[] { return results .map((result) => { if (!result.data || !isSafeMultisigTransactionListResponse(result)) return null