@eth-optimism/actions-sdk 0.0.4 → 0.1.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/actions.d.ts +19 -7
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +49 -19
- package/dist/actions.js.map +1 -1
- package/dist/actions.test.js +30 -80
- package/dist/actions.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lend/core/LendProvider.d.ts +3 -2
- package/dist/lend/core/LendProvider.d.ts.map +1 -1
- package/dist/lend/core/LendProvider.js.map +1 -1
- package/dist/lend/core/__tests__/LendProvider.test.js +18 -48
- package/dist/lend/core/__tests__/LendProvider.test.js.map +1 -1
- package/dist/lend/index.d.ts +1 -0
- package/dist/lend/index.d.ts.map +1 -1
- package/dist/lend/index.js +1 -0
- package/dist/lend/index.js.map +1 -1
- package/dist/lend/namespaces/ActionsLendNamespace.d.ts +35 -8
- package/dist/lend/namespaces/ActionsLendNamespace.d.ts.map +1 -1
- package/dist/lend/namespaces/ActionsLendNamespace.js +45 -8
- package/dist/lend/namespaces/ActionsLendNamespace.js.map +1 -1
- package/dist/lend/namespaces/WalletLendNamespace.d.ts +35 -8
- package/dist/lend/namespaces/WalletLendNamespace.d.ts.map +1 -1
- package/dist/lend/namespaces/WalletLendNamespace.js +59 -11
- package/dist/lend/namespaces/WalletLendNamespace.js.map +1 -1
- package/dist/lend/namespaces/__tests__/ActionsLendNamespace.spec.js +23 -15
- package/dist/lend/namespaces/__tests__/ActionsLendNamespace.spec.js.map +1 -1
- package/dist/lend/namespaces/__tests__/WalletLendNamespace.spec.js +29 -11
- package/dist/lend/namespaces/__tests__/WalletLendNamespace.spec.js.map +1 -1
- package/dist/lend/providers/aave/AaveLendProvider.d.ts +82 -0
- package/dist/lend/providers/aave/AaveLendProvider.d.ts.map +1 -0
- package/dist/lend/providers/aave/AaveLendProvider.js +346 -0
- package/dist/lend/providers/aave/AaveLendProvider.js.map +1 -0
- package/dist/lend/providers/aave/addresses.d.ts +57 -0
- package/dist/lend/providers/aave/addresses.d.ts.map +1 -0
- package/dist/lend/providers/aave/addresses.js +83 -0
- package/dist/lend/providers/aave/addresses.js.map +1 -0
- package/dist/lend/providers/aave/sdk.d.ts +57 -0
- package/dist/lend/providers/aave/sdk.d.ts.map +1 -0
- package/dist/lend/providers/aave/sdk.js +260 -0
- package/dist/lend/providers/aave/sdk.js.map +1 -0
- package/dist/lend/providers/morpho/MorphoLendProvider.d.ts +4 -3
- package/dist/lend/providers/morpho/MorphoLendProvider.d.ts.map +1 -1
- package/dist/lend/providers/morpho/MorphoLendProvider.js +2 -2
- package/dist/lend/providers/morpho/MorphoLendProvider.js.map +1 -1
- package/dist/lend/providers/morpho/__tests__/MorphoLendProvider.test.js +1 -33
- package/dist/lend/providers/morpho/__tests__/MorphoLendProvider.test.js.map +1 -1
- package/dist/lend/providers/morpho/__tests__/sdk.test.js +1 -0
- package/dist/lend/providers/morpho/__tests__/sdk.test.js.map +1 -1
- package/dist/lend/providers/morpho/sdk.d.ts +4 -3
- package/dist/lend/providers/morpho/sdk.d.ts.map +1 -1
- package/dist/supported/tokens.d.ts.map +1 -1
- package/dist/supported/tokens.js +18 -2
- package/dist/supported/tokens.js.map +1 -1
- package/dist/test/MockLendProvider.d.ts +5 -4
- package/dist/test/MockLendProvider.d.ts.map +1 -1
- package/dist/test/MockLendProvider.js +5 -5
- package/dist/test/MockLendProvider.js.map +1 -1
- package/dist/types/actions.d.ts +26 -2
- package/dist/types/actions.d.ts.map +1 -1
- package/dist/types/lend/base.d.ts +6 -19
- package/dist/types/lend/base.d.ts.map +1 -1
- package/dist/wallet/core/namespace/__tests__/WalletNamespace.spec.js +9 -9
- package/dist/wallet/core/namespace/__tests__/WalletNamespace.spec.js.map +1 -1
- package/dist/wallet/core/providers/__tests__/WalletProvider.spec.js +8 -8
- package/dist/wallet/core/providers/__tests__/WalletProvider.spec.js.map +1 -1
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts +12 -3
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js +3 -2
- package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js.map +1 -1
- package/dist/wallet/core/providers/hosted/types/index.d.ts +8 -2
- package/dist/wallet/core/providers/hosted/types/index.d.ts.map +1 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts +14 -6
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts.map +1 -1
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js +10 -6
- package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js.map +1 -1
- package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js +36 -13
- package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js.map +1 -1
- package/dist/wallet/core/wallets/abstract/Wallet.d.ts +19 -7
- package/dist/wallet/core/wallets/abstract/Wallet.d.ts.map +1 -1
- package/dist/wallet/core/wallets/abstract/Wallet.js +9 -7
- package/dist/wallet/core/wallets/abstract/Wallet.js.map +1 -1
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts +9 -3
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts.map +1 -1
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js +4 -4
- package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js.map +1 -1
- package/dist/wallet/core/wallets/smart/default/__tests__/DefaultSmartWallet.spec.js +1 -1
- package/dist/wallet/core/wallets/smart/default/__tests__/DefaultSmartWallet.spec.js.map +1 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts +10 -3
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js +5 -3
- package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/node/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js +4 -3
- package/dist/wallet/node/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.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 +5 -4
- package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.js.map +1 -1
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts +9 -2
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +6 -3
- package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/node/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.js +4 -3
- package/dist/wallet/node/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.js.map +1 -1
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts +10 -3
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts.map +1 -1
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js +5 -4
- package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js.map +1 -1
- package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.d.ts +8 -2
- 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 +6 -2
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js +3 -3
- package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.js +19 -7
- 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 -2
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js +3 -3
- package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js +7 -3
- 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 -2
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +3 -3
- package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
- package/dist/wallet/react/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.js +6 -3
- package/dist/wallet/react/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.js.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 +6 -2
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.d.ts.map +1 -1
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js +3 -3
- package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js.map +1 -1
- package/dist/wallet/react/wallets/hosted/dynamic/__mocks__/DynamicWalletMock.d.ts +6 -0
- package/dist/wallet/react/wallets/hosted/dynamic/__mocks__/DynamicWalletMock.d.ts.map +1 -1
- package/dist/wallet/react/wallets/hosted/dynamic/__mocks__/DynamicWalletMock.js.map +1 -1
- package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.d.ts +6 -2
- 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 +6 -2
- 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 +4 -1
- package/src/actions.test.ts +32 -93
- package/src/actions.ts +82 -26
- package/src/index.ts +1 -2
- package/src/lend/core/LendProvider.ts +6 -5
- package/src/lend/core/__tests__/LendProvider.test.ts +19 -61
- package/src/lend/index.ts +1 -0
- package/src/lend/namespaces/ActionsLendNamespace.ts +77 -13
- package/src/lend/namespaces/WalletLendNamespace.ts +98 -18
- package/src/lend/namespaces/__tests__/ActionsLendNamespace.spec.ts +24 -18
- package/src/lend/namespaces/__tests__/WalletLendNamespace.spec.ts +49 -11
- package/src/lend/providers/aave/AaveLendProvider.ts +463 -0
- package/src/lend/providers/aave/addresses.ts +95 -0
- package/src/lend/providers/aave/sdk.ts +369 -0
- package/src/lend/providers/morpho/MorphoLendProvider.ts +5 -5
- package/src/lend/providers/morpho/__tests__/MorphoLendProvider.test.ts +5 -53
- package/src/lend/providers/morpho/__tests__/sdk.test.ts +1 -0
- package/src/lend/providers/morpho/sdk.ts +3 -3
- package/src/supported/tokens.ts +24 -2
- package/src/test/MockLendProvider.ts +9 -9
- package/src/types/actions.ts +30 -2
- package/src/types/lend/base.ts +6 -22
- package/src/wallet/core/namespace/__tests__/WalletNamespace.spec.ts +9 -9
- package/src/wallet/core/providers/__tests__/WalletProvider.spec.ts +8 -8
- package/src/wallet/core/providers/hosted/abstract/HostedWalletProvider.ts +15 -4
- package/src/wallet/core/providers/hosted/types/index.ts +8 -2
- package/src/wallet/core/providers/smart/default/DefaultSmartWalletProvider.ts +24 -9
- package/src/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.ts +38 -46
- package/src/wallet/core/wallets/abstract/Wallet.ts +25 -17
- package/src/wallet/core/wallets/smart/default/DefaultSmartWallet.ts +17 -10
- package/src/wallet/core/wallets/smart/default/__tests__/DefaultSmartWallet.spec.ts +4 -7
- package/src/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.ts +13 -5
- package/src/wallet/node/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.ts +4 -4
- package/src/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.ts +6 -4
- package/src/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +13 -4
- package/src/wallet/node/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.ts +4 -4
- package/src/wallet/node/wallets/hosted/privy/PrivyWallet.ts +18 -6
- package/src/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.ts +16 -5
- package/src/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.ts +8 -4
- package/src/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.ts +25 -14
- package/src/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.ts +8 -4
- package/src/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.ts +7 -7
- package/src/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +8 -4
- package/src/wallet/react/providers/hosted/turnkey/__tests__/TurnkeyHostedWalletProvider.spec.ts +6 -7
- package/src/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.ts +6 -6
- package/src/wallet/react/wallets/hosted/dynamic/DynamicWallet.ts +12 -5
- package/src/wallet/react/wallets/hosted/dynamic/__mocks__/DynamicWalletMock.ts +6 -0
- package/src/wallet/react/wallets/hosted/privy/PrivyWallet.ts +12 -5
- package/src/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.ts +12 -5
- package/dist/constants/config.d.ts +0 -10
- package/dist/constants/config.d.ts.map +0 -1
- package/dist/constants/config.js +0 -10
- package/dist/constants/config.js.map +0 -1
- package/src/constants/config.ts +0 -9
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
import { encodeFunctionData, erc20Abi, formatUnits, parseAbi } from 'viem'
|
|
3
|
+
|
|
4
|
+
import { LendProvider } from '@/lend/core/LendProvider.js'
|
|
5
|
+
import type { ChainManager } from '@/services/ChainManager.js'
|
|
6
|
+
import type { LendProviderConfig } from '@/types/actions.js'
|
|
7
|
+
import type {
|
|
8
|
+
GetLendMarketsParams,
|
|
9
|
+
GetMarketBalanceParams,
|
|
10
|
+
LendClosePositionParams,
|
|
11
|
+
LendMarket,
|
|
12
|
+
LendMarketId,
|
|
13
|
+
LendMarketPosition,
|
|
14
|
+
LendOpenPositionInternalParams,
|
|
15
|
+
LendTransaction,
|
|
16
|
+
} from '@/types/lend/index.js'
|
|
17
|
+
import { getAssetAddress } from '@/utils/assets.js'
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
getPoolAddress,
|
|
21
|
+
getSupportedChainIds,
|
|
22
|
+
getWETHGatewayAddress,
|
|
23
|
+
} from './addresses.js'
|
|
24
|
+
import { getReserve, getReserves } from './sdk.js'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* WETH predeploy address on OP Stack chains
|
|
28
|
+
* @description WETH is deployed at the same address on all OP Stack chains (Optimism, Base, etc.)
|
|
29
|
+
*/
|
|
30
|
+
const WETH_ADDRESS = '0x4200000000000000000000000000000000000006'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Aave Pool ABI - only the functions we need
|
|
34
|
+
*/
|
|
35
|
+
const POOL_ABI = parseAbi([
|
|
36
|
+
'function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)',
|
|
37
|
+
'function withdraw(address asset, uint256 amount, address to) returns (uint256)',
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Aave WETHGateway ABI - for native ETH deposits/withdrawals
|
|
42
|
+
*/
|
|
43
|
+
const WETH_GATEWAY_ABI = parseAbi([
|
|
44
|
+
'function depositETH(address pool, address onBehalfOf, uint16 referralCode) payable',
|
|
45
|
+
'function withdrawETH(address pool, uint256 amount, address to)',
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Supported chain IDs for Aave lending
|
|
50
|
+
* @description Array of chain IDs where Aave V3 is available on Optimism Superchain
|
|
51
|
+
*/
|
|
52
|
+
export const SUPPORTED_CHAIN_IDS = getSupportedChainIds() as readonly number[]
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Aave lending provider implementation
|
|
56
|
+
* @description Lending provider implementation using Aave V3 protocol
|
|
57
|
+
*/
|
|
58
|
+
export class AaveLendProvider extends LendProvider<LendProviderConfig> {
|
|
59
|
+
protected readonly SUPPORTED_CHAIN_IDS = SUPPORTED_CHAIN_IDS
|
|
60
|
+
|
|
61
|
+
private chainManager: ChainManager
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a new Aave lending provider
|
|
65
|
+
* @param config - Aave lending configuration
|
|
66
|
+
* @param chainManager - Chain manager for blockchain interactions
|
|
67
|
+
*/
|
|
68
|
+
constructor(config: LendProviderConfig, chainManager: ChainManager) {
|
|
69
|
+
super(config)
|
|
70
|
+
this.chainManager = chainManager
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if market is a WETH market
|
|
75
|
+
* @param marketId - Market identifier
|
|
76
|
+
* @returns true if market is for WETH
|
|
77
|
+
* @description WETH is a predeploy at the same address on all OP Stack chains
|
|
78
|
+
*/
|
|
79
|
+
private isWETHMarket(marketId: LendMarketId): boolean {
|
|
80
|
+
return marketId.address.toLowerCase() === WETH_ADDRESS.toLowerCase()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Open a lending position in an Aave market
|
|
85
|
+
* @description Opens a lending position by supplying assets to an Aave reserve
|
|
86
|
+
* @param params - Position opening parameters
|
|
87
|
+
* @returns Promise resolving to lending transaction details
|
|
88
|
+
*/
|
|
89
|
+
protected async _openPosition(
|
|
90
|
+
params: LendOpenPositionInternalParams,
|
|
91
|
+
): Promise<LendTransaction> {
|
|
92
|
+
try {
|
|
93
|
+
// Get Pool address for this chain
|
|
94
|
+
const poolAddress = getPoolAddress(params.marketId.chainId)
|
|
95
|
+
if (!poolAddress) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Aave V3 not deployed on chain ${params.marketId.chainId}`,
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Get market information for APY
|
|
102
|
+
const marketInfo = await this.getMarket({
|
|
103
|
+
address: params.marketId.address,
|
|
104
|
+
chainId: params.marketId.chainId,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Check if this is a WETH market
|
|
108
|
+
if (this.isWETHMarket(params.marketId)) {
|
|
109
|
+
return this._openWETHPosition(params, poolAddress, marketInfo)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Standard ERC-20 flow
|
|
113
|
+
return this._openERC20Position(params, poolAddress, marketInfo)
|
|
114
|
+
} catch (error) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`Failed to open position with ${params.amountWei} of ${params.asset.metadata.symbol}: ${
|
|
117
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
118
|
+
}`,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Open position for WETH market using WETHGateway
|
|
125
|
+
* @description Deposits native ETH via WETHGateway which wraps and deposits in one tx
|
|
126
|
+
*/
|
|
127
|
+
private async _openWETHPosition(
|
|
128
|
+
params: LendOpenPositionInternalParams,
|
|
129
|
+
poolAddress: Address,
|
|
130
|
+
marketInfo: LendMarket,
|
|
131
|
+
): Promise<LendTransaction> {
|
|
132
|
+
const gatewayAddress = getWETHGatewayAddress(params.marketId.chainId)
|
|
133
|
+
if (!gatewayAddress) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`WETHGateway not available on chain ${params.marketId.chainId}`,
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Generate depositETH transaction
|
|
140
|
+
const depositCallData = encodeFunctionData({
|
|
141
|
+
abi: WETH_GATEWAY_ABI,
|
|
142
|
+
functionName: 'depositETH',
|
|
143
|
+
args: [
|
|
144
|
+
poolAddress, // pool address
|
|
145
|
+
params.walletAddress, // onBehalfOf (receives aWETH)
|
|
146
|
+
0, // referralCode (0 = no referral)
|
|
147
|
+
],
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
amount: params.amountWei,
|
|
152
|
+
asset: WETH_ADDRESS,
|
|
153
|
+
marketId: params.marketId.address,
|
|
154
|
+
apy: marketInfo.apy.total,
|
|
155
|
+
transactionData: {
|
|
156
|
+
openPosition: {
|
|
157
|
+
to: gatewayAddress,
|
|
158
|
+
data: depositCallData,
|
|
159
|
+
value: params.amountWei, // Send ETH as msg.value
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
slippage: params.options?.slippage ?? 50,
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Open position for standard ERC-20 tokens
|
|
168
|
+
* @description Standard approve + supply flow for non-WETH assets
|
|
169
|
+
*/
|
|
170
|
+
private async _openERC20Position(
|
|
171
|
+
params: LendOpenPositionInternalParams,
|
|
172
|
+
poolAddress: Address,
|
|
173
|
+
marketInfo: LendMarket,
|
|
174
|
+
): Promise<LendTransaction> {
|
|
175
|
+
// Get asset address for the chain
|
|
176
|
+
const assetAddress = params.asset.address[params.marketId.chainId]
|
|
177
|
+
if (!assetAddress) {
|
|
178
|
+
throw new Error(`Asset not supported on chain ${params.marketId.chainId}`)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Generate approval transaction
|
|
182
|
+
const approvalCallData = encodeFunctionData({
|
|
183
|
+
abi: erc20Abi,
|
|
184
|
+
functionName: 'approve',
|
|
185
|
+
args: [poolAddress, params.amountWei],
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// Generate supply transaction
|
|
189
|
+
const supplyCallData = encodeFunctionData({
|
|
190
|
+
abi: POOL_ABI,
|
|
191
|
+
functionName: 'supply',
|
|
192
|
+
args: [
|
|
193
|
+
assetAddress, // asset
|
|
194
|
+
params.amountWei, // amount
|
|
195
|
+
params.walletAddress, // onBehalfOf
|
|
196
|
+
0, // referralCode
|
|
197
|
+
],
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
amount: params.amountWei,
|
|
202
|
+
asset: assetAddress,
|
|
203
|
+
marketId: params.marketId.address,
|
|
204
|
+
apy: marketInfo.apy.total,
|
|
205
|
+
transactionData: {
|
|
206
|
+
approval: {
|
|
207
|
+
to: assetAddress,
|
|
208
|
+
data: approvalCallData,
|
|
209
|
+
value: 0n,
|
|
210
|
+
},
|
|
211
|
+
openPosition: {
|
|
212
|
+
to: poolAddress,
|
|
213
|
+
data: supplyCallData,
|
|
214
|
+
value: 0n,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
slippage: params.options?.slippage ?? 50,
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Close a position in an Aave market
|
|
223
|
+
* @description Withdraws assets from an Aave reserve
|
|
224
|
+
* @param params - Position closing operation parameters
|
|
225
|
+
* @returns Promise resolving to withdrawal transaction details
|
|
226
|
+
*/
|
|
227
|
+
protected async _closePosition(
|
|
228
|
+
params: LendClosePositionParams,
|
|
229
|
+
): Promise<LendTransaction> {
|
|
230
|
+
try {
|
|
231
|
+
// Get Pool address for this chain
|
|
232
|
+
const poolAddress = getPoolAddress(params.marketId.chainId)
|
|
233
|
+
if (!poolAddress) {
|
|
234
|
+
throw new Error(
|
|
235
|
+
`Aave V3 not deployed on chain ${params.marketId.chainId}`,
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const marketInfo = await this.getMarket({
|
|
240
|
+
address: params.marketId.address,
|
|
241
|
+
chainId: params.marketId.chainId,
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
// Check if this is a WETH market
|
|
245
|
+
if (this.isWETHMarket(params.marketId)) {
|
|
246
|
+
return this._closeWETHPosition(params, poolAddress, marketInfo)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Standard ERC-20 flow
|
|
250
|
+
return this._closeERC20Position(params, poolAddress, marketInfo)
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`Failed to close position: ${
|
|
254
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
255
|
+
}`,
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Close position for WETH market using WETHGateway
|
|
262
|
+
* @description Withdraws aWETH, unwraps to ETH, and sends to user
|
|
263
|
+
*/
|
|
264
|
+
private async _closeWETHPosition(
|
|
265
|
+
params: LendClosePositionParams,
|
|
266
|
+
poolAddress: Address,
|
|
267
|
+
marketInfo: LendMarket,
|
|
268
|
+
): Promise<LendTransaction> {
|
|
269
|
+
const gatewayAddress = getWETHGatewayAddress(params.marketId.chainId)
|
|
270
|
+
if (!gatewayAddress) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
`WETHGateway not available on chain ${params.marketId.chainId}`,
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Get the aToken address for the underlying WETH asset
|
|
277
|
+
// Note: params.marketId.address is the underlying WETH address, not the aToken
|
|
278
|
+
const { getATokenAddress } = await import('./sdk.js')
|
|
279
|
+
const aWETHAddress = await getATokenAddress({
|
|
280
|
+
underlyingAsset: params.marketId.address,
|
|
281
|
+
chainId: params.marketId.chainId,
|
|
282
|
+
chainManager: this.chainManager,
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
// First: User must approve aWETH to WETHGateway
|
|
286
|
+
const approvalCallData = encodeFunctionData({
|
|
287
|
+
abi: erc20Abi,
|
|
288
|
+
functionName: 'approve',
|
|
289
|
+
args: [gatewayAddress, params.amount],
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
// Second: Call withdrawETH on gateway
|
|
293
|
+
const withdrawCallData = encodeFunctionData({
|
|
294
|
+
abi: WETH_GATEWAY_ABI,
|
|
295
|
+
functionName: 'withdrawETH',
|
|
296
|
+
args: [
|
|
297
|
+
poolAddress, // pool
|
|
298
|
+
params.amount, // amount
|
|
299
|
+
params.walletAddress, // to (receives native ETH)
|
|
300
|
+
],
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
amount: params.amount,
|
|
305
|
+
asset: WETH_ADDRESS,
|
|
306
|
+
marketId: params.marketId.address,
|
|
307
|
+
apy: marketInfo.apy.total,
|
|
308
|
+
transactionData: {
|
|
309
|
+
approval: {
|
|
310
|
+
to: aWETHAddress,
|
|
311
|
+
data: approvalCallData,
|
|
312
|
+
value: 0n,
|
|
313
|
+
},
|
|
314
|
+
closePosition: {
|
|
315
|
+
to: gatewayAddress,
|
|
316
|
+
data: withdrawCallData,
|
|
317
|
+
value: 0n,
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
slippage: params.options?.slippage ?? 50,
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Close position for standard ERC-20 tokens
|
|
326
|
+
*/
|
|
327
|
+
private async _closeERC20Position(
|
|
328
|
+
params: LendClosePositionParams,
|
|
329
|
+
poolAddress: Address,
|
|
330
|
+
marketInfo: LendMarket,
|
|
331
|
+
): Promise<LendTransaction> {
|
|
332
|
+
// Get asset address for the market's chain
|
|
333
|
+
const assetAddress = getAssetAddress(
|
|
334
|
+
marketInfo.asset,
|
|
335
|
+
params.marketId.chainId,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
// Generate withdraw transaction
|
|
339
|
+
const withdrawCallData = encodeFunctionData({
|
|
340
|
+
abi: POOL_ABI,
|
|
341
|
+
functionName: 'withdraw',
|
|
342
|
+
args: [
|
|
343
|
+
assetAddress, // asset
|
|
344
|
+
params.amount, // amount
|
|
345
|
+
params.walletAddress, // to
|
|
346
|
+
],
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
amount: params.amount,
|
|
351
|
+
asset: assetAddress,
|
|
352
|
+
marketId: params.marketId.address,
|
|
353
|
+
apy: marketInfo.apy.total,
|
|
354
|
+
transactionData: {
|
|
355
|
+
closePosition: {
|
|
356
|
+
to: poolAddress,
|
|
357
|
+
data: withdrawCallData,
|
|
358
|
+
value: 0n,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
slippage: params.options?.slippage ?? 50,
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Get detailed market information
|
|
367
|
+
* @param marketId - Market identifier containing address and chainId
|
|
368
|
+
* @returns Promise resolving to market information
|
|
369
|
+
*/
|
|
370
|
+
protected async _getMarket(marketId: LendMarketId): Promise<LendMarket> {
|
|
371
|
+
return getReserve({
|
|
372
|
+
marketId,
|
|
373
|
+
chainManager: this.chainManager,
|
|
374
|
+
lendConfig: this._config,
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get list of available lending markets
|
|
380
|
+
* @param params - Filtering parameters
|
|
381
|
+
* @returns Promise resolving to array of market information
|
|
382
|
+
*/
|
|
383
|
+
protected async _getMarkets(
|
|
384
|
+
params: GetLendMarketsParams,
|
|
385
|
+
): Promise<LendMarket[]> {
|
|
386
|
+
const marketConfigs = params.markets || []
|
|
387
|
+
|
|
388
|
+
return getReserves({
|
|
389
|
+
chainManager: this.chainManager,
|
|
390
|
+
lendConfig: this._config,
|
|
391
|
+
markets: marketConfigs,
|
|
392
|
+
})
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get position for a specific wallet address
|
|
397
|
+
* @param params - Parameters for fetching position
|
|
398
|
+
* @returns Promise resolving to position information
|
|
399
|
+
*/
|
|
400
|
+
protected async _getPosition(
|
|
401
|
+
params: GetMarketBalanceParams,
|
|
402
|
+
): Promise<LendMarketPosition> {
|
|
403
|
+
try {
|
|
404
|
+
const publicClient = this.chainManager.getPublicClient(
|
|
405
|
+
params.marketId.chainId,
|
|
406
|
+
)
|
|
407
|
+
const market = await this._getMarket(params.marketId)
|
|
408
|
+
const poolAddress = getPoolAddress(params.marketId.chainId)
|
|
409
|
+
|
|
410
|
+
if (!poolAddress) {
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Aave V3 not deployed on chain ${params.marketId.chainId}`,
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Get the aToken address from Pool.getReserveData
|
|
417
|
+
const assetAddress = getAssetAddress(
|
|
418
|
+
market.asset,
|
|
419
|
+
params.marketId.chainId,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
const reserveData = (await publicClient.readContract({
|
|
423
|
+
address: poolAddress,
|
|
424
|
+
abi: parseAbi([
|
|
425
|
+
'struct ReserveData { uint256 configuration; uint128 liquidityIndex; uint128 currentLiquidityRate; uint128 variableBorrowIndex; uint128 currentVariableBorrowRate; uint128 currentStableBorrowRate; uint40 lastUpdateTimestamp; uint16 id; address aTokenAddress; address stableDebtTokenAddress; address variableDebtTokenAddress; address interestRateStrategyAddress; uint128 accruedToTreasury; uint128 unbacked; uint128 isolationModeTotalDebt; }',
|
|
426
|
+
'function getReserveData(address asset) view returns (ReserveData)',
|
|
427
|
+
]),
|
|
428
|
+
functionName: 'getReserveData',
|
|
429
|
+
args: [assetAddress],
|
|
430
|
+
})) as {
|
|
431
|
+
aTokenAddress: Address
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const aTokenAddress = reserveData.aTokenAddress
|
|
435
|
+
|
|
436
|
+
const balance = await publicClient.readContract({
|
|
437
|
+
address: aTokenAddress,
|
|
438
|
+
abi: erc20Abi,
|
|
439
|
+
functionName: 'balanceOf',
|
|
440
|
+
args: [params.walletAddress],
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
const balanceFormatted = formatUnits(
|
|
444
|
+
balance,
|
|
445
|
+
market.asset.metadata.decimals,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
balance,
|
|
450
|
+
balanceFormatted,
|
|
451
|
+
shares: balance, // In Aave, aTokens are 1:1 with underlying
|
|
452
|
+
sharesFormatted: balanceFormatted,
|
|
453
|
+
marketId: params.marketId,
|
|
454
|
+
}
|
|
455
|
+
} catch (error) {
|
|
456
|
+
throw new Error(
|
|
457
|
+
`Failed to get market balance for ${params.walletAddress} in market ${params.marketId.address}: ${
|
|
458
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
459
|
+
}`,
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
import { base, baseSepolia, optimism, optimismSepolia } from 'viem/chains'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Aave V3 Pool addresses for Optimism Superchain networks
|
|
6
|
+
* @description Hardcoded Pool contract addresses for each supported chain
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Mainnet Pool addresses
|
|
11
|
+
*/
|
|
12
|
+
export const POOL_ADDRESSES_MAINNET: Record<number, Address> = {
|
|
13
|
+
[optimism.id]: '0x794a61358D6845594F94dc1DB02A252b5b4814aD',
|
|
14
|
+
[base.id]: '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5',
|
|
15
|
+
} as const
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Testnet Pool addresses
|
|
19
|
+
*/
|
|
20
|
+
export const POOL_ADDRESSES_TESTNET: Record<number, Address> = {
|
|
21
|
+
[optimismSepolia.id]: '0xb50201558b00496a145fe76f7424749556e326d8',
|
|
22
|
+
[baseSepolia.id]: '0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27',
|
|
23
|
+
} as const
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* All Pool addresses (mainnet + testnet)
|
|
27
|
+
*/
|
|
28
|
+
export const POOL_ADDRESSES: Record<number, Address> = {
|
|
29
|
+
...POOL_ADDRESSES_MAINNET,
|
|
30
|
+
...POOL_ADDRESSES_TESTNET,
|
|
31
|
+
} as const
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get Pool address for a given chain ID
|
|
35
|
+
* @param chainId - Chain ID
|
|
36
|
+
* @returns Pool address if supported, undefined otherwise
|
|
37
|
+
*/
|
|
38
|
+
export function getPoolAddress(chainId: number): Address | undefined {
|
|
39
|
+
return POOL_ADDRESSES[chainId]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if a chain ID has Aave V3 deployed
|
|
44
|
+
* @param chainId - Chain ID to check
|
|
45
|
+
* @returns true if Aave V3 is deployed on this chain
|
|
46
|
+
*/
|
|
47
|
+
export function isAaveChainSupported(chainId: number): boolean {
|
|
48
|
+
return chainId in POOL_ADDRESSES
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get all supported chain IDs
|
|
53
|
+
* @returns Array of chain IDs with Aave V3 deployed
|
|
54
|
+
*/
|
|
55
|
+
export function getSupportedChainIds(): number[] {
|
|
56
|
+
return Object.keys(POOL_ADDRESSES).map(Number)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Aave V3 WETHGateway addresses for Optimism Superchain networks
|
|
61
|
+
* @description Gateway contracts that handle native ETH wrapping and depositing
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Mainnet WETHGateway addresses
|
|
66
|
+
*/
|
|
67
|
+
export const WETH_GATEWAY_ADDRESSES_MAINNET: Record<number, Address> = {
|
|
68
|
+
[optimism.id]: '0x5f2508cAE9923b02316254026CD43d7902866725',
|
|
69
|
+
[base.id]: '0xa0d9C1E9E48Ca30c8d8C3B5D69FF5dc1f6DFfC24',
|
|
70
|
+
} as const
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Testnet WETHGateway addresses
|
|
74
|
+
*/
|
|
75
|
+
export const WETH_GATEWAY_ADDRESSES_TESTNET: Record<number, Address> = {
|
|
76
|
+
[optimismSepolia.id]: '0x589750BA8aF186cE5B55391B0b7148cAD43a1619',
|
|
77
|
+
[baseSepolia.id]: '0x0568130e794429D2eEBC4dafE18f25Ff1a1ed8b6',
|
|
78
|
+
} as const
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* All WETHGateway addresses (mainnet + testnet)
|
|
82
|
+
*/
|
|
83
|
+
export const WETH_GATEWAY_ADDRESSES: Record<number, Address> = {
|
|
84
|
+
...WETH_GATEWAY_ADDRESSES_MAINNET,
|
|
85
|
+
...WETH_GATEWAY_ADDRESSES_TESTNET,
|
|
86
|
+
} as const
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get WETHGateway address for a given chain ID
|
|
90
|
+
* @param chainId - Chain ID
|
|
91
|
+
* @returns WETHGateway address if supported, undefined otherwise
|
|
92
|
+
*/
|
|
93
|
+
export function getWETHGatewayAddress(chainId: number): Address | undefined {
|
|
94
|
+
return WETH_GATEWAY_ADDRESSES[chainId]
|
|
95
|
+
}
|