@eth-optimism/actions-sdk 0.2.0 → 0.3.0
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/__mocks__/MockAssets.d.ts.map +1 -1
- package/dist/__mocks__/MockAssets.js +2 -0
- package/dist/__mocks__/MockAssets.js.map +1 -1
- package/dist/__tests__/actions.test.js +0 -4
- package/dist/__tests__/actions.test.js.map +1 -1
- package/dist/actions.d.ts +20 -1
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +37 -13
- package/dist/actions.js.map +1 -1
- package/dist/constants/assets.d.ts +4 -0
- package/dist/constants/assets.d.ts.map +1 -1
- package/dist/constants/assets.js +15 -0
- package/dist/constants/assets.js.map +1 -1
- package/dist/constants/contracts.d.ts +4 -0
- package/dist/constants/contracts.d.ts.map +1 -0
- package/dist/constants/contracts.js +3 -0
- package/dist/constants/contracts.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lend/core/LendProvider.d.ts +0 -6
- package/dist/lend/core/LendProvider.d.ts.map +1 -1
- package/dist/lend/core/LendProvider.js +6 -15
- package/dist/lend/core/LendProvider.js.map +1 -1
- package/dist/lend/core/__tests__/LendProvider.test.js +2 -4
- package/dist/lend/core/__tests__/LendProvider.test.js.map +1 -1
- package/dist/lend/providers/morpho/__tests__/sdk.test.js +3 -2
- package/dist/lend/providers/morpho/__tests__/sdk.test.js.map +1 -1
- package/dist/lend/providers/morpho/api.d.ts +4 -0
- package/dist/lend/providers/morpho/api.d.ts.map +1 -1
- package/dist/lend/providers/morpho/api.js.map +1 -1
- package/dist/lend/providers/morpho/sdk.d.ts.map +1 -1
- package/dist/lend/providers/morpho/sdk.js +10 -1
- package/dist/lend/providers/morpho/sdk.js.map +1 -1
- package/dist/supported/tokens.d.ts.map +1 -1
- package/dist/supported/tokens.js +9 -2
- package/dist/supported/tokens.js.map +1 -1
- package/dist/swap/__mocks__/MockSwapProvider.d.ts +38 -0
- package/dist/swap/__mocks__/MockSwapProvider.d.ts.map +1 -0
- package/dist/swap/__mocks__/MockSwapProvider.js +138 -0
- package/dist/swap/__mocks__/MockSwapProvider.js.map +1 -0
- package/dist/swap/core/SwapProvider.d.ts +56 -0
- package/dist/swap/core/SwapProvider.d.ts.map +1 -0
- package/dist/swap/core/SwapProvider.js +177 -0
- package/dist/swap/core/SwapProvider.js.map +1 -0
- package/dist/swap/core/__tests__/SwapProvider.test.d.ts +2 -0
- package/dist/swap/core/__tests__/SwapProvider.test.d.ts.map +1 -0
- package/dist/swap/core/__tests__/SwapProvider.test.js +329 -0
- package/dist/swap/core/__tests__/SwapProvider.test.js.map +1 -0
- package/dist/swap/index.d.ts +7 -0
- package/dist/swap/index.d.ts.map +1 -0
- package/dist/swap/index.js +8 -0
- package/dist/swap/index.js.map +1 -0
- package/dist/swap/namespaces/ActionsSwapNamespace.d.ts +8 -0
- package/dist/swap/namespaces/ActionsSwapNamespace.d.ts.map +1 -0
- package/dist/swap/namespaces/ActionsSwapNamespace.js +8 -0
- package/dist/swap/namespaces/ActionsSwapNamespace.js.map +1 -0
- package/dist/swap/namespaces/BaseSwapNamespace.d.ts +33 -0
- package/dist/swap/namespaces/BaseSwapNamespace.d.ts.map +1 -0
- package/dist/swap/namespaces/BaseSwapNamespace.js +58 -0
- package/dist/swap/namespaces/BaseSwapNamespace.js.map +1 -0
- package/dist/swap/namespaces/WalletSwapNamespace.d.ts +22 -0
- package/dist/swap/namespaces/WalletSwapNamespace.d.ts.map +1 -0
- package/dist/swap/namespaces/WalletSwapNamespace.js +60 -0
- package/dist/swap/namespaces/WalletSwapNamespace.js.map +1 -0
- package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.d.ts +2 -0
- package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.d.ts.map +1 -0
- package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.js +106 -0
- package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.js.map +1 -0
- package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.d.ts +2 -0
- package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.d.ts.map +1 -0
- package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.js +132 -0
- package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.js.map +1 -0
- package/dist/swap/providers/uniswap/UniswapSwapProvider.d.ts +68 -0
- package/dist/swap/providers/uniswap/UniswapSwapProvider.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/UniswapSwapProvider.js +206 -0
- package/dist/swap/providers/uniswap/UniswapSwapProvider.js.map +1 -0
- package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.d.ts +2 -0
- package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.js +257 -0
- package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.js.map +1 -0
- package/dist/swap/providers/uniswap/__tests__/sdk.test.d.ts +2 -0
- package/dist/swap/providers/uniswap/__tests__/sdk.test.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/__tests__/sdk.test.js +312 -0
- package/dist/swap/providers/uniswap/__tests__/sdk.test.js.map +1 -0
- package/dist/swap/providers/uniswap/abis.d.ts +227 -0
- package/dist/swap/providers/uniswap/abis.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/abis.js +138 -0
- package/dist/swap/providers/uniswap/abis.js.map +1 -0
- package/dist/swap/providers/uniswap/addresses.d.ts +21 -0
- package/dist/swap/providers/uniswap/addresses.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/addresses.js +81 -0
- package/dist/swap/providers/uniswap/addresses.js.map +1 -0
- package/dist/swap/providers/uniswap/encoding.d.ts +77 -0
- package/dist/swap/providers/uniswap/encoding.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/encoding.js +233 -0
- package/dist/swap/providers/uniswap/encoding.js.map +1 -0
- package/dist/swap/providers/uniswap/types.d.ts +20 -0
- package/dist/swap/providers/uniswap/types.d.ts.map +1 -0
- package/dist/swap/providers/uniswap/types.js +2 -0
- package/dist/swap/providers/uniswap/types.js.map +1 -0
- package/dist/types/actions.d.ts +19 -5
- package/dist/types/actions.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/lend/base.d.ts +3 -13
- package/dist/types/lend/base.d.ts.map +1 -1
- package/dist/types/lend/base.js.map +1 -1
- package/dist/types/swap/base.d.ts +238 -0
- package/dist/types/swap/base.d.ts.map +1 -0
- package/dist/types/swap/base.js +4 -0
- package/dist/types/swap/base.js.map +1 -0
- package/dist/types/swap/index.d.ts +2 -0
- package/dist/types/swap/index.d.ts.map +1 -0
- package/dist/types/swap/index.js +2 -0
- package/dist/types/swap/index.js.map +1 -0
- package/dist/types/transaction.d.ts +14 -0
- package/dist/types/transaction.d.ts.map +1 -0
- package/dist/types/transaction.js +2 -0
- package/dist/types/transaction.js.map +1 -0
- package/dist/utils/assets.d.ts +4 -5
- package/dist/utils/assets.d.ts.map +1 -1
- package/dist/utils/assets.js +4 -11
- package/dist/utils/assets.js.map +1 -1
- package/dist/utils/assets.test.js +13 -1
- package/dist/utils/assets.test.js.map +1 -1
- package/dist/utils/permit2.d.ts +46 -0
- package/dist/utils/permit2.d.ts.map +1 -0
- package/dist/utils/permit2.js +100 -0
- package/dist/utils/permit2.js.map +1 -0
- package/dist/utils/permit2.test.d.ts +2 -0
- package/dist/utils/permit2.test.d.ts.map +1 -0
- package/dist/utils/permit2.test.js +110 -0
- package/dist/utils/permit2.test.js.map +1 -0
- package/dist/utils/validation.d.ts +12 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +44 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts +7 -1
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js +2 -1
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js.map +1 -1
- package/dist/wallet/core/providers/hosted/types/index.d.ts +5 -1
- package/dist/wallet/core/providers/hosted/types/index.d.ts.map +1 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts +7 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts.map +1 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js +5 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js.map +1 -1
- package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js +2 -2
- package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js.map +1 -1
- package/dist/wallet/core/wallets/abstract/Wallet.d.ts +13 -2
- package/dist/wallet/core/wallets/abstract/Wallet.d.ts.map +1 -1
- package/dist/wallet/core/wallets/abstract/Wallet.js +7 -1
- package/dist/wallet/core/wallets/abstract/Wallet.js.map +1 -1
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts +7 -2
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts.map +1 -1
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js +6 -5
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js.map +1 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts +6 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js +3 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.d.ts.map +1 -1
- package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.js +4 -3
- package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.js.map +1 -1
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts +5 -1
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +4 -2
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts +6 -1
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts.map +1 -1
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js +4 -3
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js.map +1 -1
- package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.d.ts +5 -1
- package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.d.ts.map +1 -1
- package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.js +2 -2
- package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.js.map +1 -1
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.d.ts +7 -1
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js +6 -2
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.js +1 -0
- package/dist/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.js.map +1 -1
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.d.ts +6 -1
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js +5 -2
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js +1 -0
- package/dist/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js.map +1 -1
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts +6 -3
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +5 -4
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.d.ts.map +1 -1
- package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.js +6 -6
- package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.js.map +1 -1
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.d.ts +7 -1
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.d.ts.map +1 -1
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js +5 -3
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js.map +1 -1
- package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.d.ts +5 -1
- package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.d.ts.map +1 -1
- package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.js +3 -3
- package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.js.map +1 -1
- package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.d.ts +5 -1
- package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.d.ts.map +1 -1
- package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.js +2 -2
- package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.js.map +1 -1
- package/package.json +2 -2
- package/src/__mocks__/MockAssets.ts +2 -0
- package/src/__tests__/actions.test.ts +0 -4
- package/src/actions.ts +57 -19
- package/src/constants/assets.ts +16 -0
- package/src/constants/contracts.ts +5 -0
- package/src/index.ts +30 -2
- package/src/lend/core/LendProvider.ts +6 -18
- package/src/lend/core/__tests__/LendProvider.test.ts +2 -5
- package/src/lend/providers/morpho/__tests__/sdk.test.ts +3 -2
- package/src/lend/providers/morpho/api.ts +4 -0
- package/src/lend/providers/morpho/sdk.ts +10 -1
- package/src/supported/tokens.ts +16 -2
- package/src/swap/__mocks__/MockSwapProvider.ts +216 -0
- package/src/swap/core/SwapProvider.ts +319 -0
- package/src/swap/core/__tests__/SwapProvider.test.ts +478 -0
- package/src/swap/index.ts +14 -0
- package/src/swap/namespaces/ActionsSwapNamespace.ts +7 -0
- package/src/swap/namespaces/BaseSwapNamespace.ts +77 -0
- package/src/swap/namespaces/WalletSwapNamespace.ts +82 -0
- package/src/swap/namespaces/__tests__/BaseSwapNamespace.spec.ts +138 -0
- package/src/swap/namespaces/__tests__/WalletSwapNamespace.spec.ts +162 -0
- package/src/swap/providers/uniswap/UniswapSwapProvider.ts +304 -0
- package/src/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.ts +299 -0
- package/src/swap/providers/uniswap/__tests__/sdk.test.ts +370 -0
- package/src/swap/providers/uniswap/abis.ts +144 -0
- package/src/swap/providers/uniswap/addresses.ts +108 -0
- package/src/swap/providers/uniswap/encoding.ts +406 -0
- package/src/swap/providers/uniswap/types.ts +24 -0
- package/src/types/actions.ts +22 -6
- package/src/types/index.ts +2 -0
- package/src/types/lend/base.ts +4 -14
- package/src/types/swap/base.ts +259 -0
- package/src/types/swap/index.ts +1 -0
- package/src/types/transaction.ts +14 -0
- package/src/utils/assets.test.ts +16 -1
- package/src/utils/assets.ts +13 -10
- package/src/utils/permit2.test.ts +142 -0
- package/src/utils/permit2.ts +144 -0
- package/src/utils/validation.ts +76 -0
- package/src/wallet/core/providers/hosted/abstract/HostedWalletProvider.ts +9 -1
- package/src/wallet/core/providers/hosted/types/index.ts +5 -1
- package/src/wallet/core/providers/smart/default/DefaultSmartWalletProvider.ts +13 -1
- package/src/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.ts +2 -0
- package/src/wallet/core/wallets/abstract/Wallet.ts +18 -2
- package/src/wallet/core/wallets/smart/default/DefaultSmartWallet.ts +14 -5
- package/src/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.ts +13 -2
- package/src/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.ts +10 -2
- package/src/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +8 -2
- package/src/wallet/node/wallets/hosted/privy/PrivyWallet.ts +11 -2
- package/src/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.ts +10 -2
- package/src/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.ts +10 -2
- package/src/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.ts +1 -0
- package/src/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.ts +9 -2
- package/src/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.ts +1 -0
- package/src/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +9 -4
- package/src/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.ts +18 -6
- package/src/wallet/react/wallets/hosted/dynamic/DynamicWallet.ts +12 -2
- package/src/wallet/react/wallets/hosted/privy/PrivyWallet.ts +10 -2
- package/src/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.ts +10 -2
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
TransactionData,
|
|
22
22
|
} from '@/types/lend/index.js'
|
|
23
23
|
import { validateMarketAsset } from '@/utils/markets.js'
|
|
24
|
+
import { validateChainSupported } from '@/utils/validation.js'
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Lending provider abstract class
|
|
@@ -77,7 +78,7 @@ export abstract class LendProvider<
|
|
|
77
78
|
throw new Error('walletAddress is required')
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
validateChainSupported(params.marketId.chainId, this.SUPPORTED_CHAIN_IDS)
|
|
81
82
|
this.validateConfigSupported(params.marketId)
|
|
82
83
|
|
|
83
84
|
// Convert human-readable amount to wei using the asset's decimals
|
|
@@ -105,7 +106,7 @@ export abstract class LendProvider<
|
|
|
105
106
|
chainId: params.chainId,
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
validateChainSupported(params.chainId, this.SUPPORTED_CHAIN_IDS)
|
|
109
110
|
this.validateConfigSupported(marketId)
|
|
110
111
|
return this._getMarket(marketId)
|
|
111
112
|
}
|
|
@@ -117,7 +118,7 @@ export abstract class LendProvider<
|
|
|
117
118
|
*/
|
|
118
119
|
async getMarkets(params: GetLendMarketsParams = {}): Promise<LendMarket[]> {
|
|
119
120
|
if (params.chainId !== undefined)
|
|
120
|
-
|
|
121
|
+
validateChainSupported(params.chainId, this.SUPPORTED_CHAIN_IDS)
|
|
121
122
|
|
|
122
123
|
const filteredMarkets = this.filterMarketConfigs(
|
|
123
124
|
params.chainId,
|
|
@@ -156,7 +157,7 @@ export abstract class LendProvider<
|
|
|
156
157
|
)
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
|
|
160
|
+
validateChainSupported(marketId.chainId, this.SUPPORTED_CHAIN_IDS)
|
|
160
161
|
this.validateConfigSupported(marketId)
|
|
161
162
|
|
|
162
163
|
return this._getPosition({ marketId, walletAddress })
|
|
@@ -176,7 +177,7 @@ export abstract class LendProvider<
|
|
|
176
177
|
throw new Error('walletAddress is required')
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
|
|
180
|
+
validateChainSupported(params.marketId.chainId, this.SUPPORTED_CHAIN_IDS)
|
|
180
181
|
this.validateConfigSupported(params.marketId)
|
|
181
182
|
|
|
182
183
|
const market = await this.getMarket({
|
|
@@ -217,19 +218,6 @@ export abstract class LendProvider<
|
|
|
217
218
|
return this.SUPPORTED_CHAIN_IDS.includes(chainId)
|
|
218
219
|
}
|
|
219
220
|
|
|
220
|
-
/**
|
|
221
|
-
* Validate that a chainId is supported for lending operations
|
|
222
|
-
* @param chainId - Chain ID to validate
|
|
223
|
-
* @throws Error if chain is not supported
|
|
224
|
-
*/
|
|
225
|
-
protected validateProviderSupported(chainId: number): void {
|
|
226
|
-
if (!this.isChainSupported(chainId)) {
|
|
227
|
-
throw new Error(
|
|
228
|
-
`Chain ${chainId} is not supported. Supported chains: ${this.SUPPORTED_CHAIN_IDS.join(', ')}`,
|
|
229
|
-
)
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
221
|
/**
|
|
234
222
|
* Validate that a market is in the config's market allowlist
|
|
235
223
|
* @param marketId - Market identifier containing address and chainId
|
|
@@ -4,13 +4,10 @@ import { describe, expect, it } from 'vitest'
|
|
|
4
4
|
import { MockUSDCAsset } from '@/__mocks__/MockAssets.js'
|
|
5
5
|
import { MockLendProvider } from '@/lend/__mocks__/MockLendProvider.js'
|
|
6
6
|
import type { LendMarketConfig, LendMarketId } from '@/types/lend/index.js'
|
|
7
|
+
import { validateChainSupported } from '@/utils/validation.js'
|
|
7
8
|
|
|
8
9
|
// Test helper class that exposes protected validation methods as public
|
|
9
10
|
class TestLendProvider extends MockLendProvider {
|
|
10
|
-
public validateProviderSupported(chainId: number): void {
|
|
11
|
-
return super.validateProviderSupported(chainId)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
11
|
public validateConfigSupported(marketId: LendMarketId): void {
|
|
15
12
|
return super.validateConfigSupported(marketId)
|
|
16
13
|
}
|
|
@@ -186,7 +183,7 @@ describe('LendProvider', () => {
|
|
|
186
183
|
const provider = new TestLendProvider()
|
|
187
184
|
|
|
188
185
|
expect(() => {
|
|
189
|
-
provider.
|
|
186
|
+
validateChainSupported(999, provider.supportedChainIds())
|
|
190
187
|
}).toThrow('Chain 999 is not supported')
|
|
191
188
|
})
|
|
192
189
|
|
|
@@ -160,11 +160,12 @@ describe('Vault Utilities', () => {
|
|
|
160
160
|
const result = calculateRewardsBreakdown(apiVault)
|
|
161
161
|
|
|
162
162
|
expect(result).toEqual({
|
|
163
|
+
eth: 0,
|
|
164
|
+
weth: 0,
|
|
163
165
|
usdc: 0,
|
|
164
166
|
usdc_demo: 0,
|
|
167
|
+
op_demo: 0,
|
|
165
168
|
morpho: 0,
|
|
166
|
-
eth: 0,
|
|
167
|
-
weth: 0,
|
|
168
169
|
other: 0,
|
|
169
170
|
totalRewards: 0,
|
|
170
171
|
})
|
|
@@ -3,7 +3,11 @@ import type { Address } from 'viem'
|
|
|
3
3
|
const MORPHO_API_ENDPOINT = 'https://api.morpho.org/graphql'
|
|
4
4
|
|
|
5
5
|
export interface RewardsBreakdown {
|
|
6
|
+
eth: number
|
|
7
|
+
weth: number
|
|
6
8
|
usdc: number
|
|
9
|
+
usdc_demo: number
|
|
10
|
+
op_demo: number
|
|
7
11
|
morpho: number
|
|
8
12
|
other: number
|
|
9
13
|
totalRewards: number
|
|
@@ -345,7 +345,16 @@ export async function getVault(params: GetVaultParams): Promise<LendMarket> {
|
|
|
345
345
|
params.marketId.address,
|
|
346
346
|
).catch((error) => {
|
|
347
347
|
console.error('Failed to fetch rewards data:', error)
|
|
348
|
-
return {
|
|
348
|
+
return {
|
|
349
|
+
eth: 0,
|
|
350
|
+
weth: 0,
|
|
351
|
+
usdc: 0,
|
|
352
|
+
usdc_demo: 0,
|
|
353
|
+
op_demo: 0,
|
|
354
|
+
morpho: 0,
|
|
355
|
+
other: 0,
|
|
356
|
+
totalRewards: 0,
|
|
357
|
+
}
|
|
349
358
|
})
|
|
350
359
|
|
|
351
360
|
const apyBreakdown = calculateApyBreakdown(vault, rewardsBreakdown)
|
package/src/supported/tokens.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import type { Address } from 'viem'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ETH,
|
|
5
|
+
MORPHO,
|
|
6
|
+
OP_DEMO,
|
|
7
|
+
USDC,
|
|
8
|
+
USDC_DEMO,
|
|
9
|
+
WETH,
|
|
10
|
+
} from '@/constants/assets.js'
|
|
4
11
|
import type { SupportedChainId } from '@/constants/supportedChains.js'
|
|
5
12
|
import type { Asset } from '@/types/asset.js'
|
|
6
13
|
|
|
7
|
-
export const SUPPORTED_TOKENS: Asset[] = [
|
|
14
|
+
export const SUPPORTED_TOKENS: Asset[] = [
|
|
15
|
+
ETH,
|
|
16
|
+
WETH,
|
|
17
|
+
USDC,
|
|
18
|
+
USDC_DEMO,
|
|
19
|
+
OP_DEMO,
|
|
20
|
+
MORPHO,
|
|
21
|
+
]
|
|
8
22
|
|
|
9
23
|
/**
|
|
10
24
|
* Get token by address and chain ID
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
import { type MockedFunction, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import type { SupportedChainId } from '@/constants/supportedChains.js'
|
|
5
|
+
import { MockChainManager } from '@/services/__mocks__/MockChainManager.js'
|
|
6
|
+
import type { ChainManager } from '@/services/ChainManager.js'
|
|
7
|
+
import { SwapProvider } from '@/swap/core/SwapProvider.js'
|
|
8
|
+
import type {
|
|
9
|
+
GetSwapMarketParams,
|
|
10
|
+
GetSwapMarketsParams,
|
|
11
|
+
ResolvedSwapParams,
|
|
12
|
+
SwapMarket,
|
|
13
|
+
SwapPrice,
|
|
14
|
+
SwapPriceParams,
|
|
15
|
+
SwapProviderConfig,
|
|
16
|
+
SwapTransaction,
|
|
17
|
+
} from '@/types/swap/index.js'
|
|
18
|
+
|
|
19
|
+
export interface MockSwapProviderConfig {
|
|
20
|
+
supportedChains: SupportedChainId[]
|
|
21
|
+
defaultPrice: string
|
|
22
|
+
defaultPriceImpact: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Mock Swap Provider for testing
|
|
27
|
+
*/
|
|
28
|
+
export class MockSwapProvider extends SwapProvider<SwapProviderConfig> {
|
|
29
|
+
public mockExecute: MockedFunction<
|
|
30
|
+
(params: ResolvedSwapParams) => Promise<SwapTransaction>
|
|
31
|
+
>
|
|
32
|
+
public mockGetPrice: MockedFunction<
|
|
33
|
+
(params: SwapPriceParams) => Promise<SwapPrice>
|
|
34
|
+
>
|
|
35
|
+
public mockGetMarket: MockedFunction<
|
|
36
|
+
(params: GetSwapMarketParams) => Promise<SwapMarket>
|
|
37
|
+
>
|
|
38
|
+
public mockGetMarkets: MockedFunction<
|
|
39
|
+
(params: GetSwapMarketsParams) => Promise<SwapMarket[]>
|
|
40
|
+
>
|
|
41
|
+
|
|
42
|
+
private _supportedChains: SupportedChainId[]
|
|
43
|
+
private mockProviderConfig: MockSwapProviderConfig
|
|
44
|
+
|
|
45
|
+
constructor(
|
|
46
|
+
config?: SwapProviderConfig,
|
|
47
|
+
mockConfig?: Partial<MockSwapProviderConfig>,
|
|
48
|
+
chainManager?: ChainManager,
|
|
49
|
+
) {
|
|
50
|
+
super(
|
|
51
|
+
config || {},
|
|
52
|
+
chainManager || (new MockChainManager() as unknown as ChainManager),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
this._supportedChains = mockConfig?.supportedChains ?? [
|
|
56
|
+
84532 as SupportedChainId,
|
|
57
|
+
]
|
|
58
|
+
this.mockProviderConfig = {
|
|
59
|
+
supportedChains: this._supportedChains,
|
|
60
|
+
defaultPrice: mockConfig?.defaultPrice ?? '1.5',
|
|
61
|
+
defaultPriceImpact: mockConfig?.defaultPriceImpact ?? 0.001,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Create mocked functions
|
|
65
|
+
this.mockExecute = vi
|
|
66
|
+
.fn()
|
|
67
|
+
.mockImplementation(this.createMockSwapTransaction.bind(this))
|
|
68
|
+
this.mockGetPrice = vi
|
|
69
|
+
.fn()
|
|
70
|
+
.mockImplementation(this.createMockPrice.bind(this))
|
|
71
|
+
this.mockGetMarket = vi
|
|
72
|
+
.fn()
|
|
73
|
+
.mockImplementation(this.createMockMarket.bind(this))
|
|
74
|
+
this.mockGetMarkets = vi
|
|
75
|
+
.fn()
|
|
76
|
+
.mockImplementation(this.createMockMarkets.bind(this))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
supportedChainIds(): SupportedChainId[] {
|
|
80
|
+
return this._supportedChains
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
reset(): void {
|
|
84
|
+
vi.clearAllMocks()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Expose protected methods for testing
|
|
88
|
+
public testValidateMarketAllowed(
|
|
89
|
+
assetIn: any,
|
|
90
|
+
assetOut: any,
|
|
91
|
+
chainId: SupportedChainId,
|
|
92
|
+
): void {
|
|
93
|
+
return this.validateMarketAllowed(assetIn, assetOut, chainId)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected async _execute(
|
|
97
|
+
params: ResolvedSwapParams,
|
|
98
|
+
): Promise<SwapTransaction> {
|
|
99
|
+
return this.mockExecute(params)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected async _getPrice(params: SwapPriceParams): Promise<SwapPrice> {
|
|
103
|
+
return this.mockGetPrice(params)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected async _getMarket(params: GetSwapMarketParams): Promise<SwapMarket> {
|
|
107
|
+
return this.mockGetMarket(params)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected async _getMarkets(
|
|
111
|
+
params: GetSwapMarketsParams,
|
|
112
|
+
): Promise<SwapMarket[]> {
|
|
113
|
+
return this.mockGetMarkets(params)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private createMockSwapTransaction(
|
|
117
|
+
params: ResolvedSwapParams,
|
|
118
|
+
): SwapTransaction {
|
|
119
|
+
const amountIn = params.amountInWei ?? 1000000n
|
|
120
|
+
const amountOut = 1500000000000000000n
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
amountIn: 1.0,
|
|
124
|
+
amountOut: 1.5,
|
|
125
|
+
amountInWei: amountIn,
|
|
126
|
+
amountOutWei: amountOut,
|
|
127
|
+
assetIn: params.assetIn,
|
|
128
|
+
assetOut: params.assetOut,
|
|
129
|
+
price: this.mockProviderConfig.defaultPrice,
|
|
130
|
+
priceImpact: this.mockProviderConfig.defaultPriceImpact,
|
|
131
|
+
transactionData: {
|
|
132
|
+
swap: {
|
|
133
|
+
to: '0x492e6456d9528771018deb9e87ef7750ef184104' as Address,
|
|
134
|
+
data: '0x1234' as `0x${string}`,
|
|
135
|
+
value: 0n,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private createMockPrice(params: SwapPriceParams): SwapPrice {
|
|
142
|
+
const amountIn =
|
|
143
|
+
params.amountIn !== undefined
|
|
144
|
+
? BigInt(
|
|
145
|
+
Math.floor(
|
|
146
|
+
params.amountIn * 10 ** params.assetIn.metadata.decimals,
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
: BigInt(10 ** params.assetIn.metadata.decimals)
|
|
150
|
+
|
|
151
|
+
const amountOut = (amountIn * 15n) / 10n
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
price: this.mockProviderConfig.defaultPrice,
|
|
155
|
+
priceInverse: '0.666666',
|
|
156
|
+
amountIn: 1.0,
|
|
157
|
+
amountOut: 1.5,
|
|
158
|
+
amountInWei: amountIn,
|
|
159
|
+
amountOutWei: amountOut,
|
|
160
|
+
priceImpact: this.mockProviderConfig.defaultPriceImpact,
|
|
161
|
+
route: {
|
|
162
|
+
path: [params.assetIn, params.assetOut!],
|
|
163
|
+
pools: [
|
|
164
|
+
{
|
|
165
|
+
address: '0x1234' as Address,
|
|
166
|
+
fee: 500,
|
|
167
|
+
version: 'v4',
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
gasEstimate: 150000n,
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private createMockMarket(params: GetSwapMarketParams): SwapMarket {
|
|
176
|
+
return {
|
|
177
|
+
marketId: {
|
|
178
|
+
poolId: params.poolId,
|
|
179
|
+
chainId: params.chainId,
|
|
180
|
+
},
|
|
181
|
+
assets: [
|
|
182
|
+
{
|
|
183
|
+
type: 'erc20',
|
|
184
|
+
address: { [params.chainId]: '0x1111' as Address },
|
|
185
|
+
metadata: { name: 'USDC', symbol: 'USDC', decimals: 6 },
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
type: 'erc20',
|
|
189
|
+
address: { [params.chainId]: '0x2222' as Address },
|
|
190
|
+
metadata: { name: 'WETH', symbol: 'WETH', decimals: 18 },
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
fee: 500,
|
|
194
|
+
provider: 'uniswap',
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private createMockMarkets(_params: GetSwapMarketsParams): SwapMarket[] {
|
|
199
|
+
return [
|
|
200
|
+
this.createMockMarket({
|
|
201
|
+
poolId: '0xpool1',
|
|
202
|
+
chainId: 84532 as SupportedChainId,
|
|
203
|
+
}),
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Create a mock swap provider
|
|
210
|
+
*/
|
|
211
|
+
export function createMockSwapProvider(
|
|
212
|
+
config?: SwapProviderConfig,
|
|
213
|
+
mockConfig?: Partial<MockSwapProviderConfig>,
|
|
214
|
+
): MockSwapProvider {
|
|
215
|
+
return new MockSwapProvider(config, mockConfig)
|
|
216
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
|
|
3
|
+
import type { SupportedChainId } from '@/constants/supportedChains.js'
|
|
4
|
+
import type { ChainManager } from '@/services/ChainManager.js'
|
|
5
|
+
import type { Asset } from '@/types/asset.js'
|
|
6
|
+
import type {
|
|
7
|
+
GetSwapMarketParams,
|
|
8
|
+
GetSwapMarketsParams,
|
|
9
|
+
ResolvedSwapParams,
|
|
10
|
+
SwapExecuteParams,
|
|
11
|
+
SwapMarket,
|
|
12
|
+
SwapMarketConfig,
|
|
13
|
+
SwapPrice,
|
|
14
|
+
SwapPriceParams,
|
|
15
|
+
SwapProviderConfig,
|
|
16
|
+
SwapTransaction,
|
|
17
|
+
} from '@/types/swap/index.js'
|
|
18
|
+
import type { TransactionData } from '@/types/transaction.js'
|
|
19
|
+
import {
|
|
20
|
+
getAssetAddress,
|
|
21
|
+
isNativeAsset,
|
|
22
|
+
parseAssetAmount,
|
|
23
|
+
} from '@/utils/assets.js'
|
|
24
|
+
import {
|
|
25
|
+
buildPermit2ApprovalTx,
|
|
26
|
+
buildTokenApprovalTx,
|
|
27
|
+
checkPermit2Allowance,
|
|
28
|
+
checkTokenAllowance,
|
|
29
|
+
} from '@/utils/permit2.js'
|
|
30
|
+
import {
|
|
31
|
+
validateAmountPositiveIfExists,
|
|
32
|
+
validateAmountProvided,
|
|
33
|
+
validateAssetOnChain,
|
|
34
|
+
validateChainSupported,
|
|
35
|
+
validateNotBothAmounts,
|
|
36
|
+
validateNotSameAsset,
|
|
37
|
+
validateNotZeroAddress,
|
|
38
|
+
validateSlippage,
|
|
39
|
+
} from '@/utils/validation.js'
|
|
40
|
+
|
|
41
|
+
const DEFAULT_SLIPPAGE = 0.005
|
|
42
|
+
const DEFAULT_DEADLINE_OFFSET = 60
|
|
43
|
+
const DEFAULT_MAX_SLIPPAGE = 0.5
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Abstract base class for swap providers.
|
|
47
|
+
* Public methods handle validation and conversion,
|
|
48
|
+
* protected abstract methods implement provider-specific logic.
|
|
49
|
+
*/
|
|
50
|
+
export abstract class SwapProvider<
|
|
51
|
+
TConfig extends SwapProviderConfig = SwapProviderConfig,
|
|
52
|
+
> {
|
|
53
|
+
protected readonly _config: TConfig
|
|
54
|
+
protected readonly chainManager: ChainManager
|
|
55
|
+
|
|
56
|
+
constructor(config: TConfig, chainManager: ChainManager) {
|
|
57
|
+
this._config = config
|
|
58
|
+
this.chainManager = chainManager
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get config(): TConfig {
|
|
62
|
+
return this._config
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get defaultSlippage(): number {
|
|
66
|
+
return this._config.defaultSlippage ?? DEFAULT_SLIPPAGE
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Execute a token swap
|
|
71
|
+
* @param params - Swap parameters including assets, amounts, and chain
|
|
72
|
+
* @returns Swap transaction data ready for execution
|
|
73
|
+
*/
|
|
74
|
+
async execute(params: SwapExecuteParams): Promise<SwapTransaction> {
|
|
75
|
+
this.executeValidations(params)
|
|
76
|
+
const resolvedParams = this.resolveParams(params)
|
|
77
|
+
validateSlippage(
|
|
78
|
+
resolvedParams.slippage,
|
|
79
|
+
this._config.maxSlippage ?? DEFAULT_MAX_SLIPPAGE,
|
|
80
|
+
)
|
|
81
|
+
return this._execute(resolvedParams)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Get price quote for a swap */
|
|
85
|
+
async getPrice(params: SwapPriceParams): Promise<SwapPrice> {
|
|
86
|
+
validateChainSupported(params.chainId, this.supportedChainIds())
|
|
87
|
+
return this._getPrice(params)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Get a specific swap market by ID */
|
|
91
|
+
async getMarket(params: GetSwapMarketParams): Promise<SwapMarket> {
|
|
92
|
+
validateChainSupported(params.chainId, this.supportedChainIds())
|
|
93
|
+
return this._getMarket(params)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Get available swap markets, optionally filtered by chainId or asset */
|
|
97
|
+
async getMarkets(params: GetSwapMarketsParams = {}): Promise<SwapMarket[]> {
|
|
98
|
+
if (params.chainId) {
|
|
99
|
+
validateChainSupported(params.chainId, this.supportedChainIds())
|
|
100
|
+
}
|
|
101
|
+
return this._getMarkets(params)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
isChainSupported(chainId: SupportedChainId): boolean {
|
|
105
|
+
return this.supportedChainIds().includes(chainId)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
// Protected helpers
|
|
110
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
protected validateMarketAllowed(
|
|
113
|
+
assetIn: Asset,
|
|
114
|
+
assetOut: Asset,
|
|
115
|
+
chainId: SupportedChainId,
|
|
116
|
+
): void {
|
|
117
|
+
const { marketBlocklist, marketAllowlist } = this._config
|
|
118
|
+
|
|
119
|
+
if (marketBlocklist?.length) {
|
|
120
|
+
const isBlocked = this.findMatchingConfig(
|
|
121
|
+
assetIn,
|
|
122
|
+
assetOut,
|
|
123
|
+
chainId,
|
|
124
|
+
marketBlocklist,
|
|
125
|
+
)
|
|
126
|
+
if (isBlocked) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Pair ${assetIn.metadata.symbol}/${assetOut.metadata.symbol} is blocked on chain ${chainId}`,
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (marketAllowlist?.length) {
|
|
134
|
+
const isAllowed = this.findMatchingConfig(
|
|
135
|
+
assetIn,
|
|
136
|
+
assetOut,
|
|
137
|
+
chainId,
|
|
138
|
+
marketAllowlist,
|
|
139
|
+
)
|
|
140
|
+
if (!isAllowed) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Pair ${assetIn.metadata.symbol}/${assetOut.metadata.symbol} is not in the allowlist for chain ${chainId}`,
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
protected resolveMarketConfig(
|
|
149
|
+
assetIn: Asset,
|
|
150
|
+
assetOut: Asset,
|
|
151
|
+
chainId: SupportedChainId,
|
|
152
|
+
): SwapMarketConfig | undefined {
|
|
153
|
+
const { marketAllowlist } = this._config
|
|
154
|
+
if (!marketAllowlist?.length) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
'No markets configured. Provide a marketAllowlist in swap provider config.',
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
return this.findMatchingConfig(assetIn, assetOut, chainId, marketAllowlist)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Build Permit2 approval transactions for an ERC20 swap input.
|
|
164
|
+
* Skipped for native assets. Checks both ERC20→Permit2 and Permit2→spender allowances in parallel.
|
|
165
|
+
* @param params - Resolved swap params (wallet address, asset info, chain)
|
|
166
|
+
* @param requiredAmount - Amount in wei that must be approved
|
|
167
|
+
* @param permit2Address - Permit2 contract address
|
|
168
|
+
* @param permit2Spender - The router/contract that Permit2 should approve (e.g. Universal Router)
|
|
169
|
+
* @param permit2ExpirySeconds - Optional custom expiry for the Permit2 approval
|
|
170
|
+
*/
|
|
171
|
+
protected async buildPermit2Approvals(
|
|
172
|
+
params: ResolvedSwapParams,
|
|
173
|
+
requiredAmount: bigint,
|
|
174
|
+
permit2Address: Address,
|
|
175
|
+
permit2Spender: Address,
|
|
176
|
+
permit2ExpirySeconds?: number,
|
|
177
|
+
): Promise<{
|
|
178
|
+
tokenApproval: TransactionData | undefined
|
|
179
|
+
permit2Approval: TransactionData | undefined
|
|
180
|
+
}> {
|
|
181
|
+
if (isNativeAsset(params.assetIn)) {
|
|
182
|
+
return { tokenApproval: undefined, permit2Approval: undefined }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const publicClient = this.chainManager.getPublicClient(params.chainId)
|
|
186
|
+
const token = getAssetAddress(params.assetIn, params.chainId)
|
|
187
|
+
|
|
188
|
+
const [tokenAllowance, permit2Allowance] = await Promise.all([
|
|
189
|
+
checkTokenAllowance({
|
|
190
|
+
publicClient,
|
|
191
|
+
token,
|
|
192
|
+
owner: params.walletAddress,
|
|
193
|
+
spender: permit2Address,
|
|
194
|
+
}),
|
|
195
|
+
checkPermit2Allowance({
|
|
196
|
+
publicClient,
|
|
197
|
+
permit2Address,
|
|
198
|
+
owner: params.walletAddress,
|
|
199
|
+
token,
|
|
200
|
+
spender: permit2Spender,
|
|
201
|
+
}),
|
|
202
|
+
])
|
|
203
|
+
|
|
204
|
+
const tokenApproval =
|
|
205
|
+
tokenAllowance < requiredAmount
|
|
206
|
+
? buildTokenApprovalTx(token, permit2Address)
|
|
207
|
+
: undefined
|
|
208
|
+
|
|
209
|
+
// Permit2 expiration is in Unix seconds (matching EVM block.timestamp)
|
|
210
|
+
const permit2Expired =
|
|
211
|
+
permit2Allowance.expiration < Math.floor(Date.now() / 1000)
|
|
212
|
+
const permit2Approval =
|
|
213
|
+
permit2Allowance.amount < requiredAmount || permit2Expired
|
|
214
|
+
? buildPermit2ApprovalTx({
|
|
215
|
+
permit2Address,
|
|
216
|
+
token,
|
|
217
|
+
spender: permit2Spender,
|
|
218
|
+
amount: requiredAmount,
|
|
219
|
+
expirySeconds: permit2ExpirySeconds,
|
|
220
|
+
})
|
|
221
|
+
: undefined
|
|
222
|
+
|
|
223
|
+
return { tokenApproval, permit2Approval }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
227
|
+
// Private helpers
|
|
228
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
private executeValidations(params: SwapExecuteParams): void {
|
|
231
|
+
validateAmountProvided(params.amountIn, params.amountOut)
|
|
232
|
+
validateAmountPositiveIfExists(params.amountIn)
|
|
233
|
+
validateAmountPositiveIfExists(params.amountOut)
|
|
234
|
+
validateNotBothAmounts(params.amountIn, params.amountOut)
|
|
235
|
+
validateNotSameAsset(params.assetIn, params.assetOut)
|
|
236
|
+
validateNotZeroAddress(params.walletAddress, 'walletAddress')
|
|
237
|
+
if (params.recipient) {
|
|
238
|
+
validateNotZeroAddress(params.recipient, 'recipient')
|
|
239
|
+
}
|
|
240
|
+
validateChainSupported(params.chainId, this.supportedChainIds())
|
|
241
|
+
this.validateMarketAllowed(params.assetIn, params.assetOut, params.chainId)
|
|
242
|
+
validateAssetOnChain(params.assetIn, params.chainId)
|
|
243
|
+
validateAssetOnChain(params.assetOut, params.chainId)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private resolveParams(params: SwapExecuteParams): ResolvedSwapParams {
|
|
247
|
+
return {
|
|
248
|
+
amountInWei: parseAssetAmount(params.assetIn, params.amountIn),
|
|
249
|
+
amountOutWei: parseAssetAmount(params.assetOut, params.amountOut),
|
|
250
|
+
assetIn: params.assetIn,
|
|
251
|
+
assetOut: params.assetOut,
|
|
252
|
+
slippage: params.slippage ?? this.defaultSlippage,
|
|
253
|
+
deadline:
|
|
254
|
+
params.deadline ??
|
|
255
|
+
Math.floor(Date.now() / 1000) + DEFAULT_DEADLINE_OFFSET,
|
|
256
|
+
// Send output tokens to specified recipient, or back to the initiating wallet
|
|
257
|
+
recipient: params.recipient ?? params.walletAddress,
|
|
258
|
+
walletAddress: params.walletAddress,
|
|
259
|
+
chainId: params.chainId,
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private findMatchingConfig(
|
|
264
|
+
assetIn: Asset,
|
|
265
|
+
assetOut: Asset,
|
|
266
|
+
chainId: SupportedChainId,
|
|
267
|
+
list: SwapMarketConfig[],
|
|
268
|
+
): SwapMarketConfig | undefined {
|
|
269
|
+
const addressIn = assetIn.address[chainId]
|
|
270
|
+
const addressOut = assetOut.address[chainId]
|
|
271
|
+
if (!addressIn || !addressOut) return undefined
|
|
272
|
+
|
|
273
|
+
return list.find((config) => {
|
|
274
|
+
if (config.chainId !== undefined && config.chainId !== chainId)
|
|
275
|
+
return false
|
|
276
|
+
return this.containsPairByAddress(
|
|
277
|
+
addressIn,
|
|
278
|
+
addressOut,
|
|
279
|
+
chainId,
|
|
280
|
+
config.assets,
|
|
281
|
+
)
|
|
282
|
+
})
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private containsPairByAddress(
|
|
286
|
+
addressIn: string,
|
|
287
|
+
addressOut: string,
|
|
288
|
+
chainId: SupportedChainId,
|
|
289
|
+
assets: Asset[],
|
|
290
|
+
): boolean {
|
|
291
|
+
const addresses = assets
|
|
292
|
+
.map((a) => a.address[chainId]?.toLowerCase())
|
|
293
|
+
.filter(Boolean)
|
|
294
|
+
return (
|
|
295
|
+
addresses.includes(addressIn.toLowerCase()) &&
|
|
296
|
+
addresses.includes(addressOut.toLowerCase())
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
301
|
+
// Abstract methods (implement in provider)
|
|
302
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
303
|
+
|
|
304
|
+
abstract supportedChainIds(): SupportedChainId[]
|
|
305
|
+
|
|
306
|
+
protected abstract _execute(
|
|
307
|
+
params: ResolvedSwapParams,
|
|
308
|
+
): Promise<SwapTransaction>
|
|
309
|
+
|
|
310
|
+
protected abstract _getPrice(params: SwapPriceParams): Promise<SwapPrice>
|
|
311
|
+
|
|
312
|
+
protected abstract _getMarket(
|
|
313
|
+
params: GetSwapMarketParams,
|
|
314
|
+
): Promise<SwapMarket>
|
|
315
|
+
|
|
316
|
+
protected abstract _getMarkets(
|
|
317
|
+
params: GetSwapMarketsParams,
|
|
318
|
+
): Promise<SwapMarket[]>
|
|
319
|
+
}
|