@across-protocol/sdk 4.3.111-alpha.4 → 4.3.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/addressAggregator/adapters/abstract.js +64 -50
- package/dist/cjs/addressAggregator/adapters/abstract.js.map +1 -1
- package/dist/cjs/addressAggregator/adapters/bybit.js +29 -16
- package/dist/cjs/addressAggregator/adapters/bybit.js.map +1 -1
- package/dist/cjs/addressAggregator/adapters/env.js +15 -11
- package/dist/cjs/addressAggregator/adapters/env.js.map +1 -1
- package/dist/cjs/addressAggregator/adapters/file.js +45 -32
- package/dist/cjs/addressAggregator/adapters/file.js.map +1 -1
- package/dist/cjs/addressAggregator/adapters/index.js +1 -1
- package/dist/cjs/addressAggregator/adapters/risklabs.js +36 -22
- package/dist/cjs/addressAggregator/adapters/risklabs.js.map +1 -1
- package/dist/cjs/addressAggregator/index.js +87 -57
- package/dist/cjs/addressAggregator/index.js.map +1 -1
- package/dist/cjs/apiClient/abstractClient.js +8 -9
- package/dist/cjs/apiClient/abstractClient.js.map +1 -1
- package/dist/cjs/apiClient/index.js +1 -1
- package/dist/cjs/apiClient/mockedClient.js +29 -23
- package/dist/cjs/apiClient/mockedClient.js.map +1 -1
- package/dist/cjs/apiClient/productionClient.js +103 -65
- package/dist/cjs/apiClient/productionClient.js.map +1 -1
- package/dist/cjs/arch/evm/BlockUtils.js +208 -122
- package/dist/cjs/arch/evm/BlockUtils.js.map +1 -1
- package/dist/cjs/arch/evm/MessageUtils.js +1 -1
- package/dist/cjs/arch/evm/MessageUtils.js.map +1 -1
- package/dist/cjs/arch/evm/SpokeUtils.js +288 -134
- package/dist/cjs/arch/evm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/evm/index.js +1 -1
- package/dist/cjs/arch/evm/utils/index.js +1 -1
- package/dist/cjs/arch/evm/utils/wait.js +49 -38
- package/dist/cjs/arch/evm/utils/wait.js.map +1 -1
- package/dist/cjs/arch/index.js +1 -1
- package/dist/cjs/arch/svm/BlockUtils.js +158 -102
- package/dist/cjs/arch/svm/BlockUtils.js.map +1 -1
- package/dist/cjs/arch/svm/MessageUtils.js +2 -2
- package/dist/cjs/arch/svm/MessageUtils.js.map +1 -1
- package/dist/cjs/arch/svm/SpokeUtils.js +1147 -708
- package/dist/cjs/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/cjs/arch/svm/encoders.js +1 -1
- package/dist/cjs/arch/svm/encoders.js.map +1 -1
- package/dist/cjs/arch/svm/eventsClient.js +236 -174
- package/dist/cjs/arch/svm/eventsClient.js.map +1 -1
- package/dist/cjs/arch/svm/index.js +1 -1
- package/dist/cjs/arch/svm/provider.js +3 -3
- package/dist/cjs/arch/svm/provider.js.map +1 -1
- package/dist/cjs/arch/svm/utils.js +355 -166
- package/dist/cjs/arch/svm/utils.js.map +1 -1
- package/dist/cjs/caching/Arweave/ArweaveClient.js +246 -168
- package/dist/cjs/caching/Arweave/ArweaveClient.js.map +1 -1
- package/dist/cjs/caching/Arweave/index.js +1 -1
- package/dist/cjs/caching/IPFS/PinataIPFSClient.js +49 -40
- package/dist/cjs/caching/IPFS/PinataIPFSClient.js.map +1 -1
- package/dist/cjs/caching/IPFS/index.js +1 -1
- package/dist/cjs/caching/Memory/MemoryCacheClient.js +18 -13
- package/dist/cjs/caching/Memory/MemoryCacheClient.js.map +1 -1
- package/dist/cjs/caching/Memory/index.js +1 -1
- package/dist/cjs/caching/index.js +1 -1
- package/dist/cjs/clients/AcrossConfigStoreClient/AcrossConfigStoreClient.js +381 -302
- package/dist/cjs/clients/AcrossConfigStoreClient/AcrossConfigStoreClient.js.map +1 -1
- package/dist/cjs/clients/AcrossConfigStoreClient/index.js +1 -1
- package/dist/cjs/clients/BaseAbstractClient.js +83 -58
- package/dist/cjs/clients/BaseAbstractClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +900 -709
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/index.js +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +128 -95
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +53 -48
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js +8 -10
- package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js +90 -67
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +24 -46
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/index.js +1 -1
- package/dist/cjs/clients/HubPoolClient.js +708 -526
- package/dist/cjs/clients/HubPoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js +179 -133
- package/dist/cjs/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js +183 -124
- package/dist/cjs/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js +389 -357
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClientManager.js +8 -9
- package/dist/cjs/clients/SpokePoolClient/SpokePoolClientManager.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient/index.js +3 -3
- package/dist/cjs/clients/SpokePoolClient/index.js.map +1 -1
- package/dist/cjs/clients/index.js +1 -1
- package/dist/cjs/clients/mocks/MockConfigStoreClient.js +67 -58
- package/dist/cjs/clients/mocks/MockConfigStoreClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockEvents.js +52 -47
- package/dist/cjs/clients/mocks/MockEvents.js.map +1 -1
- package/dist/cjs/clients/mocks/MockHubPoolClient.js +185 -142
- package/dist/cjs/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js +192 -208
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js +143 -140
- package/dist/cjs/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.js +73 -57
- package/dist/cjs/clients/mocks/MockSvmSpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/index.js +1 -1
- package/dist/cjs/coingecko/Coingecko.js +437 -285
- package/dist/cjs/coingecko/Coingecko.js.map +1 -1
- package/dist/cjs/coingecko/index.js +1 -1
- package/dist/cjs/constants.js +30 -23
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/contracts/acrossConfigStore.js +48 -27
- package/dist/cjs/contracts/acrossConfigStore.js.map +1 -1
- package/dist/cjs/contracts/hubPool.js +20 -36
- package/dist/cjs/contracts/hubPool.js.map +1 -1
- package/dist/cjs/contracts/index.js +1 -1
- package/dist/cjs/contracts/utils.js +8 -6
- package/dist/cjs/contracts/utils.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/arbitrum.js +16 -7
- package/dist/cjs/gasPriceOracle/adapters/arbitrum.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/ethereum.js +45 -26
- package/dist/cjs/gasPriceOracle/adapters/ethereum.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/linea-viem.js +28 -16
- package/dist/cjs/gasPriceOracle/adapters/linea-viem.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/polygon.js +112 -73
- package/dist/cjs/gasPriceOracle/adapters/polygon.js.map +1 -1
- package/dist/cjs/gasPriceOracle/adapters/solana.js +33 -20
- package/dist/cjs/gasPriceOracle/adapters/solana.js.map +1 -1
- package/dist/cjs/gasPriceOracle/oracle.js +104 -77
- package/dist/cjs/gasPriceOracle/oracle.js.map +1 -1
- package/dist/cjs/gasPriceOracle/types.js +3 -3
- package/dist/cjs/gasPriceOracle/types.js.map +1 -1
- package/dist/cjs/gasPriceOracle/util.js +8 -8
- package/dist/cjs/gasPriceOracle/util.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/interfaces/index.js +1 -1
- package/dist/cjs/lpFeeCalculator/index.js +1 -1
- package/dist/cjs/lpFeeCalculator/lpFeeCalculator.js +35 -33
- package/dist/cjs/lpFeeCalculator/lpFeeCalculator.js.map +1 -1
- package/dist/cjs/lpFeeCalculator/rateModel.js +9 -7
- package/dist/cjs/lpFeeCalculator/rateModel.js.map +1 -1
- package/dist/cjs/merkleDistributor/MerkleDistributor.js +18 -20
- package/dist/cjs/merkleDistributor/MerkleDistributor.js.map +1 -1
- package/dist/cjs/merkleDistributor/index.js +1 -1
- package/dist/cjs/merkleDistributor/model/index.js +1 -1
- package/dist/cjs/pool/TransactionManager.js +100 -45
- package/dist/cjs/pool/TransactionManager.js.map +1 -1
- package/dist/cjs/pool/index.js +1 -1
- package/dist/cjs/pool/poolClient.js +731 -464
- package/dist/cjs/pool/poolClient.js.map +1 -1
- package/dist/cjs/pool/uma/across/index.js +1 -1
- package/dist/cjs/pool/uma/across/transactionManager.js +100 -45
- package/dist/cjs/pool/uma/across/transactionManager.js.map +1 -1
- package/dist/cjs/pool/uma/clients/erc20/client.js +16 -18
- package/dist/cjs/pool/uma/clients/erc20/client.js.map +1 -1
- package/dist/cjs/pool/uma/clients/erc20/index.js +1 -1
- package/dist/cjs/pool/uma/clients/index.js +1 -1
- package/dist/cjs/pool/uma/index.js +1 -1
- package/dist/cjs/pool/uma/oracle/index.js +1 -1
- package/dist/cjs/pool/uma/oracle/utils.js +5 -4
- package/dist/cjs/pool/uma/oracle/utils.js.map +1 -1
- package/dist/cjs/pool/uma/utils.js +30 -11
- package/dist/cjs/pool/uma/utils.js.map +1 -1
- package/dist/cjs/priceClient/adapters/acrossApi.js +39 -22
- package/dist/cjs/priceClient/adapters/acrossApi.js.map +1 -1
- package/dist/cjs/priceClient/adapters/baseAdapter.js +73 -49
- package/dist/cjs/priceClient/adapters/baseAdapter.js.map +1 -1
- package/dist/cjs/priceClient/adapters/coingecko.js +61 -34
- package/dist/cjs/priceClient/adapters/coingecko.js.map +1 -1
- package/dist/cjs/priceClient/adapters/default.js +31 -16
- package/dist/cjs/priceClient/adapters/default.js.map +1 -1
- package/dist/cjs/priceClient/adapters/defiLlama.js +74 -40
- package/dist/cjs/priceClient/adapters/defiLlama.js.map +1 -1
- package/dist/cjs/priceClient/adapters/index.js +1 -1
- package/dist/cjs/priceClient/index.js +1 -1
- package/dist/cjs/priceClient/priceClient.js +159 -110
- package/dist/cjs/priceClient/priceClient.js.map +1 -1
- package/dist/cjs/providers/alchemy.js +19 -17
- package/dist/cjs/providers/alchemy.js.map +1 -1
- package/dist/cjs/providers/cachedProvider.js +129 -88
- package/dist/cjs/providers/cachedProvider.js.map +1 -1
- package/dist/cjs/providers/drpc.js +11 -9
- package/dist/cjs/providers/drpc.js.map +1 -1
- package/dist/cjs/providers/index.js +1 -1
- package/dist/cjs/providers/infura.js +12 -10
- package/dist/cjs/providers/infura.js.map +1 -1
- package/dist/cjs/providers/mocks/MockCachedSolanaRpcFactory.js +15 -7
- package/dist/cjs/providers/mocks/MockCachedSolanaRpcFactory.js.map +1 -1
- package/dist/cjs/providers/mocks/MockRateLimitedSolanaRpcFactory.js +14 -6
- package/dist/cjs/providers/mocks/MockRateLimitedSolanaRpcFactory.js.map +1 -1
- package/dist/cjs/providers/mocks/MockRetrySolanaRpcFactory.js +15 -7
- package/dist/cjs/providers/mocks/MockRetrySolanaRpcFactory.js.map +1 -1
- package/dist/cjs/providers/mocks/MockSolanaRpcFactory.js +66 -42
- package/dist/cjs/providers/mocks/MockSolanaRpcFactory.js.map +1 -1
- package/dist/cjs/providers/mocks/index.js +1 -1
- package/dist/cjs/providers/mocks/mockEthersProvider.js +31 -29
- package/dist/cjs/providers/mocks/mockEthersProvider.js.map +1 -1
- package/dist/cjs/providers/quicknode.js +21 -19
- package/dist/cjs/providers/quicknode.js.map +1 -1
- package/dist/cjs/providers/rateLimitedProvider.js +79 -64
- package/dist/cjs/providers/rateLimitedProvider.js.map +1 -1
- package/dist/cjs/providers/retryProvider.js +246 -163
- package/dist/cjs/providers/retryProvider.js.map +1 -1
- package/dist/cjs/providers/solana/baseRpcFactories.js +18 -14
- package/dist/cjs/providers/solana/baseRpcFactories.js.map +1 -1
- package/dist/cjs/providers/solana/cachedRpcFactory.js +112 -70
- package/dist/cjs/providers/solana/cachedRpcFactory.js.map +1 -1
- package/dist/cjs/providers/solana/defaultRpcFactory.js +15 -8
- package/dist/cjs/providers/solana/defaultRpcFactory.js.map +1 -1
- package/dist/cjs/providers/solana/index.js +1 -1
- package/dist/cjs/providers/solana/quorumFallbackRpcFactory.js +191 -135
- package/dist/cjs/providers/solana/quorumFallbackRpcFactory.js.map +1 -1
- package/dist/cjs/providers/solana/rateLimitedRpcFactory.js +90 -67
- package/dist/cjs/providers/solana/rateLimitedRpcFactory.js.map +1 -1
- package/dist/cjs/providers/solana/retryRpcFactory.js +79 -52
- package/dist/cjs/providers/solana/retryRpcFactory.js.map +1 -1
- package/dist/cjs/providers/solana/utils.js +2 -2
- package/dist/cjs/providers/solana/utils.js.map +1 -1
- package/dist/cjs/providers/speedProvider.js +53 -31
- package/dist/cjs/providers/speedProvider.js.map +1 -1
- package/dist/cjs/providers/types.js +1 -1
- package/dist/cjs/providers/types.js.map +1 -1
- package/dist/cjs/providers/utils.js +28 -26
- package/dist/cjs/providers/utils.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js +162 -108
- package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/customGasToken.js +26 -14
- package/dist/cjs/relayFeeCalculator/chain-queries/customGasToken.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/factory.js +29 -20
- package/dist/cjs/relayFeeCalculator/chain-queries/factory.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/index.js +1 -1
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +137 -88
- package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/cjs/relayFeeCalculator/index.js +1 -1
- package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js +297 -199
- package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
- package/dist/cjs/typeguards/error.js +7 -5
- package/dist/cjs/typeguards/error.js.map +1 -1
- package/dist/cjs/typeguards/index.js +1 -1
- package/dist/cjs/utils/AddressUtils.js +144 -117
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/ArrayUtils.js +78 -21
- package/dist/cjs/utils/ArrayUtils.js.map +1 -1
- package/dist/cjs/utils/BigNumberUtils.js +10 -9
- package/dist/cjs/utils/BigNumberUtils.js.map +1 -1
- package/dist/cjs/utils/BlockExplorerUtils.js +30 -26
- package/dist/cjs/utils/BlockExplorerUtils.js.map +1 -1
- package/dist/cjs/utils/BlockFinder.js +5 -2
- package/dist/cjs/utils/BlockFinder.js.map +1 -1
- package/dist/cjs/utils/BlockUtils.js +41 -24
- package/dist/cjs/utils/BlockUtils.js.map +1 -1
- package/dist/cjs/utils/BundleUtils.js +24 -21
- package/dist/cjs/utils/BundleUtils.js.map +1 -1
- package/dist/cjs/utils/CCTPUtils.js +126 -62
- package/dist/cjs/utils/CCTPUtils.js.map +1 -1
- package/dist/cjs/utils/CachingUtils.js +42 -20
- package/dist/cjs/utils/CachingUtils.js.map +1 -1
- package/dist/cjs/utils/ContractUtils.js +5 -5
- package/dist/cjs/utils/ContractUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.js +99 -122
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/cjs/utils/EventUtils.js +70 -49
- package/dist/cjs/utils/EventUtils.js.map +1 -1
- package/dist/cjs/utils/FormattingUtils.js +32 -26
- package/dist/cjs/utils/FormattingUtils.js.map +1 -1
- package/dist/cjs/utils/HyperLiquidUtils.js +23 -10
- package/dist/cjs/utils/HyperLiquidUtils.js.map +1 -1
- package/dist/cjs/utils/IPFSUtils.js +34 -16
- package/dist/cjs/utils/IPFSUtils.js.map +1 -1
- package/dist/cjs/utils/JSONUtils.js +6 -6
- package/dist/cjs/utils/JSONUtils.js.map +1 -1
- package/dist/cjs/utils/LogUtils.js +12 -10
- package/dist/cjs/utils/LogUtils.js.map +1 -1
- package/dist/cjs/utils/Multicall.js +115 -56
- package/dist/cjs/utils/Multicall.js.map +1 -1
- package/dist/cjs/utils/NetworkUtils.js +28 -12
- package/dist/cjs/utils/NetworkUtils.js.map +1 -1
- package/dist/cjs/utils/NumberUtils.js +3 -1
- package/dist/cjs/utils/NumberUtils.js.map +1 -1
- package/dist/cjs/utils/ObjectUtils.js +41 -27
- package/dist/cjs/utils/ObjectUtils.js.map +1 -1
- package/dist/cjs/utils/Profiler.js +83 -80
- package/dist/cjs/utils/Profiler.js.map +1 -1
- package/dist/cjs/utils/ReviverUtils.js +9 -5
- package/dist/cjs/utils/ReviverUtils.js.map +1 -1
- package/dist/cjs/utils/SpokeUtils.js +84 -84
- package/dist/cjs/utils/SpokeUtils.js.map +1 -1
- package/dist/cjs/utils/TokenUtils.js +64 -41
- package/dist/cjs/utils/TokenUtils.js.map +1 -1
- package/dist/cjs/utils/TypeGuards.js +1 -1
- package/dist/cjs/utils/TypeGuards.js.map +1 -1
- package/dist/cjs/utils/ValidatorUtils.js +7 -7
- package/dist/cjs/utils/ValidatorUtils.js.map +1 -1
- package/dist/cjs/utils/abi/contracts/index.js +1 -1
- package/dist/cjs/utils/abi/index.js +22 -12
- package/dist/cjs/utils/abi/index.js.map +1 -1
- package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js +12 -9
- package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -1
- package/dist/cjs/utils/abi/typechain/index.js +1 -1
- package/dist/cjs/utils/common.js +53 -40
- package/dist/cjs/utils/common.js.map +1 -1
- package/dist/cjs/utils/index.js +1 -1
- package/dist/esm/addressAggregator/adapters/abstract.js +64 -48
- package/dist/esm/addressAggregator/adapters/abstract.js.map +1 -1
- package/dist/esm/addressAggregator/adapters/bybit.js +29 -15
- package/dist/esm/addressAggregator/adapters/bybit.js.map +1 -1
- package/dist/esm/addressAggregator/adapters/env.js +14 -9
- package/dist/esm/addressAggregator/adapters/env.js.map +1 -1
- package/dist/esm/addressAggregator/adapters/file.js +43 -29
- package/dist/esm/addressAggregator/adapters/file.js.map +1 -1
- package/dist/esm/addressAggregator/adapters/risklabs.js +35 -20
- package/dist/esm/addressAggregator/adapters/risklabs.js.map +1 -1
- package/dist/esm/addressAggregator/index.js +83 -52
- package/dist/esm/addressAggregator/index.js.map +1 -1
- package/dist/esm/addressAggregator/types.js +1 -1
- package/dist/esm/addressAggregator/types.js.map +1 -1
- package/dist/esm/apiClient/abstractClient.js +9 -15
- package/dist/esm/apiClient/abstractClient.js.map +1 -1
- package/dist/esm/apiClient/mockedClient.js +26 -21
- package/dist/esm/apiClient/mockedClient.js.map +1 -1
- package/dist/esm/apiClient/productionClient.js +101 -61
- package/dist/esm/apiClient/productionClient.js.map +1 -1
- package/dist/esm/arch/evm/BlockUtils.js +217 -139
- package/dist/esm/arch/evm/BlockUtils.js.map +1 -1
- package/dist/esm/arch/evm/SpokeUtils.js +289 -146
- package/dist/esm/arch/evm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/evm/utils/wait.js +46 -34
- package/dist/esm/arch/evm/utils/wait.js.map +1 -1
- package/dist/esm/arch/svm/BlockUtils.js +166 -118
- package/dist/esm/arch/svm/BlockUtils.js.map +1 -1
- package/dist/esm/arch/svm/SpokeUtils.js +1150 -738
- package/dist/esm/arch/svm/SpokeUtils.js.map +1 -1
- package/dist/esm/arch/svm/constants.js +1 -1
- package/dist/esm/arch/svm/constants.js.map +1 -1
- package/dist/esm/arch/svm/eventsClient.js +232 -172
- package/dist/esm/arch/svm/eventsClient.js.map +1 -1
- package/dist/esm/arch/svm/provider.js +1 -1
- package/dist/esm/arch/svm/provider.js.map +1 -1
- package/dist/esm/arch/svm/utils.js +345 -155
- package/dist/esm/arch/svm/utils.js.map +1 -1
- package/dist/esm/caching/Arweave/ArweaveClient.js +256 -182
- package/dist/esm/caching/Arweave/ArweaveClient.js.map +1 -1
- package/dist/esm/caching/IPFS/PinataIPFSClient.js +48 -47
- package/dist/esm/caching/IPFS/PinataIPFSClient.js.map +1 -1
- package/dist/esm/caching/Memory/MemoryCacheClient.js +19 -13
- package/dist/esm/caching/Memory/MemoryCacheClient.js.map +1 -1
- package/dist/esm/clients/AcrossConfigStoreClient/AcrossConfigStoreClient.js +408 -333
- package/dist/esm/clients/AcrossConfigStoreClient/AcrossConfigStoreClient.js.map +1 -1
- package/dist/esm/clients/BaseAbstractClient.js +92 -66
- package/dist/esm/clients/BaseAbstractClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +1054 -927
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +131 -102
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +59 -57
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js +5 -7
- package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js +94 -75
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +23 -45
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/esm/clients/HubPoolClient.js +740 -581
- package/dist/esm/clients/HubPoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js +178 -133
- package/dist/esm/clients/SpokePoolClient/EVMSpokePoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js +183 -126
- package/dist/esm/clients/SpokePoolClient/SVMSpokePoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js +399 -372
- package/dist/esm/clients/SpokePoolClient/SpokePoolClient.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/SpokePoolClientManager.js +9 -9
- package/dist/esm/clients/SpokePoolClient/SpokePoolClientManager.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/index.js +2 -2
- package/dist/esm/clients/SpokePoolClient/index.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient/types.js +2 -2
- package/dist/esm/clients/SpokePoolClient/types.js.map +1 -1
- package/dist/esm/clients/mocks/MockConfigStoreClient.js +64 -53
- package/dist/esm/clients/mocks/MockConfigStoreClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockEvents.js +49 -42
- package/dist/esm/clients/mocks/MockEvents.js.map +1 -1
- package/dist/esm/clients/mocks/MockHubPoolClient.js +182 -138
- package/dist/esm/clients/mocks/MockHubPoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSpokePoolClient.js +188 -202
- package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js +132 -127
- package/dist/esm/clients/mocks/MockSvmCpiEventsClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSvmSpokePoolClient.js +69 -53
- package/dist/esm/clients/mocks/MockSvmSpokePoolClient.js.map +1 -1
- package/dist/esm/coingecko/Coingecko.js +443 -298
- package/dist/esm/coingecko/Coingecko.js.map +1 -1
- package/dist/esm/constants.js +47 -40
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/contracts/acrossConfigStore.js +46 -24
- package/dist/esm/contracts/acrossConfigStore.js.map +1 -1
- package/dist/esm/contracts/hubPool.js +18 -34
- package/dist/esm/contracts/hubPool.js.map +1 -1
- package/dist/esm/contracts/utils.js +5 -3
- package/dist/esm/contracts/utils.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/arbitrum.js +14 -6
- package/dist/esm/gasPriceOracle/adapters/arbitrum.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/ethereum.js +42 -22
- package/dist/esm/gasPriceOracle/adapters/ethereum.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/linea-viem.js +25 -13
- package/dist/esm/gasPriceOracle/adapters/linea-viem.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/polygon.js +108 -72
- package/dist/esm/gasPriceOracle/adapters/polygon.js.map +1 -1
- package/dist/esm/gasPriceOracle/adapters/solana.js +31 -22
- package/dist/esm/gasPriceOracle/adapters/solana.js.map +1 -1
- package/dist/esm/gasPriceOracle/oracle.js +96 -70
- package/dist/esm/gasPriceOracle/oracle.js.map +1 -1
- package/dist/esm/gasPriceOracle/types.js +2 -2
- package/dist/esm/gasPriceOracle/types.js.map +1 -1
- package/dist/esm/gasPriceOracle/util.js +4 -4
- package/dist/esm/gasPriceOracle/util.js.map +1 -1
- package/dist/esm/lpFeeCalculator/lpFeeCalculator.js +33 -30
- package/dist/esm/lpFeeCalculator/lpFeeCalculator.js.map +1 -1
- package/dist/esm/lpFeeCalculator/rateModel.js +9 -7
- package/dist/esm/lpFeeCalculator/rateModel.js.map +1 -1
- package/dist/esm/merkleDistributor/MerkleDistributor.js +17 -18
- package/dist/esm/merkleDistributor/MerkleDistributor.js.map +1 -1
- package/dist/esm/pool/TransactionManager.js +100 -45
- package/dist/esm/pool/TransactionManager.js.map +1 -1
- package/dist/esm/pool/poolClient.js +740 -479
- package/dist/esm/pool/poolClient.js.map +1 -1
- package/dist/esm/pool/uma/across/constants.js +2 -2
- package/dist/esm/pool/uma/across/constants.js.map +1 -1
- package/dist/esm/pool/uma/across/transactionManager.js +100 -45
- package/dist/esm/pool/uma/across/transactionManager.js.map +1 -1
- package/dist/esm/pool/uma/clients/erc20/client.js +13 -15
- package/dist/esm/pool/uma/clients/erc20/client.js.map +1 -1
- package/dist/esm/pool/uma/oracle/utils.js +3 -2
- package/dist/esm/pool/uma/oracle/utils.js.map +1 -1
- package/dist/esm/pool/uma/utils.js +28 -9
- package/dist/esm/pool/uma/utils.js.map +1 -1
- package/dist/esm/priceClient/adapters/acrossApi.js +40 -21
- package/dist/esm/priceClient/adapters/acrossApi.js.map +1 -1
- package/dist/esm/priceClient/adapters/baseAdapter.js +72 -46
- package/dist/esm/priceClient/adapters/baseAdapter.js.map +1 -1
- package/dist/esm/priceClient/adapters/coingecko.js +61 -33
- package/dist/esm/priceClient/adapters/coingecko.js.map +1 -1
- package/dist/esm/priceClient/adapters/default.js +31 -15
- package/dist/esm/priceClient/adapters/default.js.map +1 -1
- package/dist/esm/priceClient/adapters/defiLlama.js +73 -38
- package/dist/esm/priceClient/adapters/defiLlama.js.map +1 -1
- package/dist/esm/priceClient/priceClient.js +158 -109
- package/dist/esm/priceClient/priceClient.js.map +1 -1
- package/dist/esm/providers/alchemy.js +18 -16
- package/dist/esm/providers/alchemy.js.map +1 -1
- package/dist/esm/providers/cachedProvider.js +134 -99
- package/dist/esm/providers/cachedProvider.js.map +1 -1
- package/dist/esm/providers/constants.js +3 -3
- package/dist/esm/providers/constants.js.map +1 -1
- package/dist/esm/providers/drpc.js +10 -8
- package/dist/esm/providers/drpc.js.map +1 -1
- package/dist/esm/providers/infura.js +11 -9
- package/dist/esm/providers/infura.js.map +1 -1
- package/dist/esm/providers/mocks/MockCachedSolanaRpcFactory.js +15 -6
- package/dist/esm/providers/mocks/MockCachedSolanaRpcFactory.js.map +1 -1
- package/dist/esm/providers/mocks/MockRateLimitedSolanaRpcFactory.js +14 -5
- package/dist/esm/providers/mocks/MockRateLimitedSolanaRpcFactory.js.map +1 -1
- package/dist/esm/providers/mocks/MockRetrySolanaRpcFactory.js +15 -6
- package/dist/esm/providers/mocks/MockRetrySolanaRpcFactory.js.map +1 -1
- package/dist/esm/providers/mocks/MockSolanaRpcFactory.js +66 -41
- package/dist/esm/providers/mocks/MockSolanaRpcFactory.js.map +1 -1
- package/dist/esm/providers/mocks/mockEthersProvider.js +30 -27
- package/dist/esm/providers/mocks/mockEthersProvider.js.map +1 -1
- package/dist/esm/providers/quicknode.js +20 -18
- package/dist/esm/providers/quicknode.js.map +1 -1
- package/dist/esm/providers/rateLimitedProvider.js +80 -68
- package/dist/esm/providers/rateLimitedProvider.js.map +1 -1
- package/dist/esm/providers/retryProvider.js +259 -186
- package/dist/esm/providers/retryProvider.js.map +1 -1
- package/dist/esm/providers/solana/baseRpcFactories.js +19 -13
- package/dist/esm/providers/solana/baseRpcFactories.js.map +1 -1
- package/dist/esm/providers/solana/cachedRpcFactory.js +112 -75
- package/dist/esm/providers/solana/cachedRpcFactory.js.map +1 -1
- package/dist/esm/providers/solana/defaultRpcFactory.js +14 -6
- package/dist/esm/providers/solana/defaultRpcFactory.js.map +1 -1
- package/dist/esm/providers/solana/quorumFallbackRpcFactory.js +202 -149
- package/dist/esm/providers/solana/quorumFallbackRpcFactory.js.map +1 -1
- package/dist/esm/providers/solana/rateLimitedRpcFactory.js +90 -70
- package/dist/esm/providers/solana/rateLimitedRpcFactory.js.map +1 -1
- package/dist/esm/providers/solana/retryRpcFactory.js +74 -50
- package/dist/esm/providers/solana/retryRpcFactory.js.map +1 -1
- package/dist/esm/providers/solana/utils.js +1 -1
- package/dist/esm/providers/solana/utils.js.map +1 -1
- package/dist/esm/providers/speedProvider.js +51 -28
- package/dist/esm/providers/speedProvider.js.map +1 -1
- package/dist/esm/providers/types.js +2 -2
- package/dist/esm/providers/types.js.map +1 -1
- package/dist/esm/providers/utils.js +20 -17
- package/dist/esm/providers/utils.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js +152 -98
- package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/customGasToken.js +26 -13
- package/dist/esm/relayFeeCalculator/chain-queries/customGasToken.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/factory.js +19 -9
- package/dist/esm/relayFeeCalculator/chain-queries/factory.js.map +1 -1
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +128 -83
- package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
- package/dist/esm/relayFeeCalculator/relayFeeCalculator.js +299 -211
- package/dist/esm/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
- package/dist/esm/typeguards/error.js +5 -3
- package/dist/esm/typeguards/error.js.map +1 -1
- package/dist/esm/utils/AddressUtils.js +147 -115
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/ArrayUtils.js +78 -21
- package/dist/esm/utils/ArrayUtils.js.map +1 -1
- package/dist/esm/utils/BigNumberUtils.js +12 -11
- package/dist/esm/utils/BigNumberUtils.js.map +1 -1
- package/dist/esm/utils/BlockExplorerUtils.js +23 -19
- package/dist/esm/utils/BlockExplorerUtils.js.map +1 -1
- package/dist/esm/utils/BlockFinder.js +6 -2
- package/dist/esm/utils/BlockFinder.js.map +1 -1
- package/dist/esm/utils/BlockUtils.js +40 -31
- package/dist/esm/utils/BlockUtils.js.map +1 -1
- package/dist/esm/utils/BundleUtils.js +24 -21
- package/dist/esm/utils/BundleUtils.js.map +1 -1
- package/dist/esm/utils/CCTPUtils.js +123 -62
- package/dist/esm/utils/CCTPUtils.js.map +1 -1
- package/dist/esm/utils/CachingUtils.js +38 -17
- package/dist/esm/utils/CachingUtils.js.map +1 -1
- package/dist/esm/utils/ContractUtils.js +3 -3
- package/dist/esm/utils/ContractUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.js +98 -121
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/esm/utils/EventUtils.js +69 -52
- package/dist/esm/utils/EventUtils.js.map +1 -1
- package/dist/esm/utils/FormattingUtils.js +26 -20
- package/dist/esm/utils/FormattingUtils.js.map +1 -1
- package/dist/esm/utils/HyperLiquidUtils.js +22 -8
- package/dist/esm/utils/HyperLiquidUtils.js.map +1 -1
- package/dist/esm/utils/IPFSUtils.js +35 -16
- package/dist/esm/utils/IPFSUtils.js.map +1 -1
- package/dist/esm/utils/JSONUtils.js +4 -4
- package/dist/esm/utils/JSONUtils.js.map +1 -1
- package/dist/esm/utils/LogUtils.js +12 -8
- package/dist/esm/utils/LogUtils.js.map +1 -1
- package/dist/esm/utils/Multicall.js +110 -50
- package/dist/esm/utils/Multicall.js.map +1 -1
- package/dist/esm/utils/NetworkUtils.js +28 -12
- package/dist/esm/utils/NetworkUtils.js.map +1 -1
- package/dist/esm/utils/NumberUtils.js +3 -1
- package/dist/esm/utils/NumberUtils.js.map +1 -1
- package/dist/esm/utils/ObjectUtils.js +41 -27
- package/dist/esm/utils/ObjectUtils.js.map +1 -1
- package/dist/esm/utils/Profiler.js +82 -77
- package/dist/esm/utils/Profiler.js.map +1 -1
- package/dist/esm/utils/ReviverUtils.js +7 -3
- package/dist/esm/utils/ReviverUtils.js.map +1 -1
- package/dist/esm/utils/SpokeUtils.js +78 -83
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/esm/utils/TokenUtils.js +57 -33
- package/dist/esm/utils/TokenUtils.js.map +1 -1
- package/dist/esm/utils/ValidatorUtils.js +4 -4
- package/dist/esm/utils/ValidatorUtils.js.map +1 -1
- package/dist/esm/utils/abi/index.js +20 -10
- package/dist/esm/utils/abi/index.js.map +1 -1
- package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js +12 -8
- package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -1
- package/dist/esm/utils/common.js +52 -38
- package/dist/esm/utils/common.js.map +1 -1
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/gasPriceOracle/oracle.d.ts.map +1 -1
- package/dist/types/utils/Multicall.d.ts.map +1 -1
- package/dist/types/utils/NetworkUtils.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/constants.ts +1 -0
- package/src/gasPriceOracle/oracle.ts +1 -0
- package/src/utils/Multicall.ts +1 -0
- package/src/utils/NetworkUtils.ts +8 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { __assign, __awaiter, __generator, __rest } from "tslib";
|
|
1
2
|
import assert from "assert";
|
|
2
3
|
import _ from "lodash";
|
|
3
4
|
import { FillType, FillStatus, } from "../../interfaces";
|
|
@@ -8,51 +9,57 @@ import { BundleDataSS, getRefundInformationFromFill, isChainDisabledAtBlock, pre
|
|
|
8
9
|
import { isEVMSpokePoolClient, isSVMSpokePoolClient } from "../SpokePoolClient";
|
|
9
10
|
import { SpokePoolManager } from "../SpokePoolClient/SpokePoolClientManager";
|
|
10
11
|
// max(uint256) - 1
|
|
11
|
-
export
|
|
12
|
+
export var INFINITE_FILL_DEADLINE = bnUint32Max;
|
|
12
13
|
// V3 dictionary helper functions
|
|
13
14
|
function updateExpiredDepositsV3(dict, deposit) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
var _c, _d;
|
|
14
17
|
// A deposit refund for a deposit is invalid if the depositor has a bytes32 address input for an EVM chain. It is valid otherwise.
|
|
15
18
|
if (!deposit.depositor.isValidOn(deposit.originChainId)) {
|
|
16
19
|
return;
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
dict[originChainId]
|
|
20
|
-
dict[originChainId][inputToken.toBytes32()]
|
|
21
|
+
var originChainId = deposit.originChainId, inputToken = deposit.inputToken;
|
|
22
|
+
(_a = dict[originChainId]) !== null && _a !== void 0 ? _a : (dict[originChainId] = {});
|
|
23
|
+
(_b = (_c = dict[originChainId])[_d = inputToken.toBytes32()]) !== null && _b !== void 0 ? _b : (_c[_d] = []);
|
|
21
24
|
dict[originChainId][inputToken.toBytes32()].push(deposit);
|
|
22
25
|
}
|
|
23
26
|
function updateBundleDepositsV3(dict, deposit) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
var _a, _b;
|
|
28
|
+
var _c, _d;
|
|
29
|
+
var originChainId = deposit.originChainId, inputToken = deposit.inputToken;
|
|
30
|
+
(_a = dict[originChainId]) !== null && _a !== void 0 ? _a : (dict[originChainId] = {});
|
|
31
|
+
(_b = (_c = dict[originChainId])[_d = inputToken.toBytes32()]) !== null && _b !== void 0 ? _b : (_c[_d] = []);
|
|
27
32
|
dict[originChainId][inputToken.toBytes32()].push(deposit);
|
|
28
33
|
}
|
|
29
34
|
function updateBundleFillsV3(dict, fill, lpFeePct, repaymentChainId, repaymentToken, repaymentAddress) {
|
|
35
|
+
var _a, _b, _c;
|
|
36
|
+
var _d, _e;
|
|
30
37
|
// We shouldn't pass any unrepayable fills into this function, so we perform an extra safety check.
|
|
31
38
|
if (!fill.relayer.isValidOn(repaymentChainId)) {
|
|
32
39
|
return;
|
|
33
40
|
}
|
|
34
|
-
dict[repaymentChainId]
|
|
35
|
-
dict[repaymentChainId][repaymentToken.toBytes32()]
|
|
41
|
+
(_a = dict[repaymentChainId]) !== null && _a !== void 0 ? _a : (dict[repaymentChainId] = {});
|
|
42
|
+
(_b = (_d = dict[repaymentChainId])[_e = repaymentToken.toBytes32()]) !== null && _b !== void 0 ? _b : (_d[_e] = {
|
|
36
43
|
fills: [],
|
|
37
44
|
totalRefundAmount: bnZero,
|
|
38
45
|
realizedLpFees: bnZero,
|
|
39
46
|
refunds: {},
|
|
40
|
-
};
|
|
41
|
-
|
|
47
|
+
});
|
|
48
|
+
var bundleFill = __assign(__assign({}, fill), { lpFeePct: lpFeePct, relayer: repaymentAddress });
|
|
42
49
|
// Add all fills, slow and fast, to dictionary.
|
|
43
50
|
assign(dict, [repaymentChainId, repaymentToken.toBytes32(), "fills"], [bundleFill]);
|
|
44
51
|
// All fills update the bundle LP fees.
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
var refundObj = dict[repaymentChainId][repaymentToken.toBytes32()];
|
|
53
|
+
var realizedLpFee = bundleFill.inputAmount.mul(bundleFill.lpFeePct).div(fixedPointAdjustment);
|
|
47
54
|
refundObj.realizedLpFees = refundObj.realizedLpFees ? refundObj.realizedLpFees.add(realizedLpFee) : realizedLpFee;
|
|
48
55
|
// Only fast fills get refunded.
|
|
49
56
|
if (!isSlowFill(bundleFill)) {
|
|
50
|
-
|
|
57
|
+
var refundAmount = bundleFill.inputAmount.mul(fixedPointAdjustment.sub(lpFeePct)).div(fixedPointAdjustment);
|
|
51
58
|
refundObj.totalRefundAmount = refundObj.totalRefundAmount
|
|
52
59
|
? refundObj.totalRefundAmount.add(refundAmount)
|
|
53
60
|
: refundAmount;
|
|
54
61
|
// Instantiate dictionary if it doesn't exist.
|
|
55
|
-
refundObj.refunds
|
|
62
|
+
(_c = refundObj.refunds) !== null && _c !== void 0 ? _c : (refundObj.refunds = {});
|
|
56
63
|
if (refundObj.refunds[bundleFill.relayer.toBytes32()]) {
|
|
57
64
|
refundObj.refunds[bundleFill.relayer.toBytes32()] =
|
|
58
65
|
refundObj.refunds[bundleFill.relayer.toBytes32()].add(refundAmount);
|
|
@@ -63,976 +70,1096 @@ function updateBundleFillsV3(dict, fill, lpFeePct, repaymentChainId, repaymentTo
|
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
function updateBundleExcessSlowFills(dict, deposit) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
var _a, _b;
|
|
74
|
+
var _c, _d;
|
|
75
|
+
var destinationChainId = deposit.destinationChainId, outputToken = deposit.outputToken;
|
|
76
|
+
(_a = dict[destinationChainId]) !== null && _a !== void 0 ? _a : (dict[destinationChainId] = {});
|
|
77
|
+
(_b = (_c = dict[destinationChainId])[_d = outputToken.toBytes32()]) !== null && _b !== void 0 ? _b : (_c[_d] = []);
|
|
69
78
|
dict[destinationChainId][outputToken.toBytes32()].push(deposit);
|
|
70
79
|
}
|
|
71
80
|
function updateBundleSlowFills(dict, deposit) {
|
|
81
|
+
var _a, _b;
|
|
82
|
+
var _c, _d;
|
|
72
83
|
if (!deposit.recipient.isValidOn(deposit.destinationChainId)) {
|
|
73
84
|
return;
|
|
74
85
|
}
|
|
75
|
-
|
|
76
|
-
dict[destinationChainId]
|
|
77
|
-
dict[destinationChainId][outputToken.toBytes32()]
|
|
86
|
+
var destinationChainId = deposit.destinationChainId, outputToken = deposit.outputToken;
|
|
87
|
+
(_a = dict[destinationChainId]) !== null && _a !== void 0 ? _a : (dict[destinationChainId] = {});
|
|
88
|
+
(_b = (_c = dict[destinationChainId])[_d = outputToken.toBytes32()]) !== null && _b !== void 0 ? _b : (_c[_d] = []);
|
|
78
89
|
dict[destinationChainId][outputToken.toBytes32()].push(deposit);
|
|
79
90
|
}
|
|
80
91
|
// @notice Shared client for computing data needed to construct or validate a bundle.
|
|
81
|
-
|
|
82
|
-
logger;
|
|
83
|
-
clients;
|
|
84
|
-
chainIdListForBundleEvaluationBlockNumbers;
|
|
85
|
-
blockRangeEndBlockBuffer;
|
|
86
|
-
loadDataCache = {};
|
|
87
|
-
arweaveDataCache = {};
|
|
88
|
-
bundleTimestampCache = {};
|
|
89
|
-
spokePoolClientManager;
|
|
92
|
+
var BundleDataClient = /** @class */ (function () {
|
|
90
93
|
// eslint-disable-next-line no-useless-constructor
|
|
91
|
-
|
|
94
|
+
function BundleDataClient(logger, clients, spokePoolClients, chainIdListForBundleEvaluationBlockNumbers, blockRangeEndBlockBuffer) {
|
|
95
|
+
if (blockRangeEndBlockBuffer === void 0) { blockRangeEndBlockBuffer = {}; }
|
|
92
96
|
this.logger = logger;
|
|
93
97
|
this.clients = clients;
|
|
94
98
|
this.chainIdListForBundleEvaluationBlockNumbers = chainIdListForBundleEvaluationBlockNumbers;
|
|
95
99
|
this.blockRangeEndBlockBuffer = blockRangeEndBlockBuffer;
|
|
100
|
+
this.loadDataCache = {};
|
|
101
|
+
this.arweaveDataCache = {};
|
|
102
|
+
this.bundleTimestampCache = {};
|
|
96
103
|
this.spokePoolClientManager = new SpokePoolManager(logger, spokePoolClients);
|
|
97
104
|
}
|
|
98
105
|
// This should be called whenever it's possible that the loadData information for a block range could have changed.
|
|
99
106
|
// For instance, if the spoke or hub clients have been updated, it probably makes sense to clear this to be safe.
|
|
100
|
-
clearCache() {
|
|
107
|
+
BundleDataClient.prototype.clearCache = function () {
|
|
101
108
|
this.loadDataCache = {};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
};
|
|
110
|
+
BundleDataClient.prototype.loadDataFromCache = function (key) {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
112
|
+
var _a, _b;
|
|
113
|
+
return __generator(this, function (_c) {
|
|
114
|
+
switch (_c.label) {
|
|
115
|
+
case 0:
|
|
116
|
+
_b = (_a = _).cloneDeep;
|
|
117
|
+
return [4 /*yield*/, this.loadDataCache[key]];
|
|
118
|
+
case 1:
|
|
119
|
+
// Always return a deep cloned copy of object stored in cache. Since JS passes by reference instead of value, we
|
|
120
|
+
// want to minimize the risk that the programmer accidentally mutates data in the cache.
|
|
121
|
+
return [2 /*return*/, _b.apply(_a, [_c.sent()])];
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
BundleDataClient.prototype.getBundleTimestampsFromCache = function (key) {
|
|
109
127
|
if (this.bundleTimestampCache[key]) {
|
|
110
128
|
return _.cloneDeep(this.bundleTimestampCache[key]);
|
|
111
129
|
}
|
|
112
130
|
return undefined;
|
|
113
|
-
}
|
|
114
|
-
setBundleTimestampsInCache(key, timestamps) {
|
|
131
|
+
};
|
|
132
|
+
BundleDataClient.prototype.setBundleTimestampsInCache = function (key, timestamps) {
|
|
115
133
|
this.bundleTimestampCache[key] = timestamps;
|
|
116
|
-
}
|
|
117
|
-
|
|
134
|
+
};
|
|
135
|
+
BundleDataClient.getArweaveClientKey = function (blockRangesForChains) {
|
|
118
136
|
// As a unique key for this bundle, use the bundle mainnet end block, which should
|
|
119
137
|
// never be duplicated between bundles as long as thebundle block range
|
|
120
138
|
// always progresses forwards, which I think is a safe assumption. Other chains might pause
|
|
121
139
|
// but mainnet should never pause.
|
|
122
140
|
return blockRangesForChains[0][1].toString();
|
|
123
|
-
}
|
|
124
|
-
getArweaveBundleDataClientKey(blockRangesForChains) {
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
};
|
|
142
|
+
BundleDataClient.prototype.getArweaveBundleDataClientKey = function (blockRangesForChains) {
|
|
143
|
+
return "bundles-".concat(BundleDataClient.getArweaveClientKey(blockRangesForChains));
|
|
144
|
+
};
|
|
145
|
+
BundleDataClient.prototype.loadPersistedDataFromArweave = function (blockRangesForChains) {
|
|
146
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
147
|
+
var start, persistedData, convertTypedStringRecordIntoNumericRecord, convertSortableEventFieldsIntoRequiredFields, convertEmbeddedSortableEventFieldsIntoRequiredFields, data, bundleData;
|
|
148
|
+
var _a;
|
|
149
|
+
return __generator(this, function (_b) {
|
|
150
|
+
switch (_b.label) {
|
|
151
|
+
case 0:
|
|
152
|
+
if (!isDefined((_a = this.clients) === null || _a === void 0 ? void 0 : _a.arweaveClient)) {
|
|
153
|
+
return [2 /*return*/, undefined];
|
|
154
|
+
}
|
|
155
|
+
start = performance.now();
|
|
156
|
+
return [4 /*yield*/, this.clients.arweaveClient.getByTopic(this.getArweaveBundleDataClientKey(blockRangesForChains), BundleDataSS)];
|
|
157
|
+
case 1:
|
|
158
|
+
persistedData = _b.sent();
|
|
159
|
+
// If there is no data or the data is empty, return undefined because we couldn't
|
|
160
|
+
// pull info from the Arweave persistence layer.
|
|
161
|
+
if (!isDefined(persistedData) || persistedData.length < 1) {
|
|
162
|
+
return [2 /*return*/, undefined];
|
|
163
|
+
}
|
|
164
|
+
convertTypedStringRecordIntoNumericRecord = function (data) {
|
|
165
|
+
return Object.keys(data).reduce(function (acc, chainId) {
|
|
166
|
+
acc[Number(chainId)] = data[chainId];
|
|
167
|
+
return acc;
|
|
168
|
+
}, {});
|
|
169
|
+
};
|
|
170
|
+
convertSortableEventFieldsIntoRequiredFields = function (data) {
|
|
171
|
+
return data.map(function (item) {
|
|
172
|
+
// For txnIndex/transactionIndex: throw if both are defined or both are missing.
|
|
173
|
+
if ((item.txnIndex !== undefined && item.transactionIndex !== undefined) ||
|
|
174
|
+
(item.txnIndex === undefined && item.transactionIndex === undefined)) {
|
|
175
|
+
throw new Error("Either txnIndex or transactionIndex must be defined, but not both.");
|
|
176
|
+
}
|
|
177
|
+
// For txnRef/transactionHash: throw if both are defined or both are missing.
|
|
178
|
+
if ((item.txnRef !== undefined && item.transactionHash !== undefined) ||
|
|
179
|
+
(item.txnRef === undefined && item.transactionHash === undefined)) {
|
|
180
|
+
throw new Error("Either txnRef or transactionHash must be defined, but not both.");
|
|
181
|
+
}
|
|
182
|
+
// Destructure the fields we don't need anymore
|
|
183
|
+
var txnIndex = item.txnIndex, transactionIndex = item.transactionIndex, txnRef = item.txnRef, transactionHash = item.transactionHash, rest = __rest(item, ["txnIndex", "transactionIndex", "txnRef", "transactionHash"]);
|
|
184
|
+
// Return a new object with normalized fields.
|
|
185
|
+
// The non-null assertion (!) is safe here because our conditions ensure that one of each pair is defined.
|
|
186
|
+
return __assign(__assign({}, rest), { txnIndex: txnIndex !== null && txnIndex !== void 0 ? txnIndex : transactionIndex, txnRef: txnRef !== null && txnRef !== void 0 ? txnRef : transactionHash });
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
convertEmbeddedSortableEventFieldsIntoRequiredFields = function (data) {
|
|
190
|
+
return Object.fromEntries(Object.entries(data).map(function (_a) {
|
|
191
|
+
var chainId = _a[0], tokenData = _a[1];
|
|
192
|
+
return [
|
|
193
|
+
chainId,
|
|
194
|
+
Object.fromEntries(Object.entries(tokenData).map(function (_a) {
|
|
195
|
+
var token = _a[0], data = _a[1];
|
|
196
|
+
return [
|
|
197
|
+
token,
|
|
198
|
+
convertSortableEventFieldsIntoRequiredFields(data),
|
|
199
|
+
];
|
|
200
|
+
})),
|
|
201
|
+
];
|
|
202
|
+
}));
|
|
203
|
+
};
|
|
204
|
+
data = persistedData[0].data;
|
|
205
|
+
bundleData = {
|
|
206
|
+
bundleFillsV3: convertTypedStringRecordIntoNumericRecord(Object.fromEntries(Object.entries(data.bundleFillsV3).map(function (_a) {
|
|
207
|
+
var chainId = _a[0], tokenData = _a[1];
|
|
208
|
+
return [
|
|
209
|
+
chainId,
|
|
210
|
+
Object.fromEntries(Object.entries(tokenData).map(function (_a) {
|
|
211
|
+
var token = _a[0], data = _a[1];
|
|
212
|
+
return [
|
|
213
|
+
token,
|
|
214
|
+
{
|
|
215
|
+
refunds: Object.fromEntries(Object.entries(data.refunds).map(function (_a) {
|
|
216
|
+
var refundAddress = _a[0], refund = _a[1];
|
|
217
|
+
return [toBytes32(refundAddress), refund];
|
|
218
|
+
})),
|
|
219
|
+
totalRefundAmount: data.totalRefundAmount,
|
|
220
|
+
realizedLpFees: data.realizedLpFees,
|
|
221
|
+
fills: convertSortableEventFieldsIntoRequiredFields(data.fills),
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
})),
|
|
225
|
+
];
|
|
226
|
+
}))),
|
|
227
|
+
expiredDepositsToRefundV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.expiredDepositsToRefundV3)),
|
|
228
|
+
bundleDepositsV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.bundleDepositsV3)),
|
|
229
|
+
unexecutableSlowFills: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.unexecutableSlowFills)),
|
|
230
|
+
bundleSlowFillsV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.bundleSlowFillsV3)),
|
|
231
|
+
};
|
|
232
|
+
this.logger.debug({
|
|
233
|
+
at: "BundleDataClient#loadPersistedDataFromArweave",
|
|
234
|
+
message: "Loaded persisted data from Arweave in ".concat(Math.round(performance.now() - start) / 1000, "s."),
|
|
235
|
+
blockRanges: JSON.stringify(blockRangesForChains),
|
|
236
|
+
bundleData: prettyPrintV3SpokePoolEvents(bundleData.bundleDepositsV3, bundleData.bundleFillsV3, bundleData.bundleSlowFillsV3, bundleData.expiredDepositsToRefundV3, bundleData.unexecutableSlowFills),
|
|
237
|
+
});
|
|
238
|
+
return [2 /*return*/, bundleData];
|
|
150
239
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
BundleDataClient.prototype.loadArweaveData = function (blockRangesForChains) {
|
|
244
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
245
|
+
var arweaveKey, arweaveData, _a, _b;
|
|
246
|
+
return __generator(this, function (_c) {
|
|
247
|
+
switch (_c.label) {
|
|
248
|
+
case 0:
|
|
249
|
+
arweaveKey = this.getArweaveBundleDataClientKey(blockRangesForChains);
|
|
250
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
251
|
+
if (!this.arweaveDataCache[arweaveKey]) {
|
|
252
|
+
this.arweaveDataCache[arweaveKey] = this.loadPersistedDataFromArweave(blockRangesForChains);
|
|
253
|
+
}
|
|
254
|
+
_b = (_a = _).cloneDeep;
|
|
255
|
+
return [4 /*yield*/, this.arweaveDataCache[arweaveKey]];
|
|
256
|
+
case 1:
|
|
257
|
+
arweaveData = _b.apply(_a, [_c.sent()]);
|
|
258
|
+
return [2 /*return*/, arweaveData];
|
|
155
259
|
}
|
|
156
|
-
// Destructure the fields we don't need anymore
|
|
157
|
-
const { txnIndex, transactionIndex, txnRef, transactionHash, ...rest } = item;
|
|
158
|
-
// Return a new object with normalized fields.
|
|
159
|
-
// The non-null assertion (!) is safe here because our conditions ensure that one of each pair is defined.
|
|
160
|
-
return {
|
|
161
|
-
...rest,
|
|
162
|
-
txnIndex: txnIndex ?? transactionIndex,
|
|
163
|
-
txnRef: txnRef ?? transactionHash,
|
|
164
|
-
};
|
|
165
260
|
});
|
|
166
|
-
};
|
|
167
|
-
const convertEmbeddedSortableEventFieldsIntoRequiredFields = (data) => {
|
|
168
|
-
return Object.fromEntries(Object.entries(data).map(([chainId, tokenData]) => [
|
|
169
|
-
chainId,
|
|
170
|
-
Object.fromEntries(Object.entries(tokenData).map(([token, data]) => [
|
|
171
|
-
token,
|
|
172
|
-
convertSortableEventFieldsIntoRequiredFields(data),
|
|
173
|
-
])),
|
|
174
|
-
]));
|
|
175
|
-
};
|
|
176
|
-
const data = persistedData[0].data;
|
|
177
|
-
// This section processes and transforms bundle data loaded from Arweave storage into the correct format:
|
|
178
|
-
// 1. Each field (bundleFillsV3, expiredDepositsToRefundV3, etc.) contains nested records keyed by chainId and token
|
|
179
|
-
// 2. The chainId keys are converted from strings to numbers using convertTypedStringRecordIntoNumericRecord
|
|
180
|
-
// 3. For arrays of events (fills, deposits, etc.), the transaction fields are normalized:
|
|
181
|
-
// - txnIndex/transactionIndex -> txnIndex
|
|
182
|
-
// - txnRef/transactionHash -> txnRef
|
|
183
|
-
// This ensures consistent field names across all event objects
|
|
184
|
-
// 4. The data structure maintains all other fields like refunds, totalRefundAmount, and realizedLpFees
|
|
185
|
-
const bundleData = {
|
|
186
|
-
bundleFillsV3: convertTypedStringRecordIntoNumericRecord(Object.fromEntries(Object.entries(data.bundleFillsV3).map(([chainId, tokenData]) => [
|
|
187
|
-
chainId,
|
|
188
|
-
Object.fromEntries(Object.entries(tokenData).map(([token, data]) => [
|
|
189
|
-
token,
|
|
190
|
-
{
|
|
191
|
-
refunds: Object.fromEntries(Object.entries(data.refunds).map(([refundAddress, refund]) => [toBytes32(refundAddress), refund])),
|
|
192
|
-
totalRefundAmount: data.totalRefundAmount,
|
|
193
|
-
realizedLpFees: data.realizedLpFees,
|
|
194
|
-
fills: convertSortableEventFieldsIntoRequiredFields(data.fills),
|
|
195
|
-
},
|
|
196
|
-
])),
|
|
197
|
-
]))),
|
|
198
|
-
expiredDepositsToRefundV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.expiredDepositsToRefundV3)),
|
|
199
|
-
bundleDepositsV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.bundleDepositsV3)),
|
|
200
|
-
unexecutableSlowFills: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.unexecutableSlowFills)),
|
|
201
|
-
bundleSlowFillsV3: convertTypedStringRecordIntoNumericRecord(convertEmbeddedSortableEventFieldsIntoRequiredFields(data.bundleSlowFillsV3)),
|
|
202
|
-
};
|
|
203
|
-
this.logger.debug({
|
|
204
|
-
at: "BundleDataClient#loadPersistedDataFromArweave",
|
|
205
|
-
message: `Loaded persisted data from Arweave in ${Math.round(performance.now() - start) / 1000}s.`,
|
|
206
|
-
blockRanges: JSON.stringify(blockRangesForChains),
|
|
207
|
-
bundleData: prettyPrintV3SpokePoolEvents(bundleData.bundleDepositsV3, bundleData.bundleFillsV3, bundleData.bundleSlowFillsV3, bundleData.expiredDepositsToRefundV3, bundleData.unexecutableSlowFills),
|
|
208
261
|
});
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
async loadArweaveData(blockRangesForChains) {
|
|
212
|
-
const arweaveKey = this.getArweaveBundleDataClientKey(blockRangesForChains);
|
|
213
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
214
|
-
if (!this.arweaveDataCache[arweaveKey]) {
|
|
215
|
-
this.arweaveDataCache[arweaveKey] = this.loadPersistedDataFromArweave(blockRangesForChains);
|
|
216
|
-
}
|
|
217
|
-
const arweaveData = _.cloneDeep(await this.arweaveDataCache[arweaveKey]);
|
|
218
|
-
return arweaveData;
|
|
219
|
-
}
|
|
262
|
+
};
|
|
220
263
|
// Common data re-formatting logic shared across all data worker public functions.
|
|
221
264
|
// User must pass in spoke pool to search event data against. This allows the user to refund relays and fill deposits
|
|
222
265
|
// on deprecated spoke pools.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
const [bundleStartBlockForMainnet, bundleEndBlockForMainnet] = blockRangesForChains[0];
|
|
253
|
-
const chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(bundleStartBlockForMainnet);
|
|
254
|
-
if (blockRangesForChains.length > chainIds.length) {
|
|
255
|
-
throw new Error(`Unexpected block range list length of ${blockRangesForChains.length}, should be <= ${chainIds.length}`);
|
|
256
|
-
}
|
|
257
|
-
// V3 specific objects:
|
|
258
|
-
const bundleDepositsV3 = {}; // Deposits in bundle block range.
|
|
259
|
-
const bundleFillsV3 = {}; // Fills to refund in bundle block range.
|
|
260
|
-
const bundleInvalidFillsV3 = []; // Fills that are not valid in this bundle.
|
|
261
|
-
const bundleUnrepayableFillsV3 = []; // Fills that are not repayable in this bundle.
|
|
262
|
-
const bundleInvalidSlowFillRequests = []; // Slow fill requests that are not valid in this bundle.
|
|
263
|
-
const bundleSlowFillsV3 = {}; // Deposits that we need to send slow fills
|
|
264
|
-
// for in this bundle.
|
|
265
|
-
const expiredDepositsToRefundV3 = {};
|
|
266
|
-
// Newly expired deposits in this bundle that need to be refunded.
|
|
267
|
-
const unexecutableSlowFills = {};
|
|
268
|
-
// Deposit data for all Slowfills that was included in a previous
|
|
269
|
-
// bundle and can no longer be executed because (1) they were replaced with a FastFill in this bundle or
|
|
270
|
-
// (2) the fill deadline has passed. We'll need to decrement running balances for these deposits on the
|
|
271
|
-
// destination chain where the slow fill would have been executed.
|
|
272
|
-
const _canCreateSlowFillLeaf = (deposit) => {
|
|
273
|
-
return (
|
|
274
|
-
// Cannot slow fill when input and output tokens are not equivalent.
|
|
275
|
-
this.clients.hubPoolClient.areTokensEquivalent(deposit.inputToken, deposit.originChainId, deposit.outputToken, deposit.destinationChainId, bundleEndBlockForMainnet) &&
|
|
276
|
-
// Cannot slow fill from or to a lite chain.
|
|
277
|
-
!deposit.fromLiteChain &&
|
|
278
|
-
!deposit.toLiteChain);
|
|
279
|
-
};
|
|
280
|
-
const _depositIsExpired = (deposit) => {
|
|
281
|
-
return deposit.fillDeadline < bundleBlockTimestamps[deposit.destinationChainId][1];
|
|
282
|
-
};
|
|
283
|
-
const _getFillStatusForDeposit = (deposit, queryBlock) => {
|
|
284
|
-
return spokePoolClients[deposit.destinationChainId].relayFillStatus(deposit,
|
|
285
|
-
// We can assume that in production
|
|
286
|
-
// the block to query is not one that the spoke pool client
|
|
287
|
-
// hasn't queried. This is because this function will usually be called
|
|
288
|
-
// in production with block ranges that were validated by
|
|
289
|
-
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
|
|
290
|
-
Math.min(queryBlock, spokePoolClients[deposit.destinationChainId].latestHeightSearched));
|
|
291
|
-
};
|
|
292
|
-
// Infer chain ID's to load from number of block ranges passed in.
|
|
293
|
-
const allChainIds = blockRangesForChains
|
|
294
|
-
.map((_blockRange, index) => chainIds[index])
|
|
295
|
-
.filter((chainId) => !isChainDisabledAtBlock(chainId, bundleStartBlockForMainnet, this.clients.configStoreClient) &&
|
|
296
|
-
spokePoolClients[chainId] !== undefined);
|
|
297
|
-
allChainIds.forEach((chainId) => {
|
|
298
|
-
const spokePoolClient = spokePoolClients[chainId];
|
|
299
|
-
if (!spokePoolClient.isUpdated) {
|
|
300
|
-
throw new Error(`SpokePoolClient for chain ${chainId} not updated.`);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
// If spoke pools are V3 contracts, then we need to compute start and end timestamps for block ranges to
|
|
304
|
-
// determine whether fillDeadlines have expired.
|
|
305
|
-
// @dev Going to leave this in so we can see impact on run-time in prod. This makes (allChainIds.length * 2) RPC
|
|
306
|
-
// calls in parallel.
|
|
307
|
-
const _cachedBundleTimestamps = this.getBundleTimestampsFromCache(key);
|
|
308
|
-
let bundleBlockTimestamps = {};
|
|
309
|
-
if (!_cachedBundleTimestamps) {
|
|
310
|
-
bundleBlockTimestamps = await this.getBundleBlockTimestamps(chainIds, blockRangesForChains, spokePoolClients);
|
|
311
|
-
this.setBundleTimestampsInCache(key, bundleBlockTimestamps);
|
|
312
|
-
this.logger.debug({
|
|
313
|
-
at: "BundleDataClient#loadData",
|
|
314
|
-
message: "Bundle block timestamps",
|
|
315
|
-
bundleBlockTimestamps,
|
|
316
|
-
blockRangesForChains: JSON.stringify(blockRangesForChains),
|
|
266
|
+
BundleDataClient.prototype.loadData = function (blockRangesForChains_1, spokePoolClients_1) {
|
|
267
|
+
return __awaiter(this, arguments, void 0, function (blockRangesForChains, spokePoolClients, attemptArweaveLoad) {
|
|
268
|
+
var key, arweaveData, data;
|
|
269
|
+
if (attemptArweaveLoad === void 0) { attemptArweaveLoad = false; }
|
|
270
|
+
return __generator(this, function (_a) {
|
|
271
|
+
switch (_a.label) {
|
|
272
|
+
case 0:
|
|
273
|
+
key = JSON.stringify(blockRangesForChains);
|
|
274
|
+
if (!!this.loadDataCache[key]) return [3 /*break*/, 4];
|
|
275
|
+
arweaveData = void 0;
|
|
276
|
+
if (!attemptArweaveLoad) return [3 /*break*/, 2];
|
|
277
|
+
return [4 /*yield*/, this.loadArweaveData(blockRangesForChains)];
|
|
278
|
+
case 1:
|
|
279
|
+
arweaveData = _a.sent();
|
|
280
|
+
return [3 /*break*/, 3];
|
|
281
|
+
case 2:
|
|
282
|
+
arweaveData = undefined;
|
|
283
|
+
_a.label = 3;
|
|
284
|
+
case 3:
|
|
285
|
+
data = isDefined(arweaveData)
|
|
286
|
+
? // We can return the data to a Promise to keep the return type consistent.
|
|
287
|
+
// Note: this is now a fast operation since we've already loaded the data from Arweave.
|
|
288
|
+
Promise.resolve(arweaveData)
|
|
289
|
+
: this.loadDataFromScratch(blockRangesForChains, spokePoolClients);
|
|
290
|
+
this.loadDataCache[key] = data;
|
|
291
|
+
_a.label = 4;
|
|
292
|
+
case 4: return [2 /*return*/, this.loadDataFromCache(key)];
|
|
293
|
+
}
|
|
317
294
|
});
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
bundleBlockTimestamps = _cachedBundleTimestamps;
|
|
321
|
-
}
|
|
322
|
-
// Use this dictionary to conveniently unite all events with the same relay data hash which will make
|
|
323
|
-
// secondary lookups faster. The goal is to lazily fill up this dictionary with all events in the SpokePool
|
|
324
|
-
// client's in-memory event cache.
|
|
325
|
-
const v3RelayHashes = {};
|
|
326
|
-
// Process all deposits first and populate the v3RelayHashes dictionary. Sort deposits into whether they are
|
|
327
|
-
// in this bundle block range or in a previous bundle block range.
|
|
328
|
-
const bundleDepositHashes = [];
|
|
329
|
-
const olderDepositHashes = [];
|
|
330
|
-
const decodeBundleDepositHash = (depositHash) => {
|
|
331
|
-
const [relayDataHash, i] = depositHash.split("@");
|
|
332
|
-
return { relayDataHash, index: Number(i) };
|
|
333
|
-
};
|
|
334
|
-
// Prerequisite step: Load all deposit events from the current or older bundles into the v3RelayHashes dictionary
|
|
335
|
-
// for convenient matching with fills.
|
|
336
|
-
for (const originChainId of allChainIds) {
|
|
337
|
-
const originClient = spokePoolClients[originChainId];
|
|
338
|
-
const originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
339
|
-
for (const destinationChainId of allChainIds) {
|
|
340
|
-
originClient.getDepositsForDestinationChainWithDuplicates(destinationChainId).forEach((deposit) => {
|
|
341
|
-
if (deposit.blockNumber > originChainBlockRange[1] || isZeroValueDeposit(deposit)) {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
const relayDataHash = getRelayEventKey(deposit);
|
|
345
|
-
if (!v3RelayHashes[relayDataHash]) {
|
|
346
|
-
v3RelayHashes[relayDataHash] = {
|
|
347
|
-
deposits: [deposit],
|
|
348
|
-
fill: undefined,
|
|
349
|
-
slowFillRequest: undefined,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
const { deposits } = v3RelayHashes[relayDataHash];
|
|
354
|
-
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
355
|
-
deposits.push(deposit);
|
|
356
|
-
}
|
|
357
|
-
// Account for duplicate deposits by concatenating the relayDataHash with the count of the number of times
|
|
358
|
-
// we have seen it so far.
|
|
359
|
-
const { deposits } = v3RelayHashes[relayDataHash];
|
|
360
|
-
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
361
|
-
const newBundleDepositHash = `${relayDataHash}@${deposits.length - 1}`;
|
|
362
|
-
const decodedBundleDepositHash = decodeBundleDepositHash(newBundleDepositHash);
|
|
363
|
-
assert(decodedBundleDepositHash.relayDataHash === relayDataHash &&
|
|
364
|
-
decodedBundleDepositHash.index === deposits.length - 1, "Not using correct bundle deposit hash key");
|
|
365
|
-
if (deposit.blockNumber >= originChainBlockRange[0]) {
|
|
366
|
-
if (bundleDepositsV3?.[originChainId]?.[deposit.inputToken.toBytes32()]?.find((d) => duplicateEvent(deposit, d))) {
|
|
367
|
-
this.logger.debug({
|
|
368
|
-
at: "BundleDataClient#loadData",
|
|
369
|
-
message: "Duplicate deposit detected",
|
|
370
|
-
deposit: convertRelayDataParamsToBytes32(deposit),
|
|
371
|
-
});
|
|
372
|
-
throw new Error("Duplicate deposit detected");
|
|
373
|
-
}
|
|
374
|
-
bundleDepositHashes.push(newBundleDepositHash);
|
|
375
|
-
updateBundleDepositsV3(bundleDepositsV3, deposit);
|
|
376
|
-
}
|
|
377
|
-
else if (deposit.blockNumber < originChainBlockRange[0]) {
|
|
378
|
-
olderDepositHashes.push(newBundleDepositHash);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
this.logger.debug({
|
|
384
|
-
at: "BundleDataClient#loadData",
|
|
385
|
-
message: `Processed ${bundleDepositHashes.length + olderDepositHashes.length} deposits in ${performance.now() - start}ms.`,
|
|
386
295
|
});
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const validatedBundleV3Fills = [];
|
|
400
|
-
const validatedBundleSlowFills = [];
|
|
401
|
-
const validatedBundleUnexecutableSlowFills = [];
|
|
402
|
-
let fillCounter = 0;
|
|
403
|
-
for (const originChainId of allChainIds) {
|
|
404
|
-
const originClient = spokePoolClients[originChainId];
|
|
405
|
-
for (const destinationChainId of allChainIds) {
|
|
406
|
-
const destinationClient = spokePoolClients[destinationChainId];
|
|
407
|
-
const destinationChainBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
408
|
-
const originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
409
|
-
const fastFillsReplacingSlowFills = [];
|
|
410
|
-
await forEachAsync(destinationClient
|
|
411
|
-
.getFillsForOriginChain(originChainId)
|
|
412
|
-
// We can remove fills for deposits with input amount equal to zero because these will result in 0 refunded
|
|
413
|
-
// tokens to the filler. We can't remove non-empty message deposit here in case there is a slow fill
|
|
414
|
-
// request for the deposit, we'd want to see the fill took place.
|
|
415
|
-
.filter((fill) => fill.blockNumber <= destinationChainBlockRange[1] &&
|
|
416
|
-
!isZeroValueFillOrSlowFillRequest(fill) &&
|
|
417
|
-
!invalidOutputToken(fill)), async (fill) => {
|
|
418
|
-
fillCounter++;
|
|
419
|
-
const relayDataHash = getRelayEventKey(fill);
|
|
420
|
-
if (v3RelayHashes[relayDataHash]) {
|
|
421
|
-
if (!v3RelayHashes[relayDataHash].fill) {
|
|
422
|
-
const { deposits } = v3RelayHashes[relayDataHash];
|
|
423
|
-
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
424
|
-
v3RelayHashes[relayDataHash].fill = fill;
|
|
425
|
-
if (fill.blockNumber >= destinationChainBlockRange[0]) {
|
|
426
|
-
let provider;
|
|
427
|
-
if (isEVMSpokePoolClient(destinationClient)) {
|
|
428
|
-
provider = destinationClient.spokePool.provider;
|
|
429
|
-
}
|
|
430
|
-
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
431
|
-
provider = destinationClient.svmEventsClient.getRpc();
|
|
432
|
-
}
|
|
433
|
-
const fillToRefund = await verifyFillRepayment(fill, provider, deposits[0], this.clients.hubPoolClient, bundleEndBlockForMainnet);
|
|
434
|
-
if (!isDefined(fillToRefund)) {
|
|
435
|
-
bundleUnrepayableFillsV3.push(fill);
|
|
436
|
-
// We don't return here yet because we still need to mark unexecutable slow fill leaves
|
|
437
|
-
// or duplicate deposits. However, we won't issue a fast fill refund.
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
441
|
-
validatedBundleV3Fills.push({
|
|
442
|
-
...fillToRefund,
|
|
443
|
-
quoteTimestamp: deposits[0].quoteTimestamp,
|
|
444
|
-
});
|
|
445
|
-
// Now that we know this deposit has been filled on-chain, identify any duplicate deposits
|
|
446
|
-
// sent for this fill and refund them to the filler, because this value would not be paid out
|
|
447
|
-
// otherwise. These deposits can no longer expire and get refunded as an expired deposit,
|
|
448
|
-
// and they won't trigger a pre-fill refund because the fill is in this bundle.
|
|
449
|
-
// Pre-fill refunds only happen when deposits are sent in this bundle and the
|
|
450
|
-
// fill is from a prior bundle. Paying out the filler keeps the behavior consistent for how
|
|
451
|
-
// we deal with duplicate deposits regardless if the deposit is matched with a pre-fill or
|
|
452
|
-
// a current bundle fill.
|
|
453
|
-
const duplicateDeposits = deposits.slice(1);
|
|
454
|
-
duplicateDeposits.forEach((duplicateDeposit) => {
|
|
455
|
-
if (isSlowFill(fill)) {
|
|
456
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, duplicateDeposit);
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
validatedBundleV3Fills.push({
|
|
460
|
-
...fillToRefund,
|
|
461
|
-
quoteTimestamp: duplicateDeposit.quoteTimestamp,
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
// If fill replaced a slow fill request, then mark it as one that might have created an
|
|
467
|
-
// unexecutable slow fill. We can't know for sure until we check the slow fill request
|
|
468
|
-
// events.
|
|
469
|
-
if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
470
|
-
_canCreateSlowFillLeaf(deposits[0])) {
|
|
471
|
-
fastFillsReplacingSlowFills.push(relayDataHash);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else {
|
|
476
|
-
this.logger.debug({
|
|
477
|
-
at: "BundleDataClient#loadData",
|
|
478
|
-
message: "Duplicate fill detected",
|
|
479
|
-
fill: convertFillParamsToBytes32(fill),
|
|
480
|
-
});
|
|
481
|
-
throw new Error("Duplicate fill detected");
|
|
296
|
+
};
|
|
297
|
+
BundleDataClient.prototype.loadDataFromScratch = function (blockRangesForChains, spokePoolClients) {
|
|
298
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
299
|
+
var start, key, _a, bundleStartBlockForMainnet, bundleEndBlockForMainnet, chainIds, bundleDepositsV3, bundleFillsV3, bundleInvalidFillsV3, bundleUnrepayableFillsV3, bundleInvalidSlowFillRequests, bundleSlowFillsV3, expiredDepositsToRefundV3, unexecutableSlowFills, _canCreateSlowFillLeaf, _depositIsExpired, _getFillStatusForDeposit, allChainIds, _cachedBundleTimestamps, bundleBlockTimestamps, v3RelayHashes, bundleDepositHashes, olderDepositHashes, decodeBundleDepositHash, _loop_1, _i, allChainIds_1, originChainId, validatedBundleV3Fills, validatedBundleSlowFills, validatedBundleUnexecutableSlowFills, fillCounter, _loop_2, _b, allChainIds_2, originChainId, promises, _c, v3FillLpFees, v3SlowFillLpFees, v3UnexecutableSlowFillLpFees, v3SpokeEventsReadable, invalidFillsWithPartialMatchedDeposits_1, preFillsForNextBundle_1, unknownReasonInvalidFills_1;
|
|
300
|
+
var _this = this;
|
|
301
|
+
return __generator(this, function (_d) {
|
|
302
|
+
switch (_d.label) {
|
|
303
|
+
case 0:
|
|
304
|
+
start = performance.now();
|
|
305
|
+
key = JSON.stringify(blockRangesForChains);
|
|
306
|
+
if (!this.clients.configStoreClient.isUpdated) {
|
|
307
|
+
throw new Error("ConfigStoreClient not updated");
|
|
482
308
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
// At this point, there is no relay hash dictionary entry for this fill, so we need to
|
|
486
|
-
// instantiate the entry. We won't modify the fill.relayer until we match it with a deposit.
|
|
487
|
-
v3RelayHashes[relayDataHash] = {
|
|
488
|
-
deposits: undefined,
|
|
489
|
-
fill,
|
|
490
|
-
slowFillRequest: undefined,
|
|
491
|
-
};
|
|
492
|
-
// TODO: We can remove the following historical query once we deprecate the deposit()
|
|
493
|
-
// function since there won't be any old, unexpired deposits anymore assuming the spoke pool client
|
|
494
|
-
// lookbacks have been validated, which they should be before we run this function.
|
|
495
|
-
// Since there was no deposit matching the relay hash, we need to do a historical query for an
|
|
496
|
-
// older deposit in case the spoke pool client's lookback isn't old enough to find the matching deposit.
|
|
497
|
-
// We can skip this step if the fill's fill deadline is not infinite, because we can assume that the
|
|
498
|
-
// spoke pool clients have loaded deposits old enough to cover all fills with a non-infinite fill deadline.
|
|
499
|
-
if (fill.blockNumber >= destinationChainBlockRange[0]) {
|
|
500
|
-
// Fill has a non-infinite expiry, and we can assume our spoke pool clients have old enough deposits
|
|
501
|
-
// to conclude that this fill is invalid if we haven't found a matching deposit in memory, so
|
|
502
|
-
// skip the historical query.
|
|
503
|
-
if (!INFINITE_FILL_DEADLINE.eq(fill.fillDeadline)) {
|
|
504
|
-
bundleInvalidFillsV3.push(fill);
|
|
505
|
-
return;
|
|
309
|
+
else if (!this.clients.hubPoolClient.isUpdated) {
|
|
310
|
+
throw new Error("HubPoolClient not updated");
|
|
506
311
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (!historicalDeposit.found) {
|
|
512
|
-
bundleInvalidFillsV3.push(fill);
|
|
312
|
+
_a = blockRangesForChains[0], bundleStartBlockForMainnet = _a[0], bundleEndBlockForMainnet = _a[1];
|
|
313
|
+
chainIds = this.clients.configStoreClient.getChainIdIndicesForBlock(bundleStartBlockForMainnet);
|
|
314
|
+
if (blockRangesForChains.length > chainIds.length) {
|
|
315
|
+
throw new Error("Unexpected block range list length of ".concat(blockRangesForChains.length, ", should be <= ").concat(chainIds.length));
|
|
513
316
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
317
|
+
bundleDepositsV3 = {};
|
|
318
|
+
bundleFillsV3 = {};
|
|
319
|
+
bundleInvalidFillsV3 = [];
|
|
320
|
+
bundleUnrepayableFillsV3 = [];
|
|
321
|
+
bundleInvalidSlowFillRequests = [];
|
|
322
|
+
bundleSlowFillsV3 = {};
|
|
323
|
+
expiredDepositsToRefundV3 = {};
|
|
324
|
+
unexecutableSlowFills = {};
|
|
325
|
+
_canCreateSlowFillLeaf = function (deposit) {
|
|
326
|
+
return (
|
|
327
|
+
// Cannot slow fill when input and output tokens are not equivalent.
|
|
328
|
+
_this.clients.hubPoolClient.areTokensEquivalent(deposit.inputToken, deposit.originChainId, deposit.outputToken, deposit.destinationChainId, bundleEndBlockForMainnet) &&
|
|
329
|
+
// Cannot slow fill from or to a lite chain.
|
|
330
|
+
!deposit.fromLiteChain &&
|
|
331
|
+
!deposit.toLiteChain);
|
|
332
|
+
};
|
|
333
|
+
_depositIsExpired = function (deposit) {
|
|
334
|
+
return deposit.fillDeadline < bundleBlockTimestamps[deposit.destinationChainId][1];
|
|
335
|
+
};
|
|
336
|
+
_getFillStatusForDeposit = function (deposit, queryBlock) {
|
|
337
|
+
return spokePoolClients[deposit.destinationChainId].relayFillStatus(deposit,
|
|
338
|
+
// We can assume that in production
|
|
339
|
+
// the block to query is not one that the spoke pool client
|
|
340
|
+
// hasn't queried. This is because this function will usually be called
|
|
341
|
+
// in production with block ranges that were validated by
|
|
342
|
+
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
|
|
343
|
+
Math.min(queryBlock, spokePoolClients[deposit.destinationChainId].latestHeightSearched));
|
|
344
|
+
};
|
|
345
|
+
allChainIds = blockRangesForChains
|
|
346
|
+
.map(function (_blockRange, index) { return chainIds[index]; })
|
|
347
|
+
.filter(function (chainId) {
|
|
348
|
+
return !isChainDisabledAtBlock(chainId, bundleStartBlockForMainnet, _this.clients.configStoreClient) &&
|
|
349
|
+
spokePoolClients[chainId] !== undefined;
|
|
350
|
+
});
|
|
351
|
+
allChainIds.forEach(function (chainId) {
|
|
352
|
+
var spokePoolClient = spokePoolClients[chainId];
|
|
353
|
+
if (!spokePoolClient.isUpdated) {
|
|
354
|
+
throw new Error("SpokePoolClient for chain ".concat(chainId, " not updated."));
|
|
535
355
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
356
|
+
});
|
|
357
|
+
_cachedBundleTimestamps = this.getBundleTimestampsFromCache(key);
|
|
358
|
+
bundleBlockTimestamps = {};
|
|
359
|
+
if (!!_cachedBundleTimestamps) return [3 /*break*/, 2];
|
|
360
|
+
return [4 /*yield*/, this.getBundleBlockTimestamps(chainIds, blockRangesForChains, spokePoolClients)];
|
|
361
|
+
case 1:
|
|
362
|
+
bundleBlockTimestamps = _d.sent();
|
|
363
|
+
this.setBundleTimestampsInCache(key, bundleBlockTimestamps);
|
|
364
|
+
this.logger.debug({
|
|
365
|
+
at: "BundleDataClient#loadData",
|
|
366
|
+
message: "Bundle block timestamps",
|
|
367
|
+
bundleBlockTimestamps: bundleBlockTimestamps,
|
|
368
|
+
blockRangesForChains: JSON.stringify(blockRangesForChains),
|
|
369
|
+
});
|
|
370
|
+
return [3 /*break*/, 3];
|
|
371
|
+
case 2:
|
|
372
|
+
bundleBlockTimestamps = _cachedBundleTimestamps;
|
|
373
|
+
_d.label = 3;
|
|
374
|
+
case 3:
|
|
375
|
+
v3RelayHashes = {};
|
|
376
|
+
bundleDepositHashes = [];
|
|
377
|
+
olderDepositHashes = [];
|
|
378
|
+
decodeBundleDepositHash = function (depositHash) {
|
|
379
|
+
var _a = depositHash.split("@"), relayDataHash = _a[0], i = _a[1];
|
|
380
|
+
return { relayDataHash: relayDataHash, index: Number(i) };
|
|
381
|
+
};
|
|
382
|
+
_loop_1 = function (originChainId) {
|
|
383
|
+
var originClient = spokePoolClients[originChainId];
|
|
384
|
+
var originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
385
|
+
for (var _e = 0, allChainIds_3 = allChainIds; _e < allChainIds_3.length; _e++) {
|
|
386
|
+
var destinationChainId = allChainIds_3[_e];
|
|
387
|
+
originClient.getDepositsForDestinationChainWithDuplicates(destinationChainId).forEach(function (deposit) {
|
|
388
|
+
var _a, _b;
|
|
389
|
+
if (deposit.blockNumber > originChainBlockRange[1] || isZeroValueDeposit(deposit)) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
var relayDataHash = getRelayEventKey(deposit);
|
|
393
|
+
if (!v3RelayHashes[relayDataHash]) {
|
|
394
|
+
v3RelayHashes[relayDataHash] = {
|
|
395
|
+
deposits: [deposit],
|
|
396
|
+
fill: undefined,
|
|
397
|
+
slowFillRequest: undefined,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
var deposits_1 = v3RelayHashes[relayDataHash].deposits;
|
|
402
|
+
assert(isDefined(deposits_1) && deposits_1.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
403
|
+
deposits_1.push(deposit);
|
|
404
|
+
}
|
|
405
|
+
// Account for duplicate deposits by concatenating the relayDataHash with the count of the number of times
|
|
406
|
+
// we have seen it so far.
|
|
407
|
+
var deposits = v3RelayHashes[relayDataHash].deposits;
|
|
408
|
+
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
409
|
+
var newBundleDepositHash = "".concat(relayDataHash, "@").concat(deposits.length - 1);
|
|
410
|
+
var decodedBundleDepositHash = decodeBundleDepositHash(newBundleDepositHash);
|
|
411
|
+
assert(decodedBundleDepositHash.relayDataHash === relayDataHash &&
|
|
412
|
+
decodedBundleDepositHash.index === deposits.length - 1, "Not using correct bundle deposit hash key");
|
|
413
|
+
if (deposit.blockNumber >= originChainBlockRange[0]) {
|
|
414
|
+
if ((_b = (_a = bundleDepositsV3 === null || bundleDepositsV3 === void 0 ? void 0 : bundleDepositsV3[originChainId]) === null || _a === void 0 ? void 0 : _a[deposit.inputToken.toBytes32()]) === null || _b === void 0 ? void 0 : _b.find(function (d) {
|
|
415
|
+
return duplicateEvent(deposit, d);
|
|
416
|
+
})) {
|
|
417
|
+
_this.logger.debug({
|
|
418
|
+
at: "BundleDataClient#loadData",
|
|
419
|
+
message: "Duplicate deposit detected",
|
|
420
|
+
deposit: convertRelayDataParamsToBytes32(deposit),
|
|
421
|
+
});
|
|
422
|
+
throw new Error("Duplicate deposit detected");
|
|
423
|
+
}
|
|
424
|
+
bundleDepositHashes.push(newBundleDepositHash);
|
|
425
|
+
updateBundleDepositsV3(bundleDepositsV3, deposit);
|
|
426
|
+
}
|
|
427
|
+
else if (deposit.blockNumber < originChainBlockRange[0]) {
|
|
428
|
+
olderDepositHashes.push(newBundleDepositHash);
|
|
429
|
+
}
|
|
545
430
|
});
|
|
546
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
547
|
-
// No need to check for duplicate deposits here since duplicate deposits with
|
|
548
|
-
// infinite deadlines are impossible to send via unsafeDeposit().
|
|
549
|
-
}
|
|
550
|
-
if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
551
|
-
_canCreateSlowFillLeaf(matchedDeposit)) {
|
|
552
|
-
fastFillsReplacingSlowFills.push(relayDataHash);
|
|
553
431
|
}
|
|
432
|
+
};
|
|
433
|
+
// Prerequisite step: Load all deposit events from the current or older bundles into the v3RelayHashes dictionary
|
|
434
|
+
// for convenient matching with fills.
|
|
435
|
+
for (_i = 0, allChainIds_1 = allChainIds; _i < allChainIds_1.length; _i++) {
|
|
436
|
+
originChainId = allChainIds_1[_i];
|
|
437
|
+
_loop_1(originChainId);
|
|
554
438
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
439
|
+
this.logger.debug({
|
|
440
|
+
at: "BundleDataClient#loadData",
|
|
441
|
+
message: "Processed ".concat(bundleDepositHashes.length + olderDepositHashes.length, " deposits in ").concat(performance.now() - start, "ms."),
|
|
442
|
+
});
|
|
443
|
+
start = performance.now();
|
|
444
|
+
validatedBundleV3Fills = [];
|
|
445
|
+
validatedBundleSlowFills = [];
|
|
446
|
+
validatedBundleUnexecutableSlowFills = [];
|
|
447
|
+
fillCounter = 0;
|
|
448
|
+
_loop_2 = function (originChainId) {
|
|
449
|
+
var originClient, _loop_3, _f, allChainIds_4, destinationChainId;
|
|
450
|
+
return __generator(this, function (_g) {
|
|
451
|
+
switch (_g.label) {
|
|
452
|
+
case 0:
|
|
453
|
+
originClient = spokePoolClients[originChainId];
|
|
454
|
+
_loop_3 = function (destinationChainId) {
|
|
455
|
+
var destinationClient, destinationChainBlockRange, originChainBlockRange, fastFillsReplacingSlowFills;
|
|
456
|
+
return __generator(this, function (_h) {
|
|
457
|
+
switch (_h.label) {
|
|
458
|
+
case 0:
|
|
459
|
+
destinationClient = spokePoolClients[destinationChainId];
|
|
460
|
+
destinationChainBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
461
|
+
originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
462
|
+
fastFillsReplacingSlowFills = [];
|
|
463
|
+
return [4 /*yield*/, forEachAsync(destinationClient
|
|
464
|
+
.getFillsForOriginChain(originChainId)
|
|
465
|
+
// We can remove fills for deposits with input amount equal to zero because these will result in 0 refunded
|
|
466
|
+
// tokens to the filler. We can't remove non-empty message deposit here in case there is a slow fill
|
|
467
|
+
// request for the deposit, we'd want to see the fill took place.
|
|
468
|
+
.filter(function (fill) {
|
|
469
|
+
return fill.blockNumber <= destinationChainBlockRange[1] &&
|
|
470
|
+
!isZeroValueFillOrSlowFillRequest(fill) &&
|
|
471
|
+
!invalidOutputToken(fill);
|
|
472
|
+
}), function (fill) { return __awaiter(_this, void 0, void 0, function () {
|
|
473
|
+
var relayDataHash, deposits, provider, fillToRefund_1, duplicateDeposits, historicalDeposit, matchedDeposit, provider, fillToRefund;
|
|
474
|
+
return __generator(this, function (_a) {
|
|
475
|
+
switch (_a.label) {
|
|
476
|
+
case 0:
|
|
477
|
+
fillCounter++;
|
|
478
|
+
relayDataHash = getRelayEventKey(fill);
|
|
479
|
+
if (!v3RelayHashes[relayDataHash]) return [3 /*break*/, 5];
|
|
480
|
+
if (!!v3RelayHashes[relayDataHash].fill) return [3 /*break*/, 3];
|
|
481
|
+
deposits = v3RelayHashes[relayDataHash].deposits;
|
|
482
|
+
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
483
|
+
v3RelayHashes[relayDataHash].fill = fill;
|
|
484
|
+
if (!(fill.blockNumber >= destinationChainBlockRange[0])) return [3 /*break*/, 2];
|
|
485
|
+
provider = void 0;
|
|
486
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
487
|
+
provider = destinationClient.spokePool.provider;
|
|
488
|
+
}
|
|
489
|
+
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
490
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
491
|
+
}
|
|
492
|
+
return [4 /*yield*/, verifyFillRepayment(fill, provider, deposits[0], this.clients.hubPoolClient, bundleEndBlockForMainnet)];
|
|
493
|
+
case 1:
|
|
494
|
+
fillToRefund_1 = _a.sent();
|
|
495
|
+
if (!isDefined(fillToRefund_1)) {
|
|
496
|
+
bundleUnrepayableFillsV3.push(fill);
|
|
497
|
+
// We don't return here yet because we still need to mark unexecutable slow fill leaves
|
|
498
|
+
// or duplicate deposits. However, we won't issue a fast fill refund.
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
v3RelayHashes[relayDataHash].fill = fillToRefund_1;
|
|
502
|
+
validatedBundleV3Fills.push(__assign(__assign({}, fillToRefund_1), { quoteTimestamp: deposits[0].quoteTimestamp }));
|
|
503
|
+
duplicateDeposits = deposits.slice(1);
|
|
504
|
+
duplicateDeposits.forEach(function (duplicateDeposit) {
|
|
505
|
+
if (isSlowFill(fill)) {
|
|
506
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, duplicateDeposit);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
validatedBundleV3Fills.push(__assign(__assign({}, fillToRefund_1), { quoteTimestamp: duplicateDeposit.quoteTimestamp }));
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
// If fill replaced a slow fill request, then mark it as one that might have created an
|
|
514
|
+
// unexecutable slow fill. We can't know for sure until we check the slow fill request
|
|
515
|
+
// events.
|
|
516
|
+
if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
517
|
+
_canCreateSlowFillLeaf(deposits[0])) {
|
|
518
|
+
fastFillsReplacingSlowFills.push(relayDataHash);
|
|
519
|
+
}
|
|
520
|
+
_a.label = 2;
|
|
521
|
+
case 2: return [3 /*break*/, 4];
|
|
522
|
+
case 3:
|
|
523
|
+
this.logger.debug({
|
|
524
|
+
at: "BundleDataClient#loadData",
|
|
525
|
+
message: "Duplicate fill detected",
|
|
526
|
+
fill: convertFillParamsToBytes32(fill),
|
|
527
|
+
});
|
|
528
|
+
throw new Error("Duplicate fill detected");
|
|
529
|
+
case 4: return [2 /*return*/];
|
|
530
|
+
case 5:
|
|
531
|
+
// At this point, there is no relay hash dictionary entry for this fill, so we need to
|
|
532
|
+
// instantiate the entry. We won't modify the fill.relayer until we match it with a deposit.
|
|
533
|
+
v3RelayHashes[relayDataHash] = {
|
|
534
|
+
deposits: undefined,
|
|
535
|
+
fill: fill,
|
|
536
|
+
slowFillRequest: undefined,
|
|
537
|
+
};
|
|
538
|
+
if (!(fill.blockNumber >= destinationChainBlockRange[0])) return [3 /*break*/, 9];
|
|
539
|
+
// Fill has a non-infinite expiry, and we can assume our spoke pool clients have old enough deposits
|
|
540
|
+
// to conclude that this fill is invalid if we haven't found a matching deposit in memory, so
|
|
541
|
+
// skip the historical query.
|
|
542
|
+
if (!INFINITE_FILL_DEADLINE.eq(fill.fillDeadline)) {
|
|
543
|
+
bundleInvalidFillsV3.push(fill);
|
|
544
|
+
return [2 /*return*/];
|
|
545
|
+
}
|
|
546
|
+
return [4 /*yield*/, queryHistoricalDepositForFill(originClient, fill)];
|
|
547
|
+
case 6:
|
|
548
|
+
historicalDeposit = _a.sent();
|
|
549
|
+
if (!!historicalDeposit.found) return [3 /*break*/, 7];
|
|
550
|
+
bundleInvalidFillsV3.push(fill);
|
|
551
|
+
return [3 /*break*/, 9];
|
|
552
|
+
case 7:
|
|
553
|
+
matchedDeposit = historicalDeposit.deposit;
|
|
554
|
+
// If deposit is in a following bundle, then this fill will have to be refunded once that deposit
|
|
555
|
+
// is in the current bundle.
|
|
556
|
+
if (matchedDeposit.blockNumber > originChainBlockRange[1]) {
|
|
557
|
+
bundleInvalidFillsV3.push(fill);
|
|
558
|
+
return [2 /*return*/];
|
|
559
|
+
}
|
|
560
|
+
v3RelayHashes[relayDataHash].deposits = [matchedDeposit];
|
|
561
|
+
provider = void 0;
|
|
562
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
563
|
+
provider = destinationClient.spokePool.provider;
|
|
564
|
+
}
|
|
565
|
+
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
566
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
567
|
+
}
|
|
568
|
+
return [4 /*yield*/, verifyFillRepayment(fill, provider, matchedDeposit, this.clients.hubPoolClient, bundleEndBlockForMainnet)];
|
|
569
|
+
case 8:
|
|
570
|
+
fillToRefund = _a.sent();
|
|
571
|
+
if (!isDefined(fillToRefund)) {
|
|
572
|
+
bundleUnrepayableFillsV3.push(fill);
|
|
573
|
+
// Don't return yet as we still need to mark down any unexecutable slow fill leaves
|
|
574
|
+
// in case this fast fill replaced a slow fill request.
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
// @dev Since queryHistoricalDepositForFill validates the fill by checking individual
|
|
578
|
+
// object property values against the deposit's, we
|
|
579
|
+
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
580
|
+
// historical deposit query is not working as expected.
|
|
581
|
+
assert(getRelayEventKey(matchedDeposit) === relayDataHash, "Relay hashes should match.");
|
|
582
|
+
validatedBundleV3Fills.push(__assign(__assign({}, fillToRefund), { quoteTimestamp: matchedDeposit.quoteTimestamp }));
|
|
583
|
+
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
584
|
+
// No need to check for duplicate deposits here since duplicate deposits with
|
|
585
|
+
// infinite deadlines are impossible to send via unsafeDeposit().
|
|
586
|
+
}
|
|
587
|
+
if (fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
588
|
+
_canCreateSlowFillLeaf(matchedDeposit)) {
|
|
589
|
+
fastFillsReplacingSlowFills.push(relayDataHash);
|
|
590
|
+
}
|
|
591
|
+
_a.label = 9;
|
|
592
|
+
case 9: return [2 /*return*/];
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
}); })];
|
|
596
|
+
case 1:
|
|
597
|
+
_h.sent();
|
|
598
|
+
// Process slow fill requests and produce slow fill leaves while maintaining the following the invariants:
|
|
599
|
+
// - Slow fill leaves cannot be produced for deposits that have expired in this bundle.
|
|
600
|
+
// - Slow fill leaves cannot be produced for deposits that have been filled.
|
|
601
|
+
// Assumptions about fills:
|
|
602
|
+
// - Duplicate slow fill requests for the same relay data hash are impossible to send.
|
|
603
|
+
// - Slow fill requests can only be sent before the deposit's fillDeadline.
|
|
604
|
+
// - Slow fill requests for a deposit that has been filled.
|
|
605
|
+
return [4 /*yield*/, forEachAsync(destinationClient
|
|
606
|
+
.getSlowFillRequestsForOriginChain(originChainId)
|
|
607
|
+
.filter(function (request) {
|
|
608
|
+
return request.blockNumber <= destinationChainBlockRange[1] &&
|
|
609
|
+
!isZeroValueFillOrSlowFillRequest(request) &&
|
|
610
|
+
!invalidOutputToken(request);
|
|
611
|
+
}), function (slowFillRequest) { return __awaiter(_this, void 0, void 0, function () {
|
|
612
|
+
var relayDataHash, _a, deposits, fill, matchedDeposit, historicalDeposit, matchedDeposit;
|
|
613
|
+
return __generator(this, function (_b) {
|
|
614
|
+
switch (_b.label) {
|
|
615
|
+
case 0:
|
|
616
|
+
relayDataHash = getRelayEventKey(slowFillRequest);
|
|
617
|
+
if (v3RelayHashes[relayDataHash]) {
|
|
618
|
+
if (!v3RelayHashes[relayDataHash].slowFillRequest) {
|
|
619
|
+
v3RelayHashes[relayDataHash].slowFillRequest = slowFillRequest;
|
|
620
|
+
_a = v3RelayHashes[relayDataHash], deposits = _a.deposits, fill = _a.fill;
|
|
621
|
+
if (fill) {
|
|
622
|
+
// Exiting here assumes that slow fill requests must precede fills, so if there was a fill
|
|
623
|
+
// following this slow fill request, then we would have already seen it. We don't need to check
|
|
624
|
+
// for a fill older than this slow fill request.
|
|
625
|
+
return [2 /*return*/];
|
|
626
|
+
}
|
|
627
|
+
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
628
|
+
matchedDeposit = deposits[0];
|
|
629
|
+
if (slowFillRequest.blockNumber >= destinationChainBlockRange[0] &&
|
|
630
|
+
_canCreateSlowFillLeaf(matchedDeposit) &&
|
|
631
|
+
!_depositIsExpired(matchedDeposit)) {
|
|
632
|
+
validatedBundleSlowFills.push(matchedDeposit);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
this.logger.debug({
|
|
637
|
+
at: "BundleDataClient#loadData",
|
|
638
|
+
message: "Duplicate slow fill request detected",
|
|
639
|
+
slowFillRequest: slowFillRequest,
|
|
640
|
+
});
|
|
641
|
+
throw new Error("Duplicate slow fill request detected.");
|
|
642
|
+
}
|
|
643
|
+
return [2 /*return*/];
|
|
644
|
+
}
|
|
645
|
+
// Instantiate dictionary if there is neither a deposit nor fill matching it.
|
|
646
|
+
v3RelayHashes[relayDataHash] = {
|
|
647
|
+
deposits: undefined,
|
|
648
|
+
fill: undefined,
|
|
649
|
+
slowFillRequest: slowFillRequest,
|
|
650
|
+
};
|
|
651
|
+
if (!(slowFillRequest.blockNumber >= destinationChainBlockRange[0])) return [3 /*break*/, 2];
|
|
652
|
+
if (!INFINITE_FILL_DEADLINE.eq(slowFillRequest.fillDeadline)) {
|
|
653
|
+
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
654
|
+
return [2 /*return*/];
|
|
655
|
+
}
|
|
656
|
+
return [4 /*yield*/, queryHistoricalDepositForFill(originClient, slowFillRequest)];
|
|
657
|
+
case 1:
|
|
658
|
+
historicalDeposit = _b.sent();
|
|
659
|
+
if (!historicalDeposit.found) {
|
|
660
|
+
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
661
|
+
return [2 /*return*/];
|
|
662
|
+
}
|
|
663
|
+
matchedDeposit = historicalDeposit.deposit;
|
|
664
|
+
// If deposit is in a following bundle, then this slow fill request will have to be created
|
|
665
|
+
// once that deposit is in the current bundle.
|
|
666
|
+
if (matchedDeposit.blockNumber > originChainBlockRange[1]) {
|
|
667
|
+
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
668
|
+
return [2 /*return*/];
|
|
669
|
+
}
|
|
670
|
+
// @dev Since queryHistoricalDepositForFill validates the slow fill request by checking individual
|
|
671
|
+
// object property values against the deposit's, we
|
|
672
|
+
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
673
|
+
// historical deposit query is not working as expected.
|
|
674
|
+
assert(getRelayEventKey(matchedDeposit) === relayDataHash, "Deposit relay hashes should match.");
|
|
675
|
+
v3RelayHashes[relayDataHash].deposits = [matchedDeposit];
|
|
676
|
+
if (!_canCreateSlowFillLeaf(matchedDeposit) || _depositIsExpired(matchedDeposit)) {
|
|
677
|
+
return [2 /*return*/];
|
|
678
|
+
}
|
|
679
|
+
validatedBundleSlowFills.push(matchedDeposit);
|
|
680
|
+
_b.label = 2;
|
|
681
|
+
case 2: return [2 /*return*/];
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
}); })];
|
|
685
|
+
case 2:
|
|
686
|
+
// Process slow fill requests and produce slow fill leaves while maintaining the following the invariants:
|
|
687
|
+
// - Slow fill leaves cannot be produced for deposits that have expired in this bundle.
|
|
688
|
+
// - Slow fill leaves cannot be produced for deposits that have been filled.
|
|
689
|
+
// Assumptions about fills:
|
|
690
|
+
// - Duplicate slow fill requests for the same relay data hash are impossible to send.
|
|
691
|
+
// - Slow fill requests can only be sent before the deposit's fillDeadline.
|
|
692
|
+
// - Slow fill requests for a deposit that has been filled.
|
|
693
|
+
_h.sent();
|
|
694
|
+
// Process deposits and maintain the following invariants:
|
|
695
|
+
// - Deposits matching fills that are not type SlowFill from previous bundle block ranges should produce
|
|
696
|
+
// refunds for those fills.
|
|
697
|
+
// - Deposits matching fills that are type SlowFill from previous bundle block ranges should be refunded to the
|
|
698
|
+
// depositor.
|
|
699
|
+
// - All deposits expiring in this bundle, even those sent in prior bundle block ranges, should be refunded
|
|
700
|
+
// to the depositor.
|
|
701
|
+
// - An expired deposit cannot be refunded if the deposit was filled.
|
|
702
|
+
// - If a deposit from a prior bundle expired in this bundle, had a slow fill request created for it
|
|
703
|
+
// in a prior bundle, and has not been filled yet, then an unexecutable slow fill leaf has been created
|
|
704
|
+
// and needs to be refunded to the HubPool.
|
|
705
|
+
// - Deposits matching slow fill requests from previous bundle block ranges should produce slow fills
|
|
706
|
+
// if the deposit has not been filled.
|
|
707
|
+
// Assumptions:
|
|
708
|
+
// - If the deposit has a matching fill or slow fill request in the bundle then we have already stored
|
|
709
|
+
// it in the relay hashes dictionary.
|
|
710
|
+
// - We've created refunds for all fills in this bundle matching a deposit.
|
|
711
|
+
// - We've created slow fill leaves for all slow fill requests in this bundle matching an unfilled deposit.
|
|
712
|
+
// - Deposits for the same relay data hash can be sent an arbitrary amount of times.
|
|
713
|
+
// - Deposits can be sent an arbitrary amount of time after a fill has been sent for the matching relay data.
|
|
714
|
+
return [4 /*yield*/, mapAsync(bundleDepositHashes, function (depositHash) { return __awaiter(_this, void 0, void 0, function () {
|
|
715
|
+
var _a, relayDataHash, index, _b, deposits, fill, slowFillRequest, deposit, provider, fillToRefund, fillStatus, prefill, provider, verifiedFill;
|
|
716
|
+
return __generator(this, function (_c) {
|
|
717
|
+
switch (_c.label) {
|
|
718
|
+
case 0:
|
|
719
|
+
_a = decodeBundleDepositHash(depositHash), relayDataHash = _a.relayDataHash, index = _a.index;
|
|
720
|
+
_b = v3RelayHashes[relayDataHash], deposits = _b.deposits, fill = _b.fill, slowFillRequest = _b.slowFillRequest;
|
|
721
|
+
if (!deposits || deposits.length === 0) {
|
|
722
|
+
throw new Error("Deposits should exist in relay hash dictionary.");
|
|
723
|
+
}
|
|
724
|
+
deposit = deposits[index];
|
|
725
|
+
if (!deposit)
|
|
726
|
+
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
727
|
+
if (deposit.originChainId !== originChainId || deposit.destinationChainId !== destinationChainId) {
|
|
728
|
+
return [2 /*return*/];
|
|
729
|
+
}
|
|
730
|
+
if (!fill) return [3 /*break*/, 3];
|
|
731
|
+
if (!(fill.blockNumber < destinationChainBlockRange[0])) return [3 /*break*/, 2];
|
|
732
|
+
provider = void 0;
|
|
733
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
734
|
+
provider = destinationClient.spokePool.provider;
|
|
735
|
+
}
|
|
736
|
+
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
737
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
738
|
+
}
|
|
739
|
+
return [4 /*yield*/, verifyFillRepayment(fill, provider, deposits[0], this.clients.hubPoolClient, bundleEndBlockForMainnet)];
|
|
740
|
+
case 1:
|
|
741
|
+
fillToRefund = _c.sent();
|
|
742
|
+
if (!isDefined(fillToRefund)) {
|
|
743
|
+
bundleUnrepayableFillsV3.push(fill);
|
|
744
|
+
}
|
|
745
|
+
else if (!isSlowFill(fill)) {
|
|
746
|
+
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
747
|
+
validatedBundleV3Fills.push(__assign(__assign({}, fillToRefund), { quoteTimestamp: deposit.quoteTimestamp }));
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
751
|
+
}
|
|
752
|
+
_c.label = 2;
|
|
753
|
+
case 2: return [2 /*return*/];
|
|
754
|
+
case 3:
|
|
755
|
+
// If a slow fill request exists in memory, then we know the deposit has not been filled because fills
|
|
756
|
+
// must follow slow fill requests and we would have seen the fill already if it existed.,
|
|
757
|
+
// We can conclude that either the deposit has expired or we need to create a slow fill leaf for the
|
|
758
|
+
// deposit because it has not been filled. Slow fill leaves were already created for requests sent
|
|
759
|
+
// in the current bundle so only create new slow fill leaves for prior bundle deposits.
|
|
760
|
+
if (slowFillRequest) {
|
|
761
|
+
if (_depositIsExpired(deposit)) {
|
|
762
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
763
|
+
}
|
|
764
|
+
else if (slowFillRequest.blockNumber < destinationChainBlockRange[0] &&
|
|
765
|
+
_canCreateSlowFillLeaf(deposit) &&
|
|
766
|
+
validatedBundleSlowFills.every(function (d) { return getRelayEventKey(d) !== relayDataHash; })) {
|
|
767
|
+
validatedBundleSlowFills.push(deposit);
|
|
768
|
+
}
|
|
769
|
+
return [2 /*return*/];
|
|
770
|
+
}
|
|
771
|
+
return [4 /*yield*/, _getFillStatusForDeposit(deposit, destinationChainBlockRange[1])];
|
|
772
|
+
case 4:
|
|
773
|
+
fillStatus = _c.sent();
|
|
774
|
+
if (!(fillStatus === FillStatus.Filled)) return [3 /*break*/, 7];
|
|
775
|
+
return [4 /*yield*/, this.findMatchingFillEvent(deposit, destinationClient)];
|
|
776
|
+
case 5:
|
|
777
|
+
prefill = _c.sent();
|
|
778
|
+
assert(isDefined(prefill), "findFillEvent# Cannot find prefill: ".concat(relayDataHash));
|
|
779
|
+
assert(getRelayEventKey(prefill) === relayDataHash, "Relay hashes should match.");
|
|
780
|
+
provider = void 0;
|
|
781
|
+
if (isEVMSpokePoolClient(destinationClient)) {
|
|
782
|
+
provider = destinationClient.spokePool.provider;
|
|
783
|
+
}
|
|
784
|
+
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
785
|
+
provider = destinationClient.svmEventsClient.getRpc();
|
|
786
|
+
}
|
|
787
|
+
return [4 /*yield*/, verifyFillRepayment(prefill, provider, deposit, this.clients.hubPoolClient, bundleEndBlockForMainnet)];
|
|
788
|
+
case 6:
|
|
789
|
+
verifiedFill = _c.sent();
|
|
790
|
+
if (!isDefined(verifiedFill)) {
|
|
791
|
+
bundleUnrepayableFillsV3.push(prefill);
|
|
792
|
+
}
|
|
793
|
+
else if (!isSlowFill(verifiedFill)) {
|
|
794
|
+
validatedBundleV3Fills.push(__assign(__assign({}, verifiedFill), { quoteTimestamp: deposit.quoteTimestamp }));
|
|
795
|
+
}
|
|
796
|
+
else {
|
|
797
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
798
|
+
}
|
|
799
|
+
return [3 /*break*/, 8];
|
|
800
|
+
case 7:
|
|
801
|
+
if (_depositIsExpired(deposit)) {
|
|
802
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
803
|
+
}
|
|
804
|
+
else if (fillStatus === FillStatus.RequestedSlowFill &&
|
|
805
|
+
// Don't create duplicate slow fill requests for the same deposit.
|
|
806
|
+
validatedBundleSlowFills.every(function (d) { return getRelayEventKey(d) !== relayDataHash; })) {
|
|
807
|
+
if (_canCreateSlowFillLeaf(deposit)) {
|
|
808
|
+
validatedBundleSlowFills.push(deposit);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
_c.label = 8;
|
|
812
|
+
case 8: return [2 /*return*/];
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
}); })];
|
|
816
|
+
case 3:
|
|
817
|
+
// Process deposits and maintain the following invariants:
|
|
818
|
+
// - Deposits matching fills that are not type SlowFill from previous bundle block ranges should produce
|
|
819
|
+
// refunds for those fills.
|
|
820
|
+
// - Deposits matching fills that are type SlowFill from previous bundle block ranges should be refunded to the
|
|
821
|
+
// depositor.
|
|
822
|
+
// - All deposits expiring in this bundle, even those sent in prior bundle block ranges, should be refunded
|
|
823
|
+
// to the depositor.
|
|
824
|
+
// - An expired deposit cannot be refunded if the deposit was filled.
|
|
825
|
+
// - If a deposit from a prior bundle expired in this bundle, had a slow fill request created for it
|
|
826
|
+
// in a prior bundle, and has not been filled yet, then an unexecutable slow fill leaf has been created
|
|
827
|
+
// and needs to be refunded to the HubPool.
|
|
828
|
+
// - Deposits matching slow fill requests from previous bundle block ranges should produce slow fills
|
|
829
|
+
// if the deposit has not been filled.
|
|
830
|
+
// Assumptions:
|
|
831
|
+
// - If the deposit has a matching fill or slow fill request in the bundle then we have already stored
|
|
832
|
+
// it in the relay hashes dictionary.
|
|
833
|
+
// - We've created refunds for all fills in this bundle matching a deposit.
|
|
834
|
+
// - We've created slow fill leaves for all slow fill requests in this bundle matching an unfilled deposit.
|
|
835
|
+
// - Deposits for the same relay data hash can be sent an arbitrary amount of times.
|
|
836
|
+
// - Deposits can be sent an arbitrary amount of time after a fill has been sent for the matching relay data.
|
|
837
|
+
_h.sent();
|
|
838
|
+
// For all fills that came after a slow fill request, we can now check if the slow fill request
|
|
839
|
+
// was a valid one and whether it was created in a previous bundle. If so, then it created a slow fill
|
|
840
|
+
// leaf that is now unexecutable.
|
|
841
|
+
fastFillsReplacingSlowFills.forEach(function (relayDataHash) {
|
|
842
|
+
var _a = v3RelayHashes[relayDataHash], deposits = _a.deposits, slowFillRequest = _a.slowFillRequest, fill = _a.fill;
|
|
843
|
+
assert((fill === null || fill === void 0 ? void 0 : fill.relayExecutionInfo.fillType) === FillType.ReplacedSlowFill, "Fill type should be ReplacedSlowFill.");
|
|
844
|
+
// Needed for TSC - are implicitly checking that deposit exists by making it to this point.
|
|
845
|
+
if (!deposits || deposits.length < 1) {
|
|
846
|
+
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
847
|
+
}
|
|
848
|
+
// We should never push fast fills involving lite chains here because slow fill requests for them are invalid:
|
|
849
|
+
assert(_canCreateSlowFillLeaf(deposits[0]), "fastFillsReplacingSlowFills should contain only deposits that can be slow filled");
|
|
850
|
+
var destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
851
|
+
var originBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
852
|
+
var matchedDeposit = deposits[0];
|
|
853
|
+
// For a slow fill leaf to have been created (and subsequently create an excess), the deposit matching the
|
|
854
|
+
// slow fill request must have been included in a previous bundle AND the slow fill request should not
|
|
855
|
+
// be included in this bundle. This is because a slow fill request is only valid once its deposit
|
|
856
|
+
// has been mined, so if the deposit is not in a prior bundle to the fill, then no slow fill leaf could
|
|
857
|
+
// have been created. Secondly, the slow fill request itself must have occurred in an older bundle than the
|
|
858
|
+
// fill otherwise the slow fill leaf be unexecutable for an already-filled deposit..
|
|
859
|
+
if (matchedDeposit.blockNumber < originBlockRange[0] &&
|
|
860
|
+
// If there is a slow fill request in this bundle that matches the relay hash, then there was no slow fill
|
|
861
|
+
// created that would be considered excess.
|
|
862
|
+
(!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0])) {
|
|
863
|
+
validatedBundleUnexecutableSlowFills.push(deposits[0]);
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
return [2 /*return*/];
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
};
|
|
870
|
+
_f = 0, allChainIds_4 = allChainIds;
|
|
871
|
+
_g.label = 1;
|
|
872
|
+
case 1:
|
|
873
|
+
if (!(_f < allChainIds_4.length)) return [3 /*break*/, 4];
|
|
874
|
+
destinationChainId = allChainIds_4[_f];
|
|
875
|
+
return [5 /*yield**/, _loop_3(destinationChainId)];
|
|
876
|
+
case 2:
|
|
877
|
+
_g.sent();
|
|
878
|
+
_g.label = 3;
|
|
879
|
+
case 3:
|
|
880
|
+
_f++;
|
|
881
|
+
return [3 /*break*/, 1];
|
|
882
|
+
case 4: return [2 /*return*/];
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
};
|
|
886
|
+
_b = 0, allChainIds_2 = allChainIds;
|
|
887
|
+
_d.label = 4;
|
|
888
|
+
case 4:
|
|
889
|
+
if (!(_b < allChainIds_2.length)) return [3 /*break*/, 7];
|
|
890
|
+
originChainId = allChainIds_2[_b];
|
|
891
|
+
return [5 /*yield**/, _loop_2(originChainId)];
|
|
892
|
+
case 5:
|
|
893
|
+
_d.sent();
|
|
894
|
+
_d.label = 6;
|
|
895
|
+
case 6:
|
|
896
|
+
_b++;
|
|
897
|
+
return [3 /*break*/, 4];
|
|
898
|
+
case 7:
|
|
899
|
+
this.logger.debug({
|
|
900
|
+
at: "BundleDataClient#loadData",
|
|
901
|
+
message: "Processed ".concat(fillCounter, " fills in ").concat(performance.now() - start, "ms."),
|
|
902
|
+
});
|
|
903
|
+
start = performance.now();
|
|
904
|
+
// For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
|
|
905
|
+
// whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
|
|
906
|
+
// by a new expired deposit refund.
|
|
907
|
+
return [4 /*yield*/, forEachAsync(olderDepositHashes, function (depositHash) { return __awaiter(_this, void 0, void 0, function () {
|
|
908
|
+
var _a, relayDataHash, index, _b, deposits, slowFillRequest, fill, deposit, destinationChainId, destinationBlockRange, fillStatus;
|
|
909
|
+
return __generator(this, function (_c) {
|
|
910
|
+
switch (_c.label) {
|
|
911
|
+
case 0:
|
|
912
|
+
_a = decodeBundleDepositHash(depositHash), relayDataHash = _a.relayDataHash, index = _a.index;
|
|
913
|
+
_b = v3RelayHashes[relayDataHash], deposits = _b.deposits, slowFillRequest = _b.slowFillRequest, fill = _b.fill;
|
|
914
|
+
if (!deposits || deposits.length < 1) {
|
|
915
|
+
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
916
|
+
}
|
|
917
|
+
deposit = deposits[index];
|
|
918
|
+
destinationChainId = deposit.destinationChainId;
|
|
919
|
+
destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
920
|
+
if (!
|
|
921
|
+
// If there is a valid fill that we saw matching this deposit, then it does not need a refund.
|
|
922
|
+
(!fill &&
|
|
923
|
+
isDefined(deposit) && // Needed for TSC - we check this above.
|
|
924
|
+
_depositIsExpired(deposit) &&
|
|
925
|
+
deposit.fillDeadline >= bundleBlockTimestamps[destinationChainId][0] &&
|
|
926
|
+
spokePoolClients[destinationChainId] !== undefined))
|
|
927
|
+
// If there is a valid fill that we saw matching this deposit, then it does not need a refund.
|
|
928
|
+
return [3 /*break*/, 2];
|
|
929
|
+
return [4 /*yield*/, _getFillStatusForDeposit(deposit, destinationBlockRange[1])];
|
|
930
|
+
case 1:
|
|
931
|
+
fillStatus = _c.sent();
|
|
932
|
+
// If there is no matching fill and the deposit expired in this bundle and the fill status on-chain is not
|
|
933
|
+
// Filled, then we can to refund it as an expired deposit.
|
|
934
|
+
if (fillStatus !== FillStatus.Filled) {
|
|
935
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
936
|
+
}
|
|
937
|
+
// If fill status is RequestedSlowFill, then we might need to mark down an unexecutable
|
|
938
|
+
// slow fill that we're going to replace with an expired deposit refund.
|
|
939
|
+
// If deposit cannot be slow filled, then exit early.
|
|
940
|
+
if (fillStatus !== FillStatus.RequestedSlowFill || !_canCreateSlowFillLeaf(deposit)) {
|
|
941
|
+
return [2 /*return*/];
|
|
942
|
+
}
|
|
943
|
+
// Now, check if there was a slow fill created for this deposit in a previous bundle which would now be
|
|
944
|
+
// unexecutable. Mark this deposit as having created an unexecutable slow fill if there is no matching
|
|
945
|
+
// slow fill request or the matching slow fill request took place in a previous bundle.
|
|
946
|
+
// If there is a slow fill request in this bundle, then the expired deposit refund will supersede
|
|
947
|
+
// the slow fill request. If there is no slow fill request seen or its older than this bundle, then we can
|
|
948
|
+
// assume a slow fill leaf was created for it when the deposit was mined. Therefore, because the deposit
|
|
949
|
+
// was in an older bundle, we can assume that a slow fill leaf was created at that time and therefore
|
|
950
|
+
// is now unexecutable.
|
|
951
|
+
if (!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0]) {
|
|
952
|
+
validatedBundleUnexecutableSlowFills.push(deposit);
|
|
953
|
+
}
|
|
954
|
+
_c.label = 2;
|
|
955
|
+
case 2: return [2 /*return*/];
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
}); })];
|
|
959
|
+
case 8:
|
|
960
|
+
// For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
|
|
961
|
+
// whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
|
|
962
|
+
// by a new expired deposit refund.
|
|
963
|
+
_d.sent();
|
|
964
|
+
// Batch compute V3 lp fees.
|
|
965
|
+
start = performance.now();
|
|
966
|
+
promises = [
|
|
967
|
+
validatedBundleV3Fills.length > 0
|
|
968
|
+
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleV3Fills.map(function (fill) {
|
|
969
|
+
var deposits = v3RelayHashes[getRelayEventKey(fill)].deposits;
|
|
970
|
+
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
971
|
+
var matchedDeposit = deposits[0];
|
|
972
|
+
assert(isDefined(matchedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
973
|
+
var paymentChainId = getRefundInformationFromFill(__assign(__assign({}, fill), { fromLiteChain: matchedDeposit.fromLiteChain }), _this.clients.hubPoolClient, bundleEndBlockForMainnet).chainToSendRefundTo;
|
|
974
|
+
return __assign(__assign({}, fill), { paymentChainId: paymentChainId });
|
|
975
|
+
}))
|
|
976
|
+
: [],
|
|
977
|
+
validatedBundleSlowFills.length > 0
|
|
978
|
+
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleSlowFills.map(function (deposit) {
|
|
979
|
+
return __assign(__assign({}, deposit), { paymentChainId: deposit.destinationChainId });
|
|
980
|
+
}))
|
|
981
|
+
: [],
|
|
982
|
+
validatedBundleUnexecutableSlowFills.length > 0
|
|
983
|
+
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleUnexecutableSlowFills.map(function (deposit) {
|
|
984
|
+
return __assign(__assign({}, deposit), { paymentChainId: deposit.destinationChainId });
|
|
985
|
+
}))
|
|
986
|
+
: [],
|
|
987
|
+
];
|
|
988
|
+
return [4 /*yield*/, Promise.all(promises)];
|
|
989
|
+
case 9:
|
|
990
|
+
_c = _d.sent(), v3FillLpFees = _c[0], v3SlowFillLpFees = _c[1], v3UnexecutableSlowFillLpFees = _c[2];
|
|
991
|
+
this.logger.debug({
|
|
992
|
+
at: "BundleDataClient#loadData",
|
|
993
|
+
message: "Computed batch async LP fees in ".concat(performance.now() - start, "ms."),
|
|
994
|
+
});
|
|
995
|
+
v3FillLpFees.forEach(function (_a, idx) {
|
|
996
|
+
var realizedLpFeePct = _a.realizedLpFeePct;
|
|
997
|
+
var fill = validatedBundleV3Fills[idx];
|
|
998
|
+
var deposits = v3RelayHashes[getRelayEventKey(fill)].deposits;
|
|
580
999
|
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
1000
|
+
var associatedDeposit = deposits[0];
|
|
1001
|
+
assert(isDefined(associatedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
1002
|
+
var _b = getRefundInformationFromFill(__assign(__assign({}, fill), { fromLiteChain: associatedDeposit.fromLiteChain }), _this.clients.hubPoolClient, bundleEndBlockForMainnet), chainToSendRefundTo = _b.chainToSendRefundTo, repaymentToken = _b.repaymentToken;
|
|
1003
|
+
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken, fill.relayer);
|
|
1004
|
+
});
|
|
1005
|
+
v3SlowFillLpFees.forEach(function (_a, idx) {
|
|
1006
|
+
var lpFeePct = _a.realizedLpFeePct;
|
|
1007
|
+
var deposit = validatedBundleSlowFills[idx];
|
|
1008
|
+
// We should not create slow fill leaves for duplicate deposit hashes and we should only create a slow
|
|
1009
|
+
// fill leaf for the first deposit (the quote timestamp of the deposit determines the LP fee, so its
|
|
1010
|
+
// important we pick out the correct deposit). Deposits are pushed into validatedBundleSlowFills in ascending
|
|
1011
|
+
// order so the following slice will only match the first deposit.
|
|
1012
|
+
var relayDataHash = getRelayEventKey(deposit);
|
|
1013
|
+
if (validatedBundleSlowFills.slice(0, idx).some(function (d) { return getRelayEventKey(d) === relayDataHash; })) {
|
|
1014
|
+
return;
|
|
586
1015
|
}
|
|
587
|
-
|
|
588
|
-
|
|
1016
|
+
assert(!_depositIsExpired(deposit), "Cannot create slow fill leaf for expired deposit.");
|
|
1017
|
+
updateBundleSlowFills(bundleSlowFillsV3, __assign(__assign({}, deposit), { lpFeePct: lpFeePct }));
|
|
1018
|
+
});
|
|
1019
|
+
v3UnexecutableSlowFillLpFees.forEach(function (_a, idx) {
|
|
1020
|
+
var lpFeePct = _a.realizedLpFeePct;
|
|
1021
|
+
var deposit = validatedBundleUnexecutableSlowFills[idx];
|
|
1022
|
+
updateBundleExcessSlowFills(unexecutableSlowFills, __assign(__assign({}, deposit), { lpFeePct: lpFeePct }));
|
|
1023
|
+
});
|
|
1024
|
+
v3SpokeEventsReadable = prettyPrintV3SpokePoolEvents(bundleDepositsV3, bundleFillsV3, bundleSlowFillsV3, expiredDepositsToRefundV3, unexecutableSlowFills);
|
|
1025
|
+
if (bundleInvalidFillsV3.length > 0) {
|
|
1026
|
+
invalidFillsWithPartialMatchedDeposits_1 = [];
|
|
1027
|
+
preFillsForNextBundle_1 = [];
|
|
1028
|
+
unknownReasonInvalidFills_1 = [];
|
|
1029
|
+
bundleInvalidFillsV3.forEach(function (fill) {
|
|
1030
|
+
var originClient = spokePoolClients[fill.originChainId];
|
|
1031
|
+
var fullyMatchedDeposit = originClient.getDepositForFill(fill);
|
|
1032
|
+
if (!isDefined(fullyMatchedDeposit)) {
|
|
1033
|
+
var partiallyMatchedDeposit = originClient.getDeposit(fill.depositId);
|
|
1034
|
+
if (isDefined(partiallyMatchedDeposit)) {
|
|
1035
|
+
invalidFillsWithPartialMatchedDeposits_1.push(fill);
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
unknownReasonInvalidFills_1.push(fill);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
else {
|
|
1042
|
+
var originBundleBlockRange = getBlockRangeForChain(blockRangesForChains, fill.originChainId, chainIds);
|
|
1043
|
+
if (fullyMatchedDeposit.blockNumber <= originBundleBlockRange[1]) {
|
|
1044
|
+
throw new Error("Detected invalid fill that matches fully with a deposit in current or prior bundle");
|
|
1045
|
+
}
|
|
1046
|
+
preFillsForNextBundle_1.push(fill);
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
589
1049
|
this.logger.debug({
|
|
590
1050
|
at: "BundleDataClient#loadData",
|
|
591
|
-
message: "
|
|
592
|
-
|
|
1051
|
+
message: "Finished loading V3 spoke pool data and found some invalid fills in range",
|
|
1052
|
+
blockRangesForChains: blockRangesForChains,
|
|
1053
|
+
invalidFillsWithPartialMatchedDeposits: invalidFillsWithPartialMatchedDeposits_1.map(function (invalidFill) {
|
|
1054
|
+
return convertFillParamsToBytes32(invalidFill);
|
|
1055
|
+
}),
|
|
1056
|
+
preFillsForNextBundle: preFillsForNextBundle_1.map(function (preFill) { return convertFillParamsToBytes32(preFill); }),
|
|
1057
|
+
unknownReasonInvalidFills: unknownReasonInvalidFills_1.map(function (invalidFill) {
|
|
1058
|
+
return convertFillParamsToBytes32(invalidFill);
|
|
1059
|
+
}),
|
|
593
1060
|
});
|
|
594
|
-
throw new Error("Duplicate slow fill request detected.");
|
|
595
|
-
}
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
// Instantiate dictionary if there is neither a deposit nor fill matching it.
|
|
599
|
-
v3RelayHashes[relayDataHash] = {
|
|
600
|
-
deposits: undefined,
|
|
601
|
-
fill: undefined,
|
|
602
|
-
slowFillRequest: slowFillRequest,
|
|
603
|
-
};
|
|
604
|
-
// TODO: We can remove the following historical query once we deprecate the deposit()
|
|
605
|
-
// function since there won't be any old, unexpired deposits anymore assuming the spoke pool client
|
|
606
|
-
// lookbacks have been validated, which they should be before we run this function.
|
|
607
|
-
// Since there was no deposit matching the relay hash, we need to do a historical query for an
|
|
608
|
-
// older deposit in case the spoke pool client's lookback isn't old enough to find the matching deposit.
|
|
609
|
-
// We can skip this step if the deposit's fill deadline is not infinite, because we can assume that the
|
|
610
|
-
// spoke pool clients have loaded deposits old enough to cover all fills with a non-infinite fill deadline.
|
|
611
|
-
// We do not need to handle the case where the deposit ID is > uint32 (in which case we wouldn't
|
|
612
|
-
// want to perform a binary search lookup for it because the deposit ID is "unsafe" and cannot be
|
|
613
|
-
// found using such a method) because infinite fill deadlines cannot be produced from the unsafeDepositV3()
|
|
614
|
-
// function.
|
|
615
|
-
if (slowFillRequest.blockNumber >= destinationChainBlockRange[0]) {
|
|
616
|
-
if (!INFINITE_FILL_DEADLINE.eq(slowFillRequest.fillDeadline)) {
|
|
617
|
-
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
const historicalDeposit = await queryHistoricalDepositForFill(originClient, slowFillRequest);
|
|
621
|
-
if (!historicalDeposit.found) {
|
|
622
|
-
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
623
|
-
return;
|
|
624
|
-
}
|
|
625
|
-
const matchedDeposit = historicalDeposit.deposit;
|
|
626
|
-
// If deposit is in a following bundle, then this slow fill request will have to be created
|
|
627
|
-
// once that deposit is in the current bundle.
|
|
628
|
-
if (matchedDeposit.blockNumber > originChainBlockRange[1]) {
|
|
629
|
-
bundleInvalidSlowFillRequests.push(slowFillRequest);
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
// @dev Since queryHistoricalDepositForFill validates the slow fill request by checking individual
|
|
633
|
-
// object property values against the deposit's, we
|
|
634
|
-
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
635
|
-
// historical deposit query is not working as expected.
|
|
636
|
-
assert(getRelayEventKey(matchedDeposit) === relayDataHash, "Deposit relay hashes should match.");
|
|
637
|
-
v3RelayHashes[relayDataHash].deposits = [matchedDeposit];
|
|
638
|
-
if (!_canCreateSlowFillLeaf(matchedDeposit) || _depositIsExpired(matchedDeposit)) {
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
validatedBundleSlowFills.push(matchedDeposit);
|
|
642
|
-
}
|
|
643
|
-
});
|
|
644
|
-
// Process deposits and maintain the following invariants:
|
|
645
|
-
// - Deposits matching fills that are not type SlowFill from previous bundle block ranges should produce
|
|
646
|
-
// refunds for those fills.
|
|
647
|
-
// - Deposits matching fills that are type SlowFill from previous bundle block ranges should be refunded to the
|
|
648
|
-
// depositor.
|
|
649
|
-
// - All deposits expiring in this bundle, even those sent in prior bundle block ranges, should be refunded
|
|
650
|
-
// to the depositor.
|
|
651
|
-
// - An expired deposit cannot be refunded if the deposit was filled.
|
|
652
|
-
// - If a deposit from a prior bundle expired in this bundle, had a slow fill request created for it
|
|
653
|
-
// in a prior bundle, and has not been filled yet, then an unexecutable slow fill leaf has been created
|
|
654
|
-
// and needs to be refunded to the HubPool.
|
|
655
|
-
// - Deposits matching slow fill requests from previous bundle block ranges should produce slow fills
|
|
656
|
-
// if the deposit has not been filled.
|
|
657
|
-
// Assumptions:
|
|
658
|
-
// - If the deposit has a matching fill or slow fill request in the bundle then we have already stored
|
|
659
|
-
// it in the relay hashes dictionary.
|
|
660
|
-
// - We've created refunds for all fills in this bundle matching a deposit.
|
|
661
|
-
// - We've created slow fill leaves for all slow fill requests in this bundle matching an unfilled deposit.
|
|
662
|
-
// - Deposits for the same relay data hash can be sent an arbitrary amount of times.
|
|
663
|
-
// - Deposits can be sent an arbitrary amount of time after a fill has been sent for the matching relay data.
|
|
664
|
-
await mapAsync(bundleDepositHashes, async (depositHash) => {
|
|
665
|
-
const { relayDataHash, index } = decodeBundleDepositHash(depositHash);
|
|
666
|
-
const { deposits, fill, slowFillRequest } = v3RelayHashes[relayDataHash];
|
|
667
|
-
if (!deposits || deposits.length === 0) {
|
|
668
|
-
throw new Error("Deposits should exist in relay hash dictionary.");
|
|
669
|
-
}
|
|
670
|
-
const deposit = deposits[index];
|
|
671
|
-
if (!deposit)
|
|
672
|
-
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
673
|
-
if (deposit.originChainId !== originChainId || deposit.destinationChainId !== destinationChainId) {
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
// If fill is in the current bundle then we can assume there is already a refund for it, so only
|
|
677
|
-
// include this pre fill if the fill is in an older bundle.
|
|
678
|
-
if (fill) {
|
|
679
|
-
if (fill.blockNumber < destinationChainBlockRange[0]) {
|
|
680
|
-
let provider;
|
|
681
|
-
if (isEVMSpokePoolClient(destinationClient)) {
|
|
682
|
-
provider = destinationClient.spokePool.provider;
|
|
683
|
-
}
|
|
684
|
-
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
685
|
-
provider = destinationClient.svmEventsClient.getRpc();
|
|
686
|
-
}
|
|
687
|
-
const fillToRefund = await verifyFillRepayment(fill, provider, deposits[0], this.clients.hubPoolClient, bundleEndBlockForMainnet);
|
|
688
|
-
if (!isDefined(fillToRefund)) {
|
|
689
|
-
bundleUnrepayableFillsV3.push(fill);
|
|
690
|
-
}
|
|
691
|
-
else if (!isSlowFill(fill)) {
|
|
692
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
693
|
-
validatedBundleV3Fills.push({
|
|
694
|
-
...fillToRefund,
|
|
695
|
-
quoteTimestamp: deposit.quoteTimestamp,
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
// If a slow fill request exists in memory, then we know the deposit has not been filled because fills
|
|
705
|
-
// must follow slow fill requests and we would have seen the fill already if it existed.,
|
|
706
|
-
// We can conclude that either the deposit has expired or we need to create a slow fill leaf for the
|
|
707
|
-
// deposit because it has not been filled. Slow fill leaves were already created for requests sent
|
|
708
|
-
// in the current bundle so only create new slow fill leaves for prior bundle deposits.
|
|
709
|
-
if (slowFillRequest) {
|
|
710
|
-
if (_depositIsExpired(deposit)) {
|
|
711
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
712
|
-
}
|
|
713
|
-
else if (slowFillRequest.blockNumber < destinationChainBlockRange[0] &&
|
|
714
|
-
_canCreateSlowFillLeaf(deposit) &&
|
|
715
|
-
validatedBundleSlowFills.every((d) => getRelayEventKey(d) !== relayDataHash)) {
|
|
716
|
-
validatedBundleSlowFills.push(deposit);
|
|
717
|
-
}
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
// So at this point in the code, there is no fill or slow fill request in memory for this deposit.
|
|
721
|
-
// We need to check its fill status on-chain to figure out whether to issue a refund or a slow fill leaf.
|
|
722
|
-
// We can assume at this point that all fills or slow fill requests, if found, were in previous bundles
|
|
723
|
-
// because the spoke pool client lookback would have returned this entire bundle of events and stored
|
|
724
|
-
// them into the relay hash dictionary.
|
|
725
|
-
const fillStatus = await _getFillStatusForDeposit(deposit, destinationChainBlockRange[1]);
|
|
726
|
-
if (fillStatus === FillStatus.Filled) {
|
|
727
|
-
// We don't need to verify the fill block is before the bundle end block on the destination chain because
|
|
728
|
-
// we queried the fillStatus at the end block. Therefore, if the fill took place after the end block,
|
|
729
|
-
// then we wouldn't be in this branch of the code.
|
|
730
|
-
const prefill = await this.findMatchingFillEvent(deposit, destinationClient);
|
|
731
|
-
assert(isDefined(prefill), `findFillEvent# Cannot find prefill: ${relayDataHash}`);
|
|
732
|
-
assert(getRelayEventKey(prefill) === relayDataHash, "Relay hashes should match.");
|
|
733
|
-
let provider;
|
|
734
|
-
if (isEVMSpokePoolClient(destinationClient)) {
|
|
735
|
-
provider = destinationClient.spokePool.provider;
|
|
736
|
-
}
|
|
737
|
-
else if (isSVMSpokePoolClient(destinationClient)) {
|
|
738
|
-
provider = destinationClient.svmEventsClient.getRpc();
|
|
739
1061
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
...verifiedFill,
|
|
747
|
-
quoteTimestamp: deposit.quoteTimestamp,
|
|
1062
|
+
if (bundleUnrepayableFillsV3.length > 0) {
|
|
1063
|
+
this.logger.debug({
|
|
1064
|
+
at: "BundleDataClient#loadData",
|
|
1065
|
+
message: "Finished loading V3 spoke pool data and found some unrepayable fills in range",
|
|
1066
|
+
blockRangesForChains: blockRangesForChains,
|
|
1067
|
+
bundleUnrepayableFillsV3: bundleUnrepayableFillsV3,
|
|
748
1068
|
});
|
|
749
1069
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
else if (fillStatus === FillStatus.RequestedSlowFill &&
|
|
758
|
-
// Don't create duplicate slow fill requests for the same deposit.
|
|
759
|
-
validatedBundleSlowFills.every((d) => getRelayEventKey(d) !== relayDataHash)) {
|
|
760
|
-
if (_canCreateSlowFillLeaf(deposit)) {
|
|
761
|
-
validatedBundleSlowFills.push(deposit);
|
|
1070
|
+
if (bundleInvalidSlowFillRequests.length > 0) {
|
|
1071
|
+
this.logger.debug({
|
|
1072
|
+
at: "BundleDataClient#loadData",
|
|
1073
|
+
message: "Finished loading V3 spoke pool data and found some invalid slow fill requests in range",
|
|
1074
|
+
blockRangesForChains: blockRangesForChains,
|
|
1075
|
+
bundleInvalidSlowFillRequests: bundleInvalidSlowFillRequests,
|
|
1076
|
+
});
|
|
762
1077
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
assert(_canCreateSlowFillLeaf(deposits[0]), "fastFillsReplacingSlowFills should contain only deposits that can be slow filled");
|
|
777
|
-
const destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
778
|
-
const originBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
779
|
-
const matchedDeposit = deposits[0];
|
|
780
|
-
// For a slow fill leaf to have been created (and subsequently create an excess), the deposit matching the
|
|
781
|
-
// slow fill request must have been included in a previous bundle AND the slow fill request should not
|
|
782
|
-
// be included in this bundle. This is because a slow fill request is only valid once its deposit
|
|
783
|
-
// has been mined, so if the deposit is not in a prior bundle to the fill, then no slow fill leaf could
|
|
784
|
-
// have been created. Secondly, the slow fill request itself must have occurred in an older bundle than the
|
|
785
|
-
// fill otherwise the slow fill leaf be unexecutable for an already-filled deposit..
|
|
786
|
-
if (matchedDeposit.blockNumber < originBlockRange[0] &&
|
|
787
|
-
// If there is a slow fill request in this bundle that matches the relay hash, then there was no slow fill
|
|
788
|
-
// created that would be considered excess.
|
|
789
|
-
(!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0])) {
|
|
790
|
-
validatedBundleUnexecutableSlowFills.push(deposits[0]);
|
|
791
|
-
}
|
|
792
|
-
});
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
this.logger.debug({
|
|
796
|
-
at: "BundleDataClient#loadData",
|
|
797
|
-
message: `Processed ${fillCounter} fills in ${performance.now() - start}ms.`,
|
|
798
|
-
});
|
|
799
|
-
start = performance.now();
|
|
800
|
-
// For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
|
|
801
|
-
// whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
|
|
802
|
-
// by a new expired deposit refund.
|
|
803
|
-
await forEachAsync(olderDepositHashes, async (depositHash) => {
|
|
804
|
-
const { relayDataHash, index } = decodeBundleDepositHash(depositHash);
|
|
805
|
-
const { deposits, slowFillRequest, fill } = v3RelayHashes[relayDataHash];
|
|
806
|
-
if (!deposits || deposits.length < 1) {
|
|
807
|
-
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
808
|
-
}
|
|
809
|
-
const deposit = deposits[index];
|
|
810
|
-
const { destinationChainId } = deposit;
|
|
811
|
-
const destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
812
|
-
// Only look for deposits that were mined before this bundle and that are newly expired.
|
|
813
|
-
// If the fill deadline is lower than the bundle start block on the destination chain, then
|
|
814
|
-
// we should assume it was refunded in a previous bundle.
|
|
815
|
-
if (
|
|
816
|
-
// If there is a valid fill that we saw matching this deposit, then it does not need a refund.
|
|
817
|
-
!fill &&
|
|
818
|
-
isDefined(deposit) && // Needed for TSC - we check this above.
|
|
819
|
-
_depositIsExpired(deposit) &&
|
|
820
|
-
deposit.fillDeadline >= bundleBlockTimestamps[destinationChainId][0] &&
|
|
821
|
-
spokePoolClients[destinationChainId] !== undefined) {
|
|
822
|
-
// If we haven't seen a fill matching this deposit, then we need to rule out that it was filled a long time ago
|
|
823
|
-
// by checkings its on-chain fill status.
|
|
824
|
-
const fillStatus = await _getFillStatusForDeposit(deposit, destinationBlockRange[1]);
|
|
825
|
-
// If there is no matching fill and the deposit expired in this bundle and the fill status on-chain is not
|
|
826
|
-
// Filled, then we can to refund it as an expired deposit.
|
|
827
|
-
if (fillStatus !== FillStatus.Filled) {
|
|
828
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
1078
|
+
this.logger.debug({
|
|
1079
|
+
at: "BundleDataClient#loadDataFromScratch",
|
|
1080
|
+
message: "Computed bundle data in ".concat(Math.round(performance.now() - start) / 1000, "s."),
|
|
1081
|
+
blockRangesForChains: JSON.stringify(blockRangesForChains),
|
|
1082
|
+
v3SpokeEventsReadable: v3SpokeEventsReadable,
|
|
1083
|
+
});
|
|
1084
|
+
return [2 /*return*/, {
|
|
1085
|
+
bundleDepositsV3: bundleDepositsV3,
|
|
1086
|
+
expiredDepositsToRefundV3: expiredDepositsToRefundV3,
|
|
1087
|
+
bundleFillsV3: bundleFillsV3,
|
|
1088
|
+
unexecutableSlowFills: unexecutableSlowFills,
|
|
1089
|
+
bundleSlowFillsV3: bundleSlowFillsV3,
|
|
1090
|
+
}];
|
|
829
1091
|
}
|
|
830
|
-
|
|
831
|
-
// slow fill that we're going to replace with an expired deposit refund.
|
|
832
|
-
// If deposit cannot be slow filled, then exit early.
|
|
833
|
-
if (fillStatus !== FillStatus.RequestedSlowFill || !_canCreateSlowFillLeaf(deposit)) {
|
|
834
|
-
return;
|
|
835
|
-
}
|
|
836
|
-
// Now, check if there was a slow fill created for this deposit in a previous bundle which would now be
|
|
837
|
-
// unexecutable. Mark this deposit as having created an unexecutable slow fill if there is no matching
|
|
838
|
-
// slow fill request or the matching slow fill request took place in a previous bundle.
|
|
839
|
-
// If there is a slow fill request in this bundle, then the expired deposit refund will supersede
|
|
840
|
-
// the slow fill request. If there is no slow fill request seen or its older than this bundle, then we can
|
|
841
|
-
// assume a slow fill leaf was created for it when the deposit was mined. Therefore, because the deposit
|
|
842
|
-
// was in an older bundle, we can assume that a slow fill leaf was created at that time and therefore
|
|
843
|
-
// is now unexecutable.
|
|
844
|
-
if (!slowFillRequest || slowFillRequest.blockNumber < destinationBlockRange[0]) {
|
|
845
|
-
validatedBundleUnexecutableSlowFills.push(deposit);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
|
-
// Batch compute V3 lp fees.
|
|
850
|
-
start = performance.now();
|
|
851
|
-
const promises = [
|
|
852
|
-
validatedBundleV3Fills.length > 0
|
|
853
|
-
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleV3Fills.map((fill) => {
|
|
854
|
-
const { deposits } = v3RelayHashes[getRelayEventKey(fill)];
|
|
855
|
-
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
856
|
-
const matchedDeposit = deposits[0];
|
|
857
|
-
assert(isDefined(matchedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
858
|
-
const { chainToSendRefundTo: paymentChainId } = getRefundInformationFromFill({
|
|
859
|
-
...fill,
|
|
860
|
-
fromLiteChain: matchedDeposit.fromLiteChain,
|
|
861
|
-
}, this.clients.hubPoolClient, bundleEndBlockForMainnet);
|
|
862
|
-
return {
|
|
863
|
-
...fill,
|
|
864
|
-
paymentChainId,
|
|
865
|
-
};
|
|
866
|
-
}))
|
|
867
|
-
: [],
|
|
868
|
-
validatedBundleSlowFills.length > 0
|
|
869
|
-
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleSlowFills.map((deposit) => {
|
|
870
|
-
return {
|
|
871
|
-
...deposit,
|
|
872
|
-
paymentChainId: deposit.destinationChainId,
|
|
873
|
-
};
|
|
874
|
-
}))
|
|
875
|
-
: [],
|
|
876
|
-
validatedBundleUnexecutableSlowFills.length > 0
|
|
877
|
-
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(validatedBundleUnexecutableSlowFills.map((deposit) => {
|
|
878
|
-
return {
|
|
879
|
-
...deposit,
|
|
880
|
-
paymentChainId: deposit.destinationChainId,
|
|
881
|
-
};
|
|
882
|
-
}))
|
|
883
|
-
: [],
|
|
884
|
-
];
|
|
885
|
-
const [v3FillLpFees, v3SlowFillLpFees, v3UnexecutableSlowFillLpFees] = await Promise.all(promises);
|
|
886
|
-
this.logger.debug({
|
|
887
|
-
at: "BundleDataClient#loadData",
|
|
888
|
-
message: `Computed batch async LP fees in ${performance.now() - start}ms.`,
|
|
889
|
-
});
|
|
890
|
-
v3FillLpFees.forEach(({ realizedLpFeePct }, idx) => {
|
|
891
|
-
const fill = validatedBundleV3Fills[idx];
|
|
892
|
-
const { deposits } = v3RelayHashes[getRelayEventKey(fill)];
|
|
893
|
-
assert(isDefined(deposits) && deposits.length > 0, "Deposit should exist in relay hash dictionary.");
|
|
894
|
-
const associatedDeposit = deposits[0];
|
|
895
|
-
assert(isDefined(associatedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
896
|
-
const { chainToSendRefundTo, repaymentToken } = getRefundInformationFromFill({
|
|
897
|
-
...fill,
|
|
898
|
-
fromLiteChain: associatedDeposit.fromLiteChain,
|
|
899
|
-
}, this.clients.hubPoolClient, bundleEndBlockForMainnet);
|
|
900
|
-
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken, fill.relayer);
|
|
901
|
-
});
|
|
902
|
-
v3SlowFillLpFees.forEach(({ realizedLpFeePct: lpFeePct }, idx) => {
|
|
903
|
-
const deposit = validatedBundleSlowFills[idx];
|
|
904
|
-
// We should not create slow fill leaves for duplicate deposit hashes and we should only create a slow
|
|
905
|
-
// fill leaf for the first deposit (the quote timestamp of the deposit determines the LP fee, so its
|
|
906
|
-
// important we pick out the correct deposit). Deposits are pushed into validatedBundleSlowFills in ascending
|
|
907
|
-
// order so the following slice will only match the first deposit.
|
|
908
|
-
const relayDataHash = getRelayEventKey(deposit);
|
|
909
|
-
if (validatedBundleSlowFills.slice(0, idx).some((d) => getRelayEventKey(d) === relayDataHash)) {
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
assert(!_depositIsExpired(deposit), "Cannot create slow fill leaf for expired deposit.");
|
|
913
|
-
updateBundleSlowFills(bundleSlowFillsV3, { ...deposit, lpFeePct });
|
|
914
|
-
});
|
|
915
|
-
v3UnexecutableSlowFillLpFees.forEach(({ realizedLpFeePct: lpFeePct }, idx) => {
|
|
916
|
-
const deposit = validatedBundleUnexecutableSlowFills[idx];
|
|
917
|
-
updateBundleExcessSlowFills(unexecutableSlowFills, { ...deposit, lpFeePct });
|
|
1092
|
+
});
|
|
918
1093
|
});
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
const partiallyMatchedDeposit = originClient.getDeposit(fill.depositId);
|
|
934
|
-
if (isDefined(partiallyMatchedDeposit)) {
|
|
935
|
-
invalidFillsWithPartialMatchedDeposits.push(fill);
|
|
936
|
-
}
|
|
937
|
-
else {
|
|
938
|
-
unknownReasonInvalidFills.push(fill);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
else {
|
|
942
|
-
const originBundleBlockRange = getBlockRangeForChain(blockRangesForChains, fill.originChainId, chainIds);
|
|
943
|
-
if (fullyMatchedDeposit.blockNumber <= originBundleBlockRange[1]) {
|
|
944
|
-
throw new Error("Detected invalid fill that matches fully with a deposit in current or prior bundle");
|
|
945
|
-
}
|
|
946
|
-
preFillsForNextBundle.push(fill);
|
|
1094
|
+
};
|
|
1095
|
+
BundleDataClient.prototype.findMatchingFillEvent = function (deposit, spokePoolClient) {
|
|
1096
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1097
|
+
return __generator(this, function (_a) {
|
|
1098
|
+
switch (_a.label) {
|
|
1099
|
+
case 0:
|
|
1100
|
+
if (!isSVMSpokePoolClient(spokePoolClient)) return [3 /*break*/, 2];
|
|
1101
|
+
return [4 /*yield*/, findSvmFillEvent(deposit, spokePoolClient.chainId, spokePoolClient.svmEventsClient, spokePoolClient.deploymentBlock, spokePoolClient.latestHeightSearched, spokePoolClient.logger)];
|
|
1102
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1103
|
+
case 2:
|
|
1104
|
+
if (!isEVMSpokePoolClient(spokePoolClient)) return [3 /*break*/, 4];
|
|
1105
|
+
return [4 /*yield*/, findEvmFillEvent(spokePoolClient.spokePool, deposit, spokePoolClient.deploymentBlock, spokePoolClient.latestHeightSearched)];
|
|
1106
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
1107
|
+
case 4: throw new Error("Unsupported spoke pool client type");
|
|
947
1108
|
}
|
|
948
1109
|
});
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1110
|
+
});
|
|
1111
|
+
};
|
|
1112
|
+
BundleDataClient.prototype.getBundleBlockTimestamps = function (chainIds, blockRangesForChains, spokePoolClients) {
|
|
1113
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1114
|
+
var _a, _b;
|
|
1115
|
+
var _this = this;
|
|
1116
|
+
return __generator(this, function (_c) {
|
|
1117
|
+
switch (_c.label) {
|
|
1118
|
+
case 0:
|
|
1119
|
+
_b = (_a = Object).fromEntries;
|
|
1120
|
+
return [4 /*yield*/, mapAsync(chainIds, function (chainId, index) { return __awaiter(_this, void 0, void 0, function () {
|
|
1121
|
+
var blockRangeForChain, _startBlockForChain, _endBlockForChain, spokePoolClient, startBlockForChain, endBlockForChain, _a, startTime, _endTime, _b, endBlockDelta, endTime;
|
|
1122
|
+
return __generator(this, function (_c) {
|
|
1123
|
+
switch (_c.label) {
|
|
1124
|
+
case 0:
|
|
1125
|
+
blockRangeForChain = blockRangesForChains[index];
|
|
1126
|
+
if (!isDefined(blockRangeForChain) ||
|
|
1127
|
+
isChainDisabledAtBlock(chainId, blockRangesForChains[0][0], this.clients.configStoreClient)) {
|
|
1128
|
+
return [2 /*return*/];
|
|
1129
|
+
}
|
|
1130
|
+
_startBlockForChain = blockRangeForChain[0], _endBlockForChain = blockRangeForChain[1];
|
|
1131
|
+
spokePoolClient = spokePoolClients[chainId];
|
|
1132
|
+
// Relayer instances using the BundleDataClient for repayment estimates may only relay on a subset of chains.
|
|
1133
|
+
if (!isDefined(spokePoolClient)) {
|
|
1134
|
+
return [2 /*return*/];
|
|
1135
|
+
}
|
|
1136
|
+
startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestHeightSearched);
|
|
1137
|
+
endBlockForChain = Math.min(_endBlockForChain + 1, spokePoolClient.latestHeightSearched);
|
|
1138
|
+
return [4 /*yield*/, spokePoolClient.getTimestampForBlock(startBlockForChain)];
|
|
1139
|
+
case 1:
|
|
1140
|
+
_b = [
|
|
1141
|
+
_c.sent()
|
|
1142
|
+
];
|
|
1143
|
+
return [4 /*yield*/, spokePoolClient.getTimestampForBlock(endBlockForChain)];
|
|
1144
|
+
case 2:
|
|
1145
|
+
_a = _b.concat([
|
|
1146
|
+
_c.sent()
|
|
1147
|
+
]), startTime = _a[0], _endTime = _a[1];
|
|
1148
|
+
endBlockDelta = endBlockForChain > startBlockForChain ? 1 : 0;
|
|
1149
|
+
endTime = Math.max(0, _endTime - endBlockDelta);
|
|
1150
|
+
// Sanity checks:
|
|
1151
|
+
assert(endTime >= startTime, "End time for block ".concat(endBlockForChain, " should be greater than start time for block ").concat(startBlockForChain, ": ").concat(endTime, " >= ").concat(startTime, "."));
|
|
1152
|
+
assert(startBlockForChain === 0 || startTime > 0, "Start timestamp must be greater than 0 if the start block is greater than 0.");
|
|
1153
|
+
return [2 /*return*/, [chainId, [startTime, endTime]]];
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
}); })];
|
|
1157
|
+
case 1: return [2 /*return*/, _b.apply(_a, [(_c.sent()).filter(isDefined)])];
|
|
1158
|
+
}
|
|
972
1159
|
});
|
|
973
|
-
}
|
|
974
|
-
this.logger.debug({
|
|
975
|
-
at: "BundleDataClient#loadDataFromScratch",
|
|
976
|
-
message: `Computed bundle data in ${Math.round(performance.now() - start) / 1000}s.`,
|
|
977
|
-
blockRangesForChains: JSON.stringify(blockRangesForChains),
|
|
978
|
-
v3SpokeEventsReadable,
|
|
979
1160
|
});
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
unexecutableSlowFills,
|
|
985
|
-
bundleSlowFillsV3,
|
|
986
|
-
};
|
|
987
|
-
}
|
|
988
|
-
async findMatchingFillEvent(deposit, spokePoolClient) {
|
|
989
|
-
if (isSVMSpokePoolClient(spokePoolClient)) {
|
|
990
|
-
return await findSvmFillEvent(deposit, spokePoolClient.chainId, spokePoolClient.svmEventsClient, spokePoolClient.deploymentBlock, spokePoolClient.latestHeightSearched, spokePoolClient.logger);
|
|
991
|
-
}
|
|
992
|
-
else if (isEVMSpokePoolClient(spokePoolClient)) {
|
|
993
|
-
return await findEvmFillEvent(spokePoolClient.spokePool, deposit, spokePoolClient.deploymentBlock, spokePoolClient.latestHeightSearched);
|
|
994
|
-
}
|
|
995
|
-
else {
|
|
996
|
-
throw new Error("Unsupported spoke pool client type");
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
async getBundleBlockTimestamps(chainIds, blockRangesForChains, spokePoolClients) {
|
|
1000
|
-
return Object.fromEntries((await mapAsync(chainIds, async (chainId, index) => {
|
|
1001
|
-
const blockRangeForChain = blockRangesForChains[index];
|
|
1002
|
-
if (!isDefined(blockRangeForChain) ||
|
|
1003
|
-
isChainDisabledAtBlock(chainId, blockRangesForChains[0][0], this.clients.configStoreClient)) {
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
const [_startBlockForChain, _endBlockForChain] = blockRangeForChain;
|
|
1007
|
-
const spokePoolClient = spokePoolClients[chainId];
|
|
1008
|
-
// Relayer instances using the BundleDataClient for repayment estimates may only relay on a subset of chains.
|
|
1009
|
-
if (!isDefined(spokePoolClient)) {
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
// We can assume that in production the block ranges passed into this function would never
|
|
1013
|
-
// contain blocks where the spoke pool client hasn't queried. This is because this function
|
|
1014
|
-
// will usually be called in production with block ranges that were validated by
|
|
1015
|
-
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
|
|
1016
|
-
const startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestHeightSearched);
|
|
1017
|
-
// @dev Add 1 to the bundle end block. The thinking here is that there can be a gap between
|
|
1018
|
-
// block timestamps in subsequent blocks. The bundle data client assumes that fill deadlines expire
|
|
1019
|
-
// in exactly one bundle, therefore we must make sure that the bundle block timestamp for one bundle's
|
|
1020
|
-
// end block is exactly equal to the bundle block timestamp for the next bundle's start block. This way
|
|
1021
|
-
// there are no gaps in block timestamps between bundles.
|
|
1022
|
-
const endBlockForChain = Math.min(_endBlockForChain + 1, spokePoolClient.latestHeightSearched);
|
|
1023
|
-
const [startTime, _endTime] = [
|
|
1024
|
-
await spokePoolClient.getTimestampForBlock(startBlockForChain),
|
|
1025
|
-
await spokePoolClient.getTimestampForBlock(endBlockForChain),
|
|
1026
|
-
];
|
|
1027
|
-
// @dev similar to reasoning above to ensure no gaps between bundle block range timestamps and also
|
|
1028
|
-
// no overlap, subtract 1 from the end time.
|
|
1029
|
-
const endBlockDelta = endBlockForChain > startBlockForChain ? 1 : 0;
|
|
1030
|
-
const endTime = Math.max(0, _endTime - endBlockDelta);
|
|
1031
|
-
// Sanity checks:
|
|
1032
|
-
assert(endTime >= startTime, `End time for block ${endBlockForChain} should be greater than start time for block ${startBlockForChain}: ${endTime} >= ${startTime}.`);
|
|
1033
|
-
assert(startBlockForChain === 0 || startTime > 0, "Start timestamp must be greater than 0 if the start block is greater than 0.");
|
|
1034
|
-
return [chainId, [startTime, endTime]];
|
|
1035
|
-
})).filter(isDefined));
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1161
|
+
};
|
|
1162
|
+
return BundleDataClient;
|
|
1163
|
+
}());
|
|
1164
|
+
export { BundleDataClient };
|
|
1038
1165
|
//# sourceMappingURL=BundleDataClient.js.map
|