@aptos-labs/cross-chain-core 6.0.0 → 6.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/CrossChainCore.d.ts +2 -2
- package/dist/CrossChainCore.d.ts.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/mainnet/chains.d.ts +1 -1
- package/dist/config/mainnet/chains.d.ts.map +1 -1
- package/dist/config/mainnet/tokens.d.ts +1 -1
- package/dist/config/mainnet/tokens.d.ts.map +1 -1
- package/dist/config/testnet/chains.d.ts +1 -1
- package/dist/config/testnet/chains.d.ts.map +1 -1
- package/dist/config/testnet/tokens.d.ts +1 -1
- package/dist/config/testnet/tokens.d.ts.map +1 -1
- package/dist/config/types.d.ts +1 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1366 -1297
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1377 -1302
- package/dist/index.mjs.map +1 -1
- package/dist/providers/wormhole/index.d.ts +4 -4
- package/dist/providers/wormhole/index.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +5 -5
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/AptosSigner.d.ts +6 -6
- package/dist/providers/wormhole/signers/AptosSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts +3 -3
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/Signer.d.ts +6 -6
- package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/SolanaLocalSigner.d.ts +4 -4
- package/dist/providers/wormhole/signers/SolanaLocalSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts +8 -9
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/SuiSigner.d.ts +3 -3
- package/dist/providers/wormhole/signers/SuiSigner.d.ts.map +1 -1
- package/dist/providers/wormhole/signers/solanaUtils.d.ts +1 -1
- package/dist/providers/wormhole/signers/solanaUtils.d.ts.map +1 -1
- package/dist/providers/wormhole/types.d.ts +10 -4
- package/dist/providers/wormhole/types.d.ts.map +1 -1
- package/dist/providers/wormhole/utils.d.ts +2 -2
- package/dist/providers/wormhole/utils.d.ts.map +1 -1
- package/dist/providers/wormhole/wormhole.d.ts +3 -3
- package/dist/providers/wormhole/wormhole.d.ts.map +1 -1
- package/dist/utils/getUsdcBalance.d.ts +1 -1
- package/dist/utils/getUsdcBalance.d.ts.map +1 -1
- package/dist/utils/receiptSerialization.d.ts +1 -1
- package/dist/utils/receiptSerialization.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +6 -8
- package/src/CrossChainCore.ts +15 -17
- package/src/config/index.ts +1 -1
- package/src/config/mainnet/chains.ts +1 -1
- package/src/config/mainnet/tokens.ts +1 -1
- package/src/config/testnet/chains.ts +1 -1
- package/src/config/testnet/tokens.ts +1 -1
- package/src/config/types.ts +1 -1
- package/src/index.ts +1 -1
- package/src/providers/wormhole/index.ts +4 -4
- package/src/providers/wormhole/signers/AptosLocalSigner.ts +12 -16
- package/src/providers/wormhole/signers/AptosSigner.ts +29 -22
- package/src/providers/wormhole/signers/EthereumSigner.ts +6 -6
- package/src/providers/wormhole/signers/Signer.ts +20 -22
- package/src/providers/wormhole/signers/SolanaLocalSigner.ts +7 -7
- package/src/providers/wormhole/signers/SolanaSigner.ts +13 -14
- package/src/providers/wormhole/signers/SuiSigner.ts +8 -8
- package/src/providers/wormhole/signers/solanaUtils.ts +43 -25
- package/src/providers/wormhole/types.ts +28 -16
- package/src/providers/wormhole/utils.ts +3 -4
- package/src/providers/wormhole/wormhole.ts +50 -48
- package/src/utils/getUsdcBalance.ts +8 -10
- package/src/utils/receiptSerialization.ts +2 -3
- package/src/version.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,123 +1,353 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Network as Network4 } from "@aptos-labs/ts-sdk";
|
|
3
|
+
|
|
1
4
|
// src/CrossChainCore.ts
|
|
2
5
|
import { Network as Network3 } from "@aptos-labs/ts-sdk";
|
|
3
6
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import aptos from "@wormhole-foundation/sdk/aptos";
|
|
13
|
-
import solana from "@wormhole-foundation/sdk/solana";
|
|
14
|
-
import evm from "@wormhole-foundation/sdk/evm";
|
|
15
|
-
import sui from "@wormhole-foundation/sdk/sui";
|
|
7
|
+
// src/config/types.ts
|
|
8
|
+
var Context = /* @__PURE__ */ ((Context2) => {
|
|
9
|
+
Context2["ETH"] = "Ethereum";
|
|
10
|
+
Context2["SOLANA"] = "Solana";
|
|
11
|
+
Context2["APTOS"] = "Aptos";
|
|
12
|
+
Context2["SUI"] = "Sui";
|
|
13
|
+
return Context2;
|
|
14
|
+
})(Context || {});
|
|
16
15
|
|
|
17
|
-
// src/
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
// src/config/mainnet/chains.ts
|
|
17
|
+
var mainnetChains = {
|
|
18
|
+
Ethereum: {
|
|
19
|
+
key: "Ethereum",
|
|
20
|
+
context: "Ethereum" /* ETH */,
|
|
21
|
+
displayName: "Ethereum",
|
|
22
|
+
explorerUrl: "https://etherscan.io/",
|
|
23
|
+
explorerName: "Etherscan",
|
|
24
|
+
chainId: 1,
|
|
25
|
+
icon: "Ethereum",
|
|
26
|
+
symbol: "ETH",
|
|
27
|
+
defaultRpc: "https://rpc.ankr.com/eth"
|
|
28
|
+
},
|
|
29
|
+
Solana: {
|
|
30
|
+
key: "Solana",
|
|
31
|
+
context: "Solana" /* SOLANA */,
|
|
32
|
+
displayName: "Solana",
|
|
33
|
+
explorerUrl: "https://solscan.io",
|
|
34
|
+
explorerName: "Solscan",
|
|
35
|
+
chainId: 0,
|
|
36
|
+
icon: "Solana",
|
|
37
|
+
symbol: "SOL",
|
|
38
|
+
defaultRpc: "https://solana-rpc.publicnode.com"
|
|
39
|
+
},
|
|
40
|
+
Aptos: {
|
|
41
|
+
key: "Aptos",
|
|
42
|
+
context: "Aptos" /* APTOS */,
|
|
43
|
+
displayName: "Aptos",
|
|
44
|
+
explorerUrl: "https://explorer.aptoslabs.com/",
|
|
45
|
+
explorerName: "Aptos Explorer",
|
|
46
|
+
chainId: 0,
|
|
47
|
+
icon: "Aptos",
|
|
48
|
+
symbol: "APT",
|
|
49
|
+
defaultRpc: "https://fullnode.mainnet.aptos.dev"
|
|
50
|
+
},
|
|
51
|
+
Avalanche: {
|
|
52
|
+
key: "Avalanche",
|
|
53
|
+
context: "Ethereum" /* ETH */,
|
|
54
|
+
chainId: 43114,
|
|
55
|
+
displayName: "Avalanche",
|
|
56
|
+
explorerUrl: "https://snowtrace.io",
|
|
57
|
+
explorerName: "Avascan",
|
|
58
|
+
icon: "Avalanche",
|
|
59
|
+
symbol: "AVAX",
|
|
60
|
+
defaultRpc: "https://avalanche-c-chain-rpc.publicnode.com"
|
|
61
|
+
},
|
|
62
|
+
Base: {
|
|
63
|
+
key: "Base",
|
|
64
|
+
context: "Ethereum" /* ETH */,
|
|
65
|
+
chainId: 8453,
|
|
66
|
+
displayName: "Base",
|
|
67
|
+
explorerUrl: "https://basescan.org",
|
|
68
|
+
explorerName: "BaseScan",
|
|
69
|
+
icon: "Base",
|
|
70
|
+
symbol: "BASE",
|
|
71
|
+
defaultRpc: "https://mainnet.base.org"
|
|
72
|
+
},
|
|
73
|
+
Arbitrum: {
|
|
74
|
+
key: "Arbitrum",
|
|
75
|
+
context: "Ethereum" /* ETH */,
|
|
76
|
+
chainId: 42161,
|
|
77
|
+
displayName: "Arbitrum",
|
|
78
|
+
explorerUrl: "https://arbiscan.io/",
|
|
79
|
+
explorerName: "Arbitrum Explorer",
|
|
80
|
+
icon: "Arbitrum",
|
|
81
|
+
symbol: "ARB",
|
|
82
|
+
defaultRpc: "https://arb1.arbitrum.io/rpc"
|
|
83
|
+
},
|
|
84
|
+
Polygon: {
|
|
85
|
+
key: "Polygon",
|
|
86
|
+
context: "Ethereum" /* ETH */,
|
|
87
|
+
chainId: 137,
|
|
88
|
+
displayName: "Polygon",
|
|
89
|
+
explorerUrl: "https://polygonscan.com/",
|
|
90
|
+
explorerName: "PolygonScan",
|
|
91
|
+
icon: "Polygon",
|
|
92
|
+
symbol: "MATIC",
|
|
93
|
+
defaultRpc: "https://polygon-bor-rpc.publicnode.com"
|
|
94
|
+
},
|
|
95
|
+
Sui: {
|
|
96
|
+
key: "Sui",
|
|
97
|
+
context: "Sui" /* SUI */,
|
|
98
|
+
displayName: "Sui",
|
|
99
|
+
explorerUrl: "https://suiscan.xyz/",
|
|
100
|
+
explorerName: "Suiscan",
|
|
101
|
+
chainId: 0,
|
|
102
|
+
icon: "Sui",
|
|
103
|
+
symbol: "SUI",
|
|
104
|
+
defaultRpc: "https://fullnode.mainnet.sui.io:443"
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/config/mainnet/tokens.ts
|
|
109
|
+
var mainnetTokens = {
|
|
110
|
+
Ethereum: {
|
|
111
|
+
symbol: "USDC",
|
|
112
|
+
tokenId: {
|
|
113
|
+
chain: "Ethereum",
|
|
114
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
115
|
+
},
|
|
116
|
+
icon: "USDC",
|
|
117
|
+
decimals: 6
|
|
118
|
+
},
|
|
119
|
+
Solana: {
|
|
120
|
+
symbol: "USDC",
|
|
121
|
+
tokenId: {
|
|
122
|
+
chain: "Solana",
|
|
123
|
+
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
|
124
|
+
},
|
|
125
|
+
icon: "USDC",
|
|
126
|
+
decimals: 6
|
|
127
|
+
},
|
|
128
|
+
Aptos: {
|
|
129
|
+
symbol: "USDC",
|
|
130
|
+
decimals: 6,
|
|
131
|
+
tokenId: {
|
|
132
|
+
chain: "Aptos",
|
|
133
|
+
address: "0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b"
|
|
134
|
+
},
|
|
135
|
+
icon: "USDC"
|
|
136
|
+
},
|
|
137
|
+
Base: {
|
|
138
|
+
symbol: "USDC",
|
|
139
|
+
decimals: 6,
|
|
140
|
+
icon: "USDC",
|
|
141
|
+
tokenId: {
|
|
142
|
+
chain: "Base",
|
|
143
|
+
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
|
|
22
144
|
}
|
|
23
145
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
146
|
+
Arbitrum: {
|
|
147
|
+
symbol: "USDC",
|
|
148
|
+
decimals: 6,
|
|
149
|
+
icon: "USDC",
|
|
150
|
+
tokenId: {
|
|
151
|
+
chain: "Arbitrum",
|
|
152
|
+
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
|
|
27
153
|
}
|
|
28
154
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
155
|
+
Avalanche: {
|
|
156
|
+
symbol: "USDC",
|
|
157
|
+
decimals: 6,
|
|
158
|
+
icon: "USDC",
|
|
159
|
+
tokenId: {
|
|
160
|
+
chain: "Avalanche",
|
|
161
|
+
address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
Polygon: {
|
|
165
|
+
symbol: "USDC",
|
|
166
|
+
decimals: 6,
|
|
167
|
+
icon: "USDC",
|
|
168
|
+
tokenId: {
|
|
169
|
+
chain: "Polygon",
|
|
170
|
+
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
|
|
32
171
|
}
|
|
172
|
+
},
|
|
173
|
+
Sui: {
|
|
174
|
+
symbol: "USDC",
|
|
175
|
+
decimals: 6,
|
|
176
|
+
tokenId: {
|
|
177
|
+
chain: "Sui",
|
|
178
|
+
address: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
|
|
179
|
+
},
|
|
180
|
+
icon: "USDC"
|
|
33
181
|
}
|
|
34
182
|
};
|
|
35
183
|
|
|
36
|
-
// src/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
184
|
+
// src/config/testnet/chains.ts
|
|
185
|
+
var testnetChains = {
|
|
186
|
+
Sepolia: {
|
|
187
|
+
key: "Sepolia",
|
|
188
|
+
context: "Ethereum" /* ETH */,
|
|
189
|
+
chainId: 11155111,
|
|
190
|
+
displayName: "Sepolia",
|
|
191
|
+
explorerUrl: "https://sepolia.etherscan.io/",
|
|
192
|
+
explorerName: "Etherscan",
|
|
193
|
+
icon: "Ethereum",
|
|
194
|
+
symbol: "ETH",
|
|
195
|
+
defaultRpc: "https://ethereum-sepolia-rpc.publicnode.com"
|
|
196
|
+
},
|
|
197
|
+
BaseSepolia: {
|
|
198
|
+
key: "BaseSepolia",
|
|
199
|
+
context: "Ethereum" /* ETH */,
|
|
200
|
+
chainId: 84532,
|
|
201
|
+
displayName: "Base Sepolia",
|
|
202
|
+
explorerUrl: "https://sepolia.basescan.org",
|
|
203
|
+
explorerName: "Basescan",
|
|
204
|
+
icon: "BaseSepolia",
|
|
205
|
+
symbol: "BASE",
|
|
206
|
+
defaultRpc: "https://chain-proxy.wallet.coinbase.com?targetName=base-sepolia"
|
|
207
|
+
},
|
|
208
|
+
ArbitrumSepolia: {
|
|
209
|
+
key: "ArbitrumSepolia",
|
|
210
|
+
context: "Ethereum" /* ETH */,
|
|
211
|
+
chainId: 421614,
|
|
212
|
+
displayName: "Arbitrum Sepolia",
|
|
213
|
+
explorerUrl: "https://sepolia.arbiscan.io",
|
|
214
|
+
explorerName: "Etherscan",
|
|
215
|
+
icon: "Arbitrum",
|
|
216
|
+
symbol: "ARB",
|
|
217
|
+
defaultRpc: "https://sepolia-rollup.arbitrum.io/rpc"
|
|
218
|
+
},
|
|
219
|
+
Avalanche: {
|
|
220
|
+
key: "Avalanche",
|
|
221
|
+
context: "Ethereum" /* ETH */,
|
|
222
|
+
chainId: 43113,
|
|
223
|
+
displayName: "Avalanche Fuji",
|
|
224
|
+
explorerUrl: "https://testnet.snowtrace.io",
|
|
225
|
+
explorerName: "Avascan",
|
|
226
|
+
icon: "Avalanche",
|
|
227
|
+
symbol: "AVAX",
|
|
228
|
+
defaultRpc: "https://api.avax-test.network/ext/bc/C/rpc"
|
|
229
|
+
},
|
|
230
|
+
PolygonSepolia: {
|
|
231
|
+
key: "PolygonSepolia",
|
|
232
|
+
context: "Ethereum" /* ETH */,
|
|
233
|
+
chainId: 80002,
|
|
234
|
+
displayName: "Polygon",
|
|
235
|
+
explorerUrl: "https://amoy.polygonscan.com/",
|
|
236
|
+
explorerName: "PolygonScan",
|
|
237
|
+
icon: "Polygon",
|
|
238
|
+
symbol: "MATIC",
|
|
239
|
+
defaultRpc: "https://rpc-amoy.polygon.technology/"
|
|
240
|
+
},
|
|
241
|
+
Solana: {
|
|
242
|
+
key: "Solana",
|
|
243
|
+
context: "Solana" /* SOLANA */,
|
|
244
|
+
displayName: "Solana",
|
|
245
|
+
explorerUrl: "https://solscan.io",
|
|
246
|
+
explorerName: "Solscan",
|
|
247
|
+
chainId: 0,
|
|
248
|
+
icon: "Solana",
|
|
249
|
+
symbol: "SOL",
|
|
250
|
+
defaultRpc: "https://api.devnet.solana.com"
|
|
251
|
+
},
|
|
252
|
+
Aptos: {
|
|
253
|
+
key: "Aptos",
|
|
254
|
+
context: "Aptos" /* APTOS */,
|
|
255
|
+
displayName: "Aptos",
|
|
256
|
+
explorerUrl: "https://explorer.aptoslabs.com?network=testnet",
|
|
257
|
+
explorerName: "Aptos Explorer",
|
|
258
|
+
chainId: 0,
|
|
259
|
+
icon: "Aptos",
|
|
260
|
+
symbol: "APT",
|
|
261
|
+
defaultRpc: "https://fullnode.testnet.aptos.dev"
|
|
262
|
+
},
|
|
263
|
+
Sui: {
|
|
264
|
+
key: "Sui",
|
|
265
|
+
context: "Sui" /* SUI */,
|
|
266
|
+
displayName: "Sui",
|
|
267
|
+
explorerUrl: "https://suiscan.xyz/testnet",
|
|
268
|
+
explorerName: "Suiscan",
|
|
269
|
+
chainId: 0,
|
|
270
|
+
icon: "Sui",
|
|
271
|
+
symbol: "SUI",
|
|
272
|
+
defaultRpc: "https://fullnode.testnet.sui.io:443"
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// src/config/testnet/tokens.ts
|
|
277
|
+
var testnetTokens = {
|
|
278
|
+
Sepolia: {
|
|
279
|
+
symbol: "USDC",
|
|
280
|
+
icon: "USDC",
|
|
281
|
+
decimals: 6,
|
|
282
|
+
tokenId: {
|
|
283
|
+
chain: "Sepolia",
|
|
284
|
+
address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
116
285
|
}
|
|
117
|
-
|
|
286
|
+
},
|
|
287
|
+
Solana: {
|
|
288
|
+
symbol: "USDC",
|
|
289
|
+
tokenId: {
|
|
290
|
+
chain: "Solana",
|
|
291
|
+
address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
|
|
292
|
+
},
|
|
293
|
+
icon: "USDC",
|
|
294
|
+
decimals: 6
|
|
295
|
+
},
|
|
296
|
+
Aptos: {
|
|
297
|
+
symbol: "USDC",
|
|
298
|
+
decimals: 6,
|
|
299
|
+
tokenId: {
|
|
300
|
+
chain: "Aptos",
|
|
301
|
+
address: "0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832"
|
|
302
|
+
},
|
|
303
|
+
icon: "USDC"
|
|
304
|
+
},
|
|
305
|
+
BaseSepolia: {
|
|
306
|
+
symbol: "USDC",
|
|
307
|
+
icon: "USDC",
|
|
308
|
+
decimals: 6,
|
|
309
|
+
tokenId: {
|
|
310
|
+
chain: "BaseSepolia",
|
|
311
|
+
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
Avalanche: {
|
|
315
|
+
symbol: "USDC",
|
|
316
|
+
icon: "USDC",
|
|
317
|
+
decimals: 6,
|
|
318
|
+
tokenId: {
|
|
319
|
+
chain: "Avalanche",
|
|
320
|
+
address: "0x5425890298aed601595a70AB815c96711a31Bc65"
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
ArbitrumSepolia: {
|
|
324
|
+
symbol: "USDC",
|
|
325
|
+
icon: "USDC",
|
|
326
|
+
decimals: 6,
|
|
327
|
+
tokenId: {
|
|
328
|
+
chain: "ArbitrumSepolia",
|
|
329
|
+
address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d"
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
PolygonSepolia: {
|
|
333
|
+
symbol: "USDC",
|
|
334
|
+
icon: "USDC",
|
|
335
|
+
decimals: 6,
|
|
336
|
+
tokenId: {
|
|
337
|
+
chain: "PolygonSepolia",
|
|
338
|
+
address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
Sui: {
|
|
342
|
+
symbol: "USDC",
|
|
343
|
+
tokenId: {
|
|
344
|
+
chain: "Sui",
|
|
345
|
+
address: "0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC"
|
|
346
|
+
},
|
|
347
|
+
icon: "USDC",
|
|
348
|
+
decimals: 6
|
|
118
349
|
}
|
|
119
|
-
|
|
120
|
-
}
|
|
350
|
+
};
|
|
121
351
|
|
|
122
352
|
// src/providers/wormhole/signers/AptosLocalSigner.ts
|
|
123
353
|
import {
|
|
@@ -134,6 +364,14 @@ function validateExpireTimestamp(value) {
|
|
|
134
364
|
}
|
|
135
365
|
}
|
|
136
366
|
var TransferError = class extends Error {
|
|
367
|
+
/** Source-chain burn transaction hash — available when the burn succeeded before the failure. */
|
|
368
|
+
originChainTxnId;
|
|
369
|
+
/**
|
|
370
|
+
* The underlying error that caused this failure.
|
|
371
|
+
* Mirrors ES2022 Error.cause — declared explicitly because the project's
|
|
372
|
+
* TypeScript lib target does not include ES2022 ErrorOptions.
|
|
373
|
+
*/
|
|
374
|
+
cause;
|
|
137
375
|
constructor(message, originChainTxnId, cause) {
|
|
138
376
|
super(message);
|
|
139
377
|
this.name = "TransferError";
|
|
@@ -142,6 +380,16 @@ var TransferError = class extends Error {
|
|
|
142
380
|
}
|
|
143
381
|
};
|
|
144
382
|
var WithdrawError = class extends Error {
|
|
383
|
+
/** Aptos burn transaction hash — always available when this error is thrown. */
|
|
384
|
+
originChainTxnId;
|
|
385
|
+
/** The withdraw phase that failed ("tracking" or "claiming"). */
|
|
386
|
+
phase;
|
|
387
|
+
/**
|
|
388
|
+
* The underlying error that caused this failure.
|
|
389
|
+
* Mirrors ES2022 Error.cause — declared explicitly because the project's
|
|
390
|
+
* TypeScript lib target does not include ES2022 ErrorOptions.
|
|
391
|
+
*/
|
|
392
|
+
cause;
|
|
145
393
|
constructor(message, originChainTxnId, phase, cause) {
|
|
146
394
|
super(message);
|
|
147
395
|
this.name = "WithdrawError";
|
|
@@ -153,8 +401,14 @@ var WithdrawError = class extends Error {
|
|
|
153
401
|
|
|
154
402
|
// src/providers/wormhole/signers/AptosLocalSigner.ts
|
|
155
403
|
var AptosLocalSigner = class {
|
|
404
|
+
_chain;
|
|
405
|
+
_options;
|
|
406
|
+
_wallet;
|
|
407
|
+
_sponsorAccount;
|
|
408
|
+
_onTransactionSigned;
|
|
409
|
+
_crossChainCore;
|
|
410
|
+
_claimedTransactionHashes = [];
|
|
156
411
|
constructor(chain, options, wallet, feePayerAccount, crossChainCore, onTransactionSigned) {
|
|
157
|
-
this._claimedTransactionHashes = [];
|
|
158
412
|
this._chain = chain;
|
|
159
413
|
this._options = options;
|
|
160
414
|
this._wallet = wallet;
|
|
@@ -215,7 +469,7 @@ async function signAndSendTransaction(request, wallet, sponsorAccount, crossChai
|
|
|
215
469
|
const txnToSign = await aptos2.transaction.build.simple({
|
|
216
470
|
data: payload,
|
|
217
471
|
sender: wallet.accountAddress.toString(),
|
|
218
|
-
withFeePayer: sponsorAccount
|
|
472
|
+
withFeePayer: !!sponsorAccount,
|
|
219
473
|
...typeof expireTimestamp !== "undefined" ? { options: { expireTimestamp } } : {}
|
|
220
474
|
});
|
|
221
475
|
const senderAuthenticator = await aptos2.transaction.sign({
|
|
@@ -240,125 +494,36 @@ async function signAndSendTransaction(request, wallet, sponsorAccount, crossChai
|
|
|
240
494
|
return tx.hash;
|
|
241
495
|
}
|
|
242
496
|
|
|
243
|
-
// src/providers/wormhole/signers/
|
|
497
|
+
// src/providers/wormhole/signers/SolanaLocalSigner.ts
|
|
244
498
|
import {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (useGasStation) {
|
|
269
|
-
const gasStationClient = new GasStationClient({
|
|
270
|
-
network: dappNetwork,
|
|
271
|
-
apiKey: sponsorAccount[dappNetwork]
|
|
272
|
-
});
|
|
273
|
-
const transactionSubmitter = new GasStationTransactionSubmitter(gasStationClient);
|
|
274
|
-
aptosConfig = new AptosConfig2({
|
|
275
|
-
network: dappNetwork,
|
|
276
|
-
pluginSettings: {
|
|
277
|
-
TRANSACTION_SUBMITTER: transactionSubmitter
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
} else {
|
|
281
|
-
aptosConfig = new AptosConfig2({
|
|
282
|
-
network: dappNetwork
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
const aptos2 = new Aptos2(aptosConfig);
|
|
286
|
-
const functionArguments = extractFunctionArguments(
|
|
287
|
-
payload.functionArguments
|
|
288
|
-
);
|
|
289
|
-
const withdrawFunction = "0x5e2d961f06cd27aa07554a39d55f5ce1e58dff35d803c3529b1cd5c4fa3ab584::withdraw::deposit_for_burn";
|
|
290
|
-
const transactionData = {
|
|
291
|
-
function: withdrawFunction,
|
|
292
|
-
functionArguments
|
|
499
|
+
Transaction
|
|
500
|
+
} from "@solana/web3.js";
|
|
501
|
+
|
|
502
|
+
// src/providers/wormhole/signers/solanaUtils.ts
|
|
503
|
+
import {
|
|
504
|
+
ComputeBudgetProgram,
|
|
505
|
+
LAMPORTS_PER_SOL
|
|
506
|
+
} from "@solana/web3.js";
|
|
507
|
+
import {
|
|
508
|
+
determinePriorityFee,
|
|
509
|
+
determinePriorityFeeTritonOne
|
|
510
|
+
} from "@wormhole-foundation/sdk-solana";
|
|
511
|
+
async function sendAndConfirmTransaction(serializedTx, blockhash, lastValidBlockHeight, config) {
|
|
512
|
+
const {
|
|
513
|
+
connection,
|
|
514
|
+
commitment,
|
|
515
|
+
retryIntervalMs = 5e3,
|
|
516
|
+
verbose = false
|
|
517
|
+
} = config;
|
|
518
|
+
const sendOptions = {
|
|
519
|
+
skipPreflight: true,
|
|
520
|
+
maxRetries: 0,
|
|
521
|
+
preflightCommitment: commitment
|
|
293
522
|
};
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const txnToSign = await aptos2.transaction.build.simple({
|
|
299
|
-
data: transactionData,
|
|
300
|
-
sender: (await wallet.features["aptos:account"]?.account()).address.toString(),
|
|
301
|
-
withFeePayer: sponsorAccount ? true : false,
|
|
302
|
-
...typeof expireTimestamp !== "undefined" ? { options: { expireTimestamp } } : {}
|
|
303
|
-
});
|
|
304
|
-
const response = await wallet.features["aptos:signTransaction"]?.signTransaction(txnToSign);
|
|
305
|
-
if (response?.status === UserResponseStatus.REJECTED) {
|
|
306
|
-
throw new Error("User has rejected the request");
|
|
307
|
-
}
|
|
308
|
-
const txnToSubmit = {
|
|
309
|
-
transaction: txnToSign,
|
|
310
|
-
senderAuthenticator: response.args
|
|
311
|
-
};
|
|
312
|
-
if (sponsorAccount && isAccount(sponsorAccount)) {
|
|
313
|
-
const feePayerSignerAuthenticator = aptos2.transaction.signAsFeePayer({
|
|
314
|
-
signer: sponsorAccount,
|
|
315
|
-
transaction: txnToSign
|
|
316
|
-
});
|
|
317
|
-
txnToSubmit.feePayerAuthenticator = feePayerSignerAuthenticator;
|
|
318
|
-
}
|
|
319
|
-
const txnSubmitted = await aptos2.transaction.submit.simple(txnToSubmit);
|
|
320
|
-
const tx = await aptos2.waitForTransaction({
|
|
321
|
-
transactionHash: txnSubmitted.hash
|
|
322
|
-
});
|
|
323
|
-
return tx.hash;
|
|
324
|
-
}
|
|
325
|
-
function extractFunctionArguments(functionArguments) {
|
|
326
|
-
const deserializer1 = new Deserializer(functionArguments[0].bcsToBytes());
|
|
327
|
-
const amount = deserializer1.deserializeU64();
|
|
328
|
-
const deserializer2 = new Deserializer(functionArguments[1].bcsToBytes());
|
|
329
|
-
const destination_domain = deserializer2.deserializeU32();
|
|
330
|
-
const mint_recipient = new AccountAddress(functionArguments[2].bcsToBytes());
|
|
331
|
-
const burn_token = new AccountAddress(functionArguments[3].bcsToBytes());
|
|
332
|
-
return [amount, destination_domain, mint_recipient, burn_token];
|
|
333
|
-
}
|
|
334
|
-
function isAccount(obj) {
|
|
335
|
-
return "accountAddress" in obj;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// src/providers/wormhole/signers/SolanaSigner.ts
|
|
339
|
-
import {
|
|
340
|
-
Transaction as Transaction2
|
|
341
|
-
} from "@solana/web3.js";
|
|
342
|
-
import { Connection as Connection2 } from "@solana/web3.js";
|
|
343
|
-
import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
|
|
344
|
-
|
|
345
|
-
// src/providers/wormhole/signers/solanaUtils.ts
|
|
346
|
-
import {
|
|
347
|
-
ComputeBudgetProgram,
|
|
348
|
-
LAMPORTS_PER_SOL
|
|
349
|
-
} from "@solana/web3.js";
|
|
350
|
-
import {
|
|
351
|
-
determinePriorityFee,
|
|
352
|
-
determinePriorityFeeTritonOne
|
|
353
|
-
} from "@wormhole-foundation/sdk-solana";
|
|
354
|
-
async function sendAndConfirmTransaction(serializedTx, blockhash, lastValidBlockHeight, config) {
|
|
355
|
-
const { connection, commitment, retryIntervalMs = 5e3, verbose = false } = config;
|
|
356
|
-
const sendOptions = {
|
|
357
|
-
skipPreflight: true,
|
|
358
|
-
maxRetries: 0,
|
|
359
|
-
preflightCommitment: commitment
|
|
360
|
-
};
|
|
361
|
-
const signature = await connection.sendRawTransaction(serializedTx, sendOptions);
|
|
523
|
+
const signature = await connection.sendRawTransaction(
|
|
524
|
+
serializedTx,
|
|
525
|
+
sendOptions
|
|
526
|
+
);
|
|
362
527
|
const confirmTransactionPromise = connection.confirmTransaction(
|
|
363
528
|
{ signature, blockhash, lastValidBlockHeight },
|
|
364
529
|
commitment
|
|
@@ -421,7 +586,9 @@ function formatTransactionError(err) {
|
|
|
421
586
|
}
|
|
422
587
|
async function addPriorityFeeInstructions(connection, transaction, priorityFeeConfig, verbose = false) {
|
|
423
588
|
const computeBudgetIxFilter = (ix) => ix.programId.toString() !== "ComputeBudget111111111111111111111111111111";
|
|
424
|
-
transaction.instructions = transaction.instructions.filter(
|
|
589
|
+
transaction.instructions = transaction.instructions.filter(
|
|
590
|
+
computeBudgetIxFilter
|
|
591
|
+
);
|
|
425
592
|
const instructions = await createPriorityFeeInstructions(
|
|
426
593
|
connection,
|
|
427
594
|
transaction,
|
|
@@ -473,19 +640,21 @@ async function createPriorityFeeInstructions(connection, transaction, priorityFe
|
|
|
473
640
|
async function simulateAndGetComputeUnits(connection, transaction) {
|
|
474
641
|
let unitsUsed = 2e5;
|
|
475
642
|
let simulationAttempts = 0;
|
|
476
|
-
|
|
477
|
-
const response = await connection.simulateTransaction(
|
|
643
|
+
while (true) {
|
|
644
|
+
const response = await connection.simulateTransaction(
|
|
645
|
+
transaction
|
|
646
|
+
);
|
|
478
647
|
if (response.value.err) {
|
|
479
648
|
if (checkKnownSimulationError(response.value)) {
|
|
480
649
|
if (simulationAttempts < 5) {
|
|
481
650
|
simulationAttempts++;
|
|
482
651
|
await sleep(1e3);
|
|
483
|
-
continue
|
|
652
|
+
continue;
|
|
484
653
|
}
|
|
485
654
|
} else if (simulationAttempts < 3) {
|
|
486
655
|
simulationAttempts++;
|
|
487
656
|
await sleep(1e3);
|
|
488
|
-
continue
|
|
657
|
+
continue;
|
|
489
658
|
}
|
|
490
659
|
throw new Error(
|
|
491
660
|
`Simulation failed: ${JSON.stringify(response.value.err)}
|
|
@@ -536,15 +705,15 @@ async function calculatePriorityFee(connection, transaction, rpcProvider, config
|
|
|
536
705
|
function checkKnownSimulationError(response) {
|
|
537
706
|
const errors = {};
|
|
538
707
|
if (response.err === "BlockhashNotFound") {
|
|
539
|
-
errors
|
|
708
|
+
errors.BlockhashNotFound = "Blockhash not found during simulation. Trying again.";
|
|
540
709
|
}
|
|
541
710
|
if (response.logs) {
|
|
542
711
|
for (const line of response.logs) {
|
|
543
712
|
if (line.includes("SlippageToleranceExceeded")) {
|
|
544
|
-
errors
|
|
713
|
+
errors.SlippageToleranceExceeded = "Slippage failure during simulation. Trying again.";
|
|
545
714
|
}
|
|
546
715
|
if (line.includes("RequireGteViolated")) {
|
|
547
|
-
errors
|
|
716
|
+
errors.RequireGteViolated = "Swap instruction failure during simulation. Trying again.";
|
|
548
717
|
}
|
|
549
718
|
}
|
|
550
719
|
}
|
|
@@ -578,157 +747,35 @@ async function sleep(timeout) {
|
|
|
578
747
|
return new Promise((resolve) => setTimeout(resolve, timeout));
|
|
579
748
|
}
|
|
580
749
|
|
|
581
|
-
// src/providers/wormhole/signers/
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
connection
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if (!wallet.solanaWallet.signTransaction) {
|
|
600
|
-
throw new Error("Wallet does not support signing transactions");
|
|
601
|
-
}
|
|
602
|
-
const tx = await wallet.solanaWallet.signTransaction(unsignedTx);
|
|
603
|
-
if (!tx) throw new Error("Failed to sign transaction");
|
|
604
|
-
if (request.transaction.signers && tx instanceof Transaction2) {
|
|
605
|
-
tx.partialSign(...request.transaction.signers);
|
|
606
|
-
}
|
|
607
|
-
const serializedTx = tx.serialize();
|
|
608
|
-
const signature = await sendAndConfirmTransaction(
|
|
609
|
-
serializedTx,
|
|
610
|
-
blockhash,
|
|
611
|
-
lastValidBlockHeight,
|
|
612
|
-
{
|
|
613
|
-
connection,
|
|
614
|
-
commitment,
|
|
615
|
-
retryIntervalMs: 5e3,
|
|
616
|
-
verbose: false
|
|
617
|
-
}
|
|
618
|
-
);
|
|
619
|
-
return signature;
|
|
620
|
-
}
|
|
621
|
-
async function setPriorityFeeInstructions(connection, blockhash, lastValidBlockHeight, request, priorityFeeConfig) {
|
|
622
|
-
const unsignedTx = request.transaction.transaction;
|
|
623
|
-
unsignedTx.recentBlockhash = blockhash;
|
|
624
|
-
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
625
|
-
await addPriorityFeeInstructions(
|
|
626
|
-
connection,
|
|
627
|
-
unsignedTx,
|
|
628
|
-
priorityFeeConfig,
|
|
629
|
-
false
|
|
630
|
-
);
|
|
631
|
-
return unsignedTx;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// src/providers/wormhole/signers/EthereumSigner.ts
|
|
635
|
-
import { ethers, getBigInt } from "ethers";
|
|
636
|
-
async function signAndSendTransaction4(request, wallet, chainName) {
|
|
637
|
-
if (!wallet) {
|
|
638
|
-
throw new Error("wallet.sendTransaction is undefined");
|
|
639
|
-
}
|
|
640
|
-
const chainId = await wallet.eip1193Provider.request({
|
|
641
|
-
method: "eth_chainId"
|
|
642
|
-
});
|
|
643
|
-
const actualChainId = parseInt(chainId, 16);
|
|
644
|
-
if (!actualChainId) throw new Error("No signer found for chain" + chainName);
|
|
645
|
-
const expectedChainId = request.transaction.chainId ? getBigInt(request.transaction.chainId) : void 0;
|
|
646
|
-
if (!actualChainId || !expectedChainId || BigInt(actualChainId) !== expectedChainId) {
|
|
647
|
-
throw new Error(
|
|
648
|
-
`Signer is not connected to the right chain. Expected ${expectedChainId}, got ${actualChainId}`
|
|
649
|
-
);
|
|
650
|
-
}
|
|
651
|
-
const provider = new ethers.BrowserProvider(
|
|
652
|
-
wallet.eip1193Provider
|
|
653
|
-
);
|
|
654
|
-
const signer = await provider.getSigner();
|
|
655
|
-
let response;
|
|
656
|
-
try {
|
|
657
|
-
response = await signer.sendTransaction(request.transaction);
|
|
658
|
-
} catch (e) {
|
|
659
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
660
|
-
const hashMatch = message.match(/"hash":\s*"(0x[a-fA-F0-9]{64})"/);
|
|
661
|
-
if (hashMatch) {
|
|
662
|
-
console.warn("Extracted EVM tx hash from error:", hashMatch[1]);
|
|
663
|
-
return hashMatch[1];
|
|
664
|
-
}
|
|
665
|
-
throw e;
|
|
666
|
-
}
|
|
667
|
-
try {
|
|
668
|
-
const receipt = await response.wait();
|
|
669
|
-
return receipt?.hash || response.hash || "";
|
|
670
|
-
} catch (e) {
|
|
671
|
-
if (e?.code === "TRANSACTION_REPLACED") {
|
|
672
|
-
if (e.reason === "repriced") {
|
|
673
|
-
const replacementHash = e.receipt?.hash || e.replacement?.hash;
|
|
674
|
-
if (replacementHash) {
|
|
675
|
-
console.warn(
|
|
676
|
-
"EVM transaction was repriced. Using replacement hash:",
|
|
677
|
-
replacementHash
|
|
678
|
-
);
|
|
679
|
-
return replacementHash;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
throw e;
|
|
683
|
-
}
|
|
684
|
-
if (response.hash) {
|
|
685
|
-
console.warn(
|
|
686
|
-
"EVM transaction wait failed but tx was submitted:",
|
|
687
|
-
response.hash
|
|
688
|
-
);
|
|
689
|
-
return response.hash;
|
|
690
|
-
}
|
|
691
|
-
throw e;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
// src/providers/wormhole/signers/SuiSigner.ts
|
|
696
|
-
async function signAndSendTransaction5(request, wallet) {
|
|
697
|
-
if (!wallet) {
|
|
698
|
-
throw new Error("wallet is undefined");
|
|
699
|
-
}
|
|
700
|
-
const suiDerivedWallet = wallet;
|
|
701
|
-
const signAndExecuteTransactionFeature = suiDerivedWallet.suiWallet.features["sui:signAndExecuteTransaction"];
|
|
702
|
-
if (!signAndExecuteTransactionFeature) {
|
|
703
|
-
throw new Error("wallet does not support signAndExecuteTransaction");
|
|
704
|
-
}
|
|
705
|
-
const { digest } = await signAndExecuteTransactionFeature.signAndExecuteTransaction({
|
|
706
|
-
transaction: request.transaction,
|
|
707
|
-
account: suiDerivedWallet.suiWallet.accounts[0],
|
|
708
|
-
chain: `sui:${request.network.toLocaleLowerCase()}`
|
|
709
|
-
});
|
|
710
|
-
return digest;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// src/providers/wormhole/signers/Signer.ts
|
|
714
|
-
var Signer = class {
|
|
715
|
-
constructor(chain, address, options, wallet, crossChainCore, sponsorAccount, onTransactionSigned, trackAsSourceChain = true) {
|
|
716
|
-
this._claimedTransactionHashes = [];
|
|
717
|
-
this._chain = chain;
|
|
718
|
-
this._address = address;
|
|
719
|
-
this._options = options;
|
|
720
|
-
this._wallet = wallet;
|
|
721
|
-
this._crossChainCore = crossChainCore;
|
|
722
|
-
this._sponsorAccount = sponsorAccount;
|
|
723
|
-
this._onTransactionSigned = onTransactionSigned;
|
|
724
|
-
this._trackAsSourceChain = trackAsSourceChain;
|
|
750
|
+
// src/providers/wormhole/signers/SolanaLocalSigner.ts
|
|
751
|
+
var SolanaLocalSigner = class {
|
|
752
|
+
keypair;
|
|
753
|
+
connection;
|
|
754
|
+
commitment;
|
|
755
|
+
retryIntervalMs;
|
|
756
|
+
priorityFeeConfig;
|
|
757
|
+
verbose;
|
|
758
|
+
_onTransactionSigned;
|
|
759
|
+
_claimedTransactionHashes = [];
|
|
760
|
+
constructor(config) {
|
|
761
|
+
this.keypair = config.keypair;
|
|
762
|
+
this.connection = config.connection;
|
|
763
|
+
this.commitment = config.commitment ?? "finalized";
|
|
764
|
+
this.retryIntervalMs = config.retryIntervalMs ?? 5e3;
|
|
765
|
+
this.priorityFeeConfig = config.priorityFeeConfig;
|
|
766
|
+
this.verbose = config.verbose ?? false;
|
|
767
|
+
this._onTransactionSigned = config.onTransactionSigned;
|
|
725
768
|
}
|
|
726
769
|
chain() {
|
|
727
|
-
return
|
|
770
|
+
return "Solana";
|
|
728
771
|
}
|
|
729
772
|
address() {
|
|
730
|
-
return this.
|
|
773
|
+
return this.keypair.publicKey.toBase58();
|
|
731
774
|
}
|
|
775
|
+
/**
|
|
776
|
+
* Returns all transaction hashes from the most recent signAndSend call,
|
|
777
|
+
* joined by comma. If only one transaction was signed, returns a single hash string.
|
|
778
|
+
*/
|
|
732
779
|
claimedTransactionHashes() {
|
|
733
780
|
return this._claimedTransactionHashes.join(",");
|
|
734
781
|
}
|
|
@@ -737,68 +784,96 @@ var Signer = class {
|
|
|
737
784
|
this._claimedTransactionHashes = [];
|
|
738
785
|
for (const tx of txs) {
|
|
739
786
|
this._onTransactionSigned?.(tx.description, null);
|
|
740
|
-
const txId = await
|
|
741
|
-
this._chain,
|
|
742
|
-
tx,
|
|
743
|
-
this._wallet,
|
|
744
|
-
this._options,
|
|
745
|
-
this._crossChainCore,
|
|
746
|
-
this._sponsorAccount
|
|
747
|
-
);
|
|
748
|
-
if (this._trackAsSourceChain) {
|
|
749
|
-
this._crossChainCore._lastSourceChainTxId = txId;
|
|
750
|
-
}
|
|
787
|
+
const txId = await this.signAndSendTransaction(tx);
|
|
751
788
|
this._onTransactionSigned?.(tx.description, txId);
|
|
752
789
|
txHashes.push(txId);
|
|
753
790
|
this._claimedTransactionHashes.push(txId);
|
|
754
791
|
}
|
|
755
792
|
return txHashes;
|
|
756
793
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
794
|
+
async signAndSendTransaction(request) {
|
|
795
|
+
const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash(this.commitment);
|
|
796
|
+
let unsignedTx = request.transaction ?? request;
|
|
797
|
+
const additionalSigners = request.transaction?.signers;
|
|
798
|
+
const MAX_UNWRAP_DEPTH = 10;
|
|
799
|
+
let unwrapDepth = 0;
|
|
800
|
+
while (unsignedTx && typeof unsignedTx === "object" && "transaction" in unsignedTx && !(unsignedTx instanceof Transaction) && !("signatures" in unsignedTx && "message" in unsignedTx)) {
|
|
801
|
+
if (++unwrapDepth > MAX_UNWRAP_DEPTH) {
|
|
802
|
+
throw new Error(
|
|
803
|
+
"Transaction unwrapping exceeded maximum depth \u2014 possible circular nesting"
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
unsignedTx = unsignedTx.transaction;
|
|
807
|
+
}
|
|
808
|
+
const isVersioned = unsignedTx.message !== void 0 && unsignedTx.signatures !== void 0 && typeof unsignedTx.message.recentBlockhash !== "undefined";
|
|
809
|
+
if (isVersioned) {
|
|
810
|
+
unsignedTx.message.recentBlockhash = blockhash;
|
|
811
|
+
if (this.verbose || this.priorityFeeConfig) {
|
|
812
|
+
console.warn(
|
|
813
|
+
"SolanaLocalSigner: Versioned transaction detected \u2014 priority fees are not applied. Consider using legacy transactions if priority fees are required."
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
unsignedTx.sign([this.keypair]);
|
|
817
|
+
if (additionalSigners && additionalSigners.length > 0) {
|
|
818
|
+
unsignedTx.sign(additionalSigners);
|
|
819
|
+
}
|
|
820
|
+
} else if (unsignedTx instanceof Transaction) {
|
|
821
|
+
unsignedTx.recentBlockhash = blockhash;
|
|
822
|
+
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
823
|
+
if (this.priorityFeeConfig) {
|
|
824
|
+
await addPriorityFeeInstructions(
|
|
825
|
+
this.connection,
|
|
826
|
+
unsignedTx,
|
|
827
|
+
this.priorityFeeConfig,
|
|
828
|
+
this.verbose
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
if (additionalSigners && additionalSigners.length > 0) {
|
|
832
|
+
unsignedTx.sign(this.keypair, ...additionalSigners);
|
|
833
|
+
} else {
|
|
834
|
+
unsignedTx.sign(this.keypair);
|
|
835
|
+
}
|
|
836
|
+
} else if (unsignedTx.recentBlockhash !== void 0 || unsignedTx.feePayer !== void 0) {
|
|
837
|
+
unsignedTx.recentBlockhash = blockhash;
|
|
838
|
+
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
839
|
+
if (this.priorityFeeConfig) {
|
|
840
|
+
await addPriorityFeeInstructions(
|
|
841
|
+
this.connection,
|
|
842
|
+
unsignedTx,
|
|
843
|
+
this.priorityFeeConfig,
|
|
844
|
+
this.verbose
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
if (additionalSigners && additionalSigners.length > 0) {
|
|
848
|
+
unsignedTx.sign(this.keypair, ...additionalSigners);
|
|
849
|
+
} else {
|
|
850
|
+
unsignedTx.sign(this.keypair);
|
|
851
|
+
}
|
|
852
|
+
} else {
|
|
853
|
+
throw new Error(
|
|
854
|
+
`Unsupported transaction type: ${unsignedTx?.constructor?.name}`
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
const serializedTx = unsignedTx.serialize();
|
|
858
|
+
const signature = await sendAndConfirmTransaction(
|
|
859
|
+
serializedTx,
|
|
860
|
+
blockhash,
|
|
861
|
+
lastValidBlockHeight,
|
|
862
|
+
{
|
|
863
|
+
connection: this.connection,
|
|
864
|
+
commitment: this.commitment,
|
|
865
|
+
retryIntervalMs: this.retryIntervalMs,
|
|
866
|
+
verbose: this.verbose
|
|
867
|
+
}
|
|
791
868
|
);
|
|
792
|
-
return
|
|
793
|
-
} else {
|
|
794
|
-
throw new Error(`Unsupported chain: ${chain}`);
|
|
869
|
+
return signature;
|
|
795
870
|
}
|
|
796
871
|
};
|
|
797
872
|
|
|
798
873
|
// src/providers/wormhole/utils.ts
|
|
799
874
|
import {
|
|
800
875
|
chainToPlatform,
|
|
801
|
-
routes
|
|
876
|
+
routes,
|
|
802
877
|
Wormhole
|
|
803
878
|
} from "@wormhole-foundation/sdk";
|
|
804
879
|
async function createCCTPRoute(wh, sourceChain, destChain, tokens) {
|
|
@@ -812,504 +887,409 @@ async function createCCTPRoute(wh, sourceChain, destChain, tokens) {
|
|
|
812
887
|
);
|
|
813
888
|
const destContext = wh.getPlatform(chainToPlatform(destChain)).getChain(destChain);
|
|
814
889
|
const sourceContext = wh.getPlatform(chainToPlatform(sourceChain)).getChain(sourceChain);
|
|
815
|
-
const request = await
|
|
890
|
+
const request = await routes.RouteTransferRequest.create(
|
|
816
891
|
wh,
|
|
817
892
|
{ source: sourceToken, destination: destToken },
|
|
818
893
|
sourceContext,
|
|
819
894
|
destContext
|
|
820
895
|
);
|
|
821
|
-
const resolver = wh.resolver([
|
|
896
|
+
const resolver = wh.resolver([routes.CCTPRoute]);
|
|
822
897
|
const foundRoutes = await resolver.findRoutes(request);
|
|
823
898
|
const cctpRoute = foundRoutes[0];
|
|
824
|
-
if (!cctpRoute || !
|
|
899
|
+
if (!cctpRoute || !routes.isManual(cctpRoute)) {
|
|
825
900
|
throw new Error("Expected manual CCTP route");
|
|
826
901
|
}
|
|
827
902
|
return { route: cctpRoute, request };
|
|
828
903
|
}
|
|
829
904
|
|
|
830
905
|
// src/providers/wormhole/wormhole.ts
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
906
|
+
import { Network, sleep as sleep2 } from "@aptos-labs/ts-sdk";
|
|
907
|
+
import {
|
|
908
|
+
routes as routes2,
|
|
909
|
+
TransferState,
|
|
910
|
+
Wormhole as Wormhole2,
|
|
911
|
+
wormhole
|
|
912
|
+
} from "@wormhole-foundation/sdk";
|
|
913
|
+
import aptos from "@wormhole-foundation/sdk/aptos";
|
|
914
|
+
import evm from "@wormhole-foundation/sdk/evm";
|
|
915
|
+
import solana from "@wormhole-foundation/sdk/solana";
|
|
916
|
+
import sui from "@wormhole-foundation/sdk/sui";
|
|
917
|
+
|
|
918
|
+
// src/utils/logger.ts
|
|
919
|
+
var logger = {
|
|
920
|
+
log: (...args) => {
|
|
921
|
+
if (process.env.NODE_ENV === "development") {
|
|
922
|
+
console.log(...args);
|
|
845
923
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const solanaRpc = dappConfig?.solanaConfig?.rpc ?? chains["Solana"]?.defaultRpc;
|
|
851
|
-
const suiRpc = dappConfig?.suiConfig?.rpc ?? chains["Sui"]?.defaultRpc;
|
|
852
|
-
const evmChainsConfig = {};
|
|
853
|
-
for (const name of EVM_CHAIN_NAMES) {
|
|
854
|
-
const rpc = dappConfig?.evmConfig?.[name]?.rpc ?? chains[name]?.defaultRpc;
|
|
855
|
-
if (rpc) {
|
|
856
|
-
evmChainsConfig[name] = { rpc };
|
|
857
|
-
}
|
|
924
|
+
},
|
|
925
|
+
warn: (...args) => {
|
|
926
|
+
if (process.env.NODE_ENV === "development") {
|
|
927
|
+
console.warn(...args);
|
|
858
928
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
...evmChainsConfig
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
this._wormholeContext = wh;
|
|
867
|
-
}
|
|
868
|
-
async getRoute(sourceChain, destinationChain) {
|
|
869
|
-
if (!this._wormholeContext) {
|
|
870
|
-
throw new Error("Wormhole context not initialized");
|
|
929
|
+
},
|
|
930
|
+
error: (...args) => {
|
|
931
|
+
if (process.env.NODE_ENV === "development") {
|
|
932
|
+
console.error(...args);
|
|
871
933
|
}
|
|
872
|
-
const { route: cctpRoute, request } = await createCCTPRoute(
|
|
873
|
-
this._wormholeContext,
|
|
874
|
-
sourceChain,
|
|
875
|
-
destinationChain,
|
|
876
|
-
this.crossChainCore.TOKENS
|
|
877
|
-
);
|
|
878
|
-
this.wormholeRoute = cctpRoute;
|
|
879
|
-
this.wormholeRequest = request;
|
|
880
|
-
this.destinationChain = destinationChain;
|
|
881
|
-
return { route: cctpRoute, request };
|
|
882
934
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
destinationChain
|
|
894
|
-
);
|
|
895
|
-
const transferParams = {
|
|
896
|
-
amount,
|
|
897
|
-
options: { nativeGas: 0 }
|
|
898
|
-
};
|
|
899
|
-
const validated = await route.validate(request, transferParams);
|
|
900
|
-
if (!validated.valid) {
|
|
901
|
-
logger.log("invalid", validated.valid);
|
|
902
|
-
throw new Error(`Invalid quote: ${validated.error}`);
|
|
903
|
-
}
|
|
904
|
-
const quote = await route.quote(request, validated.params);
|
|
905
|
-
if (!quote.success) {
|
|
906
|
-
logger.log("quote failed", quote.success);
|
|
907
|
-
throw new Error(`Invalid quote: ${quote.error}`);
|
|
908
|
-
}
|
|
909
|
-
this.wormholeQuote = quote;
|
|
910
|
-
logger.log("quote", quote);
|
|
911
|
-
return quote;
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// src/utils/receiptSerialization.ts
|
|
938
|
+
import {
|
|
939
|
+
UniversalAddress
|
|
940
|
+
} from "@wormhole-foundation/sdk";
|
|
941
|
+
function uint8ArrayToBase64(bytes) {
|
|
942
|
+
let binary = "";
|
|
943
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
944
|
+
binary += String.fromCharCode(bytes[i]);
|
|
912
945
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
}
|
|
921
|
-
let signerAddress;
|
|
922
|
-
const chainContext = this.getChainConfig(sourceChain).context;
|
|
923
|
-
if (chainContext === "Solana") {
|
|
924
|
-
signerAddress = wallet.solanaWallet.publicKey?.toBase58() || "";
|
|
925
|
-
} else if (chainContext === "Ethereum") {
|
|
926
|
-
[signerAddress] = await wallet.eip1193Provider.request({
|
|
927
|
-
method: "eth_requestAccounts"
|
|
928
|
-
});
|
|
929
|
-
} else if (chainContext === "Sui") {
|
|
930
|
-
signerAddress = wallet.suiWallet.accounts[0].address || "";
|
|
931
|
-
} else {
|
|
932
|
-
throw new Error("Unsupported chain context: " + chainContext);
|
|
933
|
-
}
|
|
934
|
-
logger.log("signerAddress", signerAddress);
|
|
935
|
-
const signer = new Signer(
|
|
936
|
-
this.getChainConfig(sourceChain),
|
|
937
|
-
signerAddress,
|
|
938
|
-
{},
|
|
939
|
-
wallet,
|
|
940
|
-
this.crossChainCore,
|
|
941
|
-
void 0,
|
|
942
|
-
onTransactionSigned
|
|
943
|
-
);
|
|
944
|
-
logger.log("signer", signer);
|
|
945
|
-
logger.log("wormholeRequest", this.wormholeRequest);
|
|
946
|
-
logger.log("wormholeQuote", this.wormholeQuote);
|
|
947
|
-
let receipt = await this.wormholeRoute.initiate(
|
|
948
|
-
this.wormholeRequest,
|
|
949
|
-
signer,
|
|
950
|
-
this.wormholeQuote,
|
|
951
|
-
Wormhole2.chainAddress("Aptos", destinationAddress.toString())
|
|
952
|
-
);
|
|
953
|
-
const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
|
|
954
|
-
return { originChainTxnId: originChainTxnId || "", receipt };
|
|
946
|
+
return btoa(binary);
|
|
947
|
+
}
|
|
948
|
+
function base64ToUint8Array(base64) {
|
|
949
|
+
const binary = atob(base64);
|
|
950
|
+
const bytes = new Uint8Array(binary.length);
|
|
951
|
+
for (let i = 0; i < binary.length; i++) {
|
|
952
|
+
bytes[i] = binary.charCodeAt(i);
|
|
955
953
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
)
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const circleAttestationReceipt = await this.wormholeRoute.complete(signer, receipt);
|
|
988
|
-
logger.log("Claim receipt: ", circleAttestationReceipt);
|
|
989
|
-
const destinationChainTxnId = signer.claimedTransactionHashes();
|
|
990
|
-
return { destinationChainTxnId };
|
|
991
|
-
} else {
|
|
992
|
-
return { destinationChainTxnId: "" };
|
|
993
|
-
}
|
|
994
|
-
} catch (e) {
|
|
995
|
-
console.error("Failed to claim", e);
|
|
996
|
-
return { destinationChainTxnId: "" };
|
|
997
|
-
}
|
|
998
|
-
}
|
|
954
|
+
return bytes;
|
|
955
|
+
}
|
|
956
|
+
function serializeReceipt(receipt) {
|
|
957
|
+
return JSON.parse(
|
|
958
|
+
JSON.stringify(receipt, (_key, value) => {
|
|
959
|
+
if (typeof value === "bigint") {
|
|
960
|
+
return { __type: "bigint", value: value.toString() };
|
|
961
|
+
}
|
|
962
|
+
if (value instanceof UniversalAddress) {
|
|
963
|
+
return {
|
|
964
|
+
__type: "UniversalAddress",
|
|
965
|
+
value: uint8ArrayToBase64(value.toUint8Array())
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
if (value instanceof Uint8Array) {
|
|
969
|
+
return {
|
|
970
|
+
__type: "Uint8Array",
|
|
971
|
+
value: uint8ArrayToBase64(value)
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
return value;
|
|
975
|
+
})
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
function deserializeReceipt(obj) {
|
|
979
|
+
function revive(value, key) {
|
|
980
|
+
if (value && typeof value === "object") {
|
|
981
|
+
const objValue = value;
|
|
982
|
+
if ("__type" in objValue) {
|
|
983
|
+
if (objValue.__type === "bigint") {
|
|
984
|
+
return BigInt(objValue.value);
|
|
999
985
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
986
|
+
if (objValue.__type === "UniversalAddress") {
|
|
987
|
+
return new UniversalAddress(
|
|
988
|
+
base64ToUint8Array(objValue.value)
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
if (objValue.__type === "Uint8Array") {
|
|
992
|
+
return base64ToUint8Array(objValue.value);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
const addressFields = [
|
|
996
|
+
"sender",
|
|
997
|
+
"recipient",
|
|
998
|
+
"destinationCaller",
|
|
999
|
+
"burnToken",
|
|
1000
|
+
"mintRecipient",
|
|
1001
|
+
"messageSender"
|
|
1002
|
+
];
|
|
1003
|
+
if (key && addressFields.includes(key) && "address" in objValue) {
|
|
1004
|
+
const addressBytes = revive(objValue.address);
|
|
1005
|
+
if (addressBytes instanceof Uint8Array) {
|
|
1006
|
+
return new UniversalAddress(addressBytes);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
if (Array.isArray(value)) {
|
|
1010
|
+
return value.map((v, i) => revive(v, String(i)));
|
|
1011
|
+
}
|
|
1012
|
+
const result = {};
|
|
1013
|
+
for (const k in objValue) {
|
|
1014
|
+
result[k] = revive(objValue[k], k);
|
|
1008
1015
|
}
|
|
1016
|
+
return result;
|
|
1009
1017
|
}
|
|
1010
|
-
return
|
|
1018
|
+
return value;
|
|
1011
1019
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
const { destinationChainTxnId } = await this.claimCCTPTransfer({
|
|
1031
|
-
receipt,
|
|
1032
|
-
mainSigner: input.mainSigner,
|
|
1033
|
-
sponsorAccount: input.sponsorAccount,
|
|
1034
|
-
onTransactionSigned: input.onTransactionSigned
|
|
1035
|
-
});
|
|
1036
|
-
return { originChainTxnId, destinationChainTxnId };
|
|
1037
|
-
} catch (error) {
|
|
1038
|
-
throw new TransferError(
|
|
1039
|
-
error?.message ?? "Transfer claim failed after source-chain burn",
|
|
1040
|
-
originChainTxnId,
|
|
1041
|
-
error
|
|
1042
|
-
);
|
|
1043
|
-
}
|
|
1020
|
+
return revive(obj);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// src/providers/wormhole/signers/AptosSigner.ts
|
|
1024
|
+
import {
|
|
1025
|
+
GasStationClient,
|
|
1026
|
+
GasStationTransactionSubmitter
|
|
1027
|
+
} from "@aptos-labs/gas-station-client";
|
|
1028
|
+
import {
|
|
1029
|
+
AccountAddress,
|
|
1030
|
+
Aptos as Aptos2,
|
|
1031
|
+
AptosConfig as AptosConfig2,
|
|
1032
|
+
Deserializer
|
|
1033
|
+
} from "@aptos-labs/ts-sdk";
|
|
1034
|
+
import { UserResponseStatus } from "@aptos-labs/wallet-standard";
|
|
1035
|
+
async function signAndSendTransaction2(request, wallet, sponsorAccount, dappNetwork, crossChainCore) {
|
|
1036
|
+
if (!wallet) {
|
|
1037
|
+
throw new Error("wallet.sendTransaction is undefined");
|
|
1044
1038
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
if (!this._wormholeContext) {
|
|
1054
|
-
throw new Error("Wormhole context not initialized");
|
|
1055
|
-
}
|
|
1056
|
-
if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
|
|
1057
|
-
throw new Error("Wormhole route, request, or quote not initialized");
|
|
1039
|
+
const payload = request.transaction;
|
|
1040
|
+
payload.functionArguments = payload.functionArguments.map((a) => {
|
|
1041
|
+
if (a instanceof Uint8Array) {
|
|
1042
|
+
return Array.from(a);
|
|
1043
|
+
} else if (typeof a === "bigint") {
|
|
1044
|
+
return a.toString();
|
|
1045
|
+
} else {
|
|
1046
|
+
return a;
|
|
1058
1047
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
sponsorAccount
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
this.destinationChain,
|
|
1070
|
-
destinationAddress.toString()
|
|
1071
|
-
);
|
|
1072
|
-
const receipt = await this.wormholeRoute.initiate(
|
|
1073
|
-
this.wormholeRequest,
|
|
1074
|
-
signer,
|
|
1075
|
-
this.wormholeQuote,
|
|
1076
|
-
wormholeDestAddress
|
|
1048
|
+
});
|
|
1049
|
+
let aptosConfig;
|
|
1050
|
+
const useGasStation = sponsorAccount && !isAccount(sponsorAccount);
|
|
1051
|
+
if (useGasStation) {
|
|
1052
|
+
const gasStationClient = new GasStationClient({
|
|
1053
|
+
network: dappNetwork,
|
|
1054
|
+
apiKey: sponsorAccount[dappNetwork]
|
|
1055
|
+
});
|
|
1056
|
+
const transactionSubmitter = new GasStationTransactionSubmitter(
|
|
1057
|
+
gasStationClient
|
|
1077
1058
|
);
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
/**
|
|
1083
|
-
* Phase 2: Tracks a withdraw receipt until attestation is ready.
|
|
1084
|
-
* This polls Wormhole and returns once the receipt reaches the Attested state.
|
|
1085
|
-
*/
|
|
1086
|
-
async trackWithdraw(receipt) {
|
|
1087
|
-
if (!this.wormholeRoute) {
|
|
1088
|
-
throw new Error("Wormhole route not initialized");
|
|
1089
|
-
}
|
|
1090
|
-
let retries = 0;
|
|
1091
|
-
const maxRetries = 5;
|
|
1092
|
-
const baseDelay = 1e3;
|
|
1093
|
-
while (retries < maxRetries) {
|
|
1094
|
-
try {
|
|
1095
|
-
for await (receipt of this.wormholeRoute.track(receipt, 120 * 1e3)) {
|
|
1096
|
-
if (receipt.state >= TransferState.Attested) {
|
|
1097
|
-
logger.log("trackWithdraw: receipt attested", receipt);
|
|
1098
|
-
return receipt;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
} catch (e) {
|
|
1102
|
-
console.error(
|
|
1103
|
-
`Error tracking withdraw (attempt ${retries + 1} / ${maxRetries}):`,
|
|
1104
|
-
e
|
|
1105
|
-
);
|
|
1106
|
-
const delay = baseDelay * Math.pow(2, retries);
|
|
1107
|
-
await sleep2(delay);
|
|
1108
|
-
retries++;
|
|
1059
|
+
aptosConfig = new AptosConfig2({
|
|
1060
|
+
network: dappNetwork,
|
|
1061
|
+
pluginSettings: {
|
|
1062
|
+
TRANSACTION_SUBMITTER: transactionSubmitter
|
|
1109
1063
|
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1064
|
+
});
|
|
1065
|
+
} else {
|
|
1066
|
+
aptosConfig = new AptosConfig2({
|
|
1067
|
+
network: dappNetwork
|
|
1068
|
+
});
|
|
1112
1069
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const serverClaimUrl = this.crossChainCore._dappConfig?.solanaConfig?.serverClaimUrl;
|
|
1126
|
-
if (claimChain === "Solana" && serverClaimUrl) {
|
|
1127
|
-
logger.log("claimWithdraw: using server-side claim via", serverClaimUrl);
|
|
1128
|
-
const response = await fetch(serverClaimUrl, {
|
|
1129
|
-
method: "POST",
|
|
1130
|
-
headers: { "Content-Type": "application/json" },
|
|
1131
|
-
body: JSON.stringify({
|
|
1132
|
-
receipt: serializeReceipt(receipt),
|
|
1133
|
-
destinationAddress,
|
|
1134
|
-
claimChain
|
|
1135
|
-
})
|
|
1136
|
-
});
|
|
1137
|
-
if (!response.ok) {
|
|
1138
|
-
const errorData = await response.json().catch(() => ({}));
|
|
1139
|
-
throw new Error(
|
|
1140
|
-
errorData.error || `Server-side claim failed with status ${response.status}`
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1143
|
-
const result = await response.json();
|
|
1144
|
-
return { destinationChainTxnId: result.destinationChainTxnId };
|
|
1145
|
-
}
|
|
1146
|
-
if (!this.wormholeRoute) {
|
|
1147
|
-
throw new Error("Wormhole route not initialized");
|
|
1148
|
-
}
|
|
1149
|
-
if (!input.wallet) {
|
|
1150
|
-
throw new Error(
|
|
1151
|
-
"Wallet is required for claim when serverClaimUrl is not configured"
|
|
1152
|
-
);
|
|
1153
|
-
}
|
|
1154
|
-
const claimSigner = new Signer(
|
|
1155
|
-
this.getChainConfig(claimChain),
|
|
1156
|
-
destinationAddress,
|
|
1157
|
-
{},
|
|
1158
|
-
input.wallet,
|
|
1159
|
-
this.crossChainCore,
|
|
1160
|
-
void 0,
|
|
1161
|
-
input.onTransactionSigned,
|
|
1162
|
-
false
|
|
1163
|
-
);
|
|
1164
|
-
if (routes3.isManual(this.wormholeRoute)) {
|
|
1165
|
-
const circleAttestationReceipt = await this.wormholeRoute.complete(
|
|
1166
|
-
claimSigner,
|
|
1167
|
-
receipt
|
|
1168
|
-
);
|
|
1169
|
-
logger.log("claimWithdraw receipt:", circleAttestationReceipt);
|
|
1170
|
-
const destinationChainTxnId = claimSigner.claimedTransactionHashes();
|
|
1171
|
-
return { destinationChainTxnId };
|
|
1172
|
-
} else {
|
|
1173
|
-
throw new Error("Automatic route not supported for manual claim");
|
|
1174
|
-
}
|
|
1070
|
+
const aptos2 = new Aptos2(aptosConfig);
|
|
1071
|
+
const functionArguments = extractFunctionArguments(
|
|
1072
|
+
payload.functionArguments
|
|
1073
|
+
);
|
|
1074
|
+
const withdrawFunction = "0x5e2d961f06cd27aa07554a39d55f5ce1e58dff35d803c3529b1cd5c4fa3ab584::withdraw::deposit_for_burn";
|
|
1075
|
+
const transactionData = {
|
|
1076
|
+
function: withdrawFunction,
|
|
1077
|
+
functionArguments
|
|
1078
|
+
};
|
|
1079
|
+
const expireTimestamp = crossChainCore?._dappConfig?.getExpireTimestamp?.();
|
|
1080
|
+
if (typeof expireTimestamp !== "undefined") {
|
|
1081
|
+
validateExpireTimestamp(expireTimestamp);
|
|
1175
1082
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
sponsorAccount,
|
|
1193
|
-
|
|
1194
|
-
onTransactionSigned
|
|
1195
|
-
} = input;
|
|
1196
|
-
onPhaseChange?.("initiating");
|
|
1197
|
-
const { originChainTxnId, receipt } = await this.initiateWithdraw({
|
|
1198
|
-
wallet,
|
|
1199
|
-
destinationAddress,
|
|
1200
|
-
sponsorAccount,
|
|
1201
|
-
onTransactionSigned
|
|
1083
|
+
const txnToSign = await aptos2.transaction.build.simple({
|
|
1084
|
+
data: transactionData,
|
|
1085
|
+
sender: (await wallet.features["aptos:account"]?.account()).address.toString(),
|
|
1086
|
+
withFeePayer: !!sponsorAccount,
|
|
1087
|
+
...typeof expireTimestamp !== "undefined" ? { options: { expireTimestamp } } : {}
|
|
1088
|
+
});
|
|
1089
|
+
const response = await wallet.features["aptos:signTransaction"]?.signTransaction(txnToSign);
|
|
1090
|
+
if (response?.status === UserResponseStatus.REJECTED) {
|
|
1091
|
+
throw new Error("User has rejected the request");
|
|
1092
|
+
}
|
|
1093
|
+
const txnToSubmit = {
|
|
1094
|
+
transaction: txnToSign,
|
|
1095
|
+
senderAuthenticator: response.args
|
|
1096
|
+
};
|
|
1097
|
+
if (sponsorAccount && isAccount(sponsorAccount)) {
|
|
1098
|
+
const feePayerSignerAuthenticator = aptos2.transaction.signAsFeePayer({
|
|
1099
|
+
signer: sponsorAccount,
|
|
1100
|
+
transaction: txnToSign
|
|
1202
1101
|
});
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1102
|
+
txnToSubmit.feePayerAuthenticator = feePayerSignerAuthenticator;
|
|
1103
|
+
}
|
|
1104
|
+
const txnSubmitted = await aptos2.transaction.submit.simple(txnToSubmit);
|
|
1105
|
+
const tx = await aptos2.waitForTransaction({
|
|
1106
|
+
transactionHash: txnSubmitted.hash
|
|
1107
|
+
});
|
|
1108
|
+
return tx.hash;
|
|
1109
|
+
}
|
|
1110
|
+
function extractFunctionArguments(functionArguments) {
|
|
1111
|
+
const deserializer1 = new Deserializer(functionArguments[0].bcsToBytes());
|
|
1112
|
+
const amount = deserializer1.deserializeU64();
|
|
1113
|
+
const deserializer2 = new Deserializer(functionArguments[1].bcsToBytes());
|
|
1114
|
+
const destination_domain = deserializer2.deserializeU32();
|
|
1115
|
+
const mint_recipient = new AccountAddress(functionArguments[2].bcsToBytes());
|
|
1116
|
+
const burn_token = new AccountAddress(functionArguments[3].bcsToBytes());
|
|
1117
|
+
return [amount, destination_domain, mint_recipient, burn_token];
|
|
1118
|
+
}
|
|
1119
|
+
function isAccount(obj) {
|
|
1120
|
+
return "accountAddress" in obj;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/providers/wormhole/signers/EthereumSigner.ts
|
|
1124
|
+
import { ethers, getBigInt } from "ethers";
|
|
1125
|
+
async function signAndSendTransaction3(request, wallet, chainName) {
|
|
1126
|
+
if (!wallet) {
|
|
1127
|
+
throw new Error("wallet.sendTransaction is undefined");
|
|
1128
|
+
}
|
|
1129
|
+
const chainId = await wallet.eip1193Provider.request({
|
|
1130
|
+
method: "eth_chainId"
|
|
1131
|
+
});
|
|
1132
|
+
const actualChainId = parseInt(chainId, 16);
|
|
1133
|
+
if (!actualChainId) throw new Error(`No signer found for chain${chainName}`);
|
|
1134
|
+
const expectedChainId = request.transaction.chainId ? getBigInt(request.transaction.chainId) : void 0;
|
|
1135
|
+
if (!actualChainId || !expectedChainId || BigInt(actualChainId) !== expectedChainId) {
|
|
1136
|
+
throw new Error(
|
|
1137
|
+
`Signer is not connected to the right chain. Expected ${expectedChainId}, got ${actualChainId}`
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
const provider = new ethers.BrowserProvider(
|
|
1141
|
+
wallet.eip1193Provider
|
|
1142
|
+
);
|
|
1143
|
+
const signer = await provider.getSigner();
|
|
1144
|
+
let response;
|
|
1145
|
+
try {
|
|
1146
|
+
response = await signer.sendTransaction(request.transaction);
|
|
1147
|
+
} catch (e) {
|
|
1148
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1149
|
+
const hashMatch = message.match(/"hash":\s*"(0x[a-fA-F0-9]{64})"/);
|
|
1150
|
+
if (hashMatch) {
|
|
1151
|
+
console.warn("Extracted EVM tx hash from error:", hashMatch[1]);
|
|
1152
|
+
return hashMatch[1];
|
|
1224
1153
|
}
|
|
1154
|
+
throw e;
|
|
1225
1155
|
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
* if (error instanceof WithdrawError && error.phase === "claiming") {
|
|
1240
|
-
* const result = await provider.retryWithdrawClaim({
|
|
1241
|
-
* sourceChain,
|
|
1242
|
-
* destinationAddress,
|
|
1243
|
-
* receipt: attestedReceipt,
|
|
1244
|
-
* wallet,
|
|
1245
|
-
* maxRetries: 5,
|
|
1246
|
-
* });
|
|
1247
|
-
* }
|
|
1248
|
-
* }
|
|
1249
|
-
* ```
|
|
1250
|
-
*/
|
|
1251
|
-
async retryWithdrawClaim(input) {
|
|
1252
|
-
const {
|
|
1253
|
-
maxRetries = 5,
|
|
1254
|
-
initialDelayMs = 2e3,
|
|
1255
|
-
backoffMultiplier = 2,
|
|
1256
|
-
...claimInput
|
|
1257
|
-
} = input;
|
|
1258
|
-
let lastError;
|
|
1259
|
-
let delay = initialDelayMs;
|
|
1260
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1261
|
-
try {
|
|
1262
|
-
const result = await this.claimWithdraw(claimInput);
|
|
1263
|
-
return { ...result, retriesUsed: attempt };
|
|
1264
|
-
} catch (error) {
|
|
1265
|
-
lastError = error;
|
|
1266
|
-
logger.log(
|
|
1267
|
-
`retryWithdrawClaim: attempt ${attempt + 1}/${maxRetries + 1} failed: ${lastError.message}`
|
|
1268
|
-
);
|
|
1269
|
-
if (attempt < maxRetries) {
|
|
1270
|
-
await sleep2(delay);
|
|
1271
|
-
delay *= backoffMultiplier;
|
|
1156
|
+
try {
|
|
1157
|
+
const receipt = await response.wait();
|
|
1158
|
+
return receipt?.hash || response.hash || "";
|
|
1159
|
+
} catch (e) {
|
|
1160
|
+
if (e?.code === "TRANSACTION_REPLACED") {
|
|
1161
|
+
if (e.reason === "repriced") {
|
|
1162
|
+
const replacementHash = e.receipt?.hash || e.replacement?.hash;
|
|
1163
|
+
if (replacementHash) {
|
|
1164
|
+
console.warn(
|
|
1165
|
+
"EVM transaction was repriced. Using replacement hash:",
|
|
1166
|
+
replacementHash
|
|
1167
|
+
);
|
|
1168
|
+
return replacementHash;
|
|
1272
1169
|
}
|
|
1273
1170
|
}
|
|
1171
|
+
throw e;
|
|
1274
1172
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
if (!chainConfig) {
|
|
1282
|
-
throw new Error(`Chain config not found for chain: ${chain}`);
|
|
1173
|
+
if (response.hash) {
|
|
1174
|
+
console.warn(
|
|
1175
|
+
"EVM transaction wait failed but tx was submitted:",
|
|
1176
|
+
response.hash
|
|
1177
|
+
);
|
|
1178
|
+
return response.hash;
|
|
1283
1179
|
}
|
|
1284
|
-
|
|
1180
|
+
throw e;
|
|
1285
1181
|
}
|
|
1286
|
-
}
|
|
1182
|
+
}
|
|
1287
1183
|
|
|
1288
|
-
// src/providers/wormhole/signers/
|
|
1184
|
+
// src/providers/wormhole/signers/SolanaSigner.ts
|
|
1185
|
+
import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
|
|
1289
1186
|
import {
|
|
1290
|
-
|
|
1187
|
+
Connection,
|
|
1188
|
+
Transaction as Transaction2
|
|
1291
1189
|
} from "@solana/web3.js";
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
this.keypair = config.keypair;
|
|
1296
|
-
this.connection = config.connection;
|
|
1297
|
-
this.commitment = config.commitment ?? "finalized";
|
|
1298
|
-
this.retryIntervalMs = config.retryIntervalMs ?? 5e3;
|
|
1299
|
-
this.priorityFeeConfig = config.priorityFeeConfig;
|
|
1300
|
-
this.verbose = config.verbose ?? false;
|
|
1301
|
-
this._onTransactionSigned = config.onTransactionSigned;
|
|
1302
|
-
}
|
|
1303
|
-
chain() {
|
|
1304
|
-
return "Solana";
|
|
1190
|
+
async function signAndSendTransaction4(request, wallet, options, crossChainCore) {
|
|
1191
|
+
if (!wallet || !(wallet instanceof SolanaDerivedWallet)) {
|
|
1192
|
+
throw new Error("Invalid wallet type or missing Solana wallet");
|
|
1305
1193
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1194
|
+
const commitment = options?.commitment ?? crossChainCore?._dappConfig?.solanaConfig?.commitment ?? "finalized";
|
|
1195
|
+
const connection = new Connection(
|
|
1196
|
+
crossChainCore?._dappConfig?.solanaConfig?.rpc ?? crossChainCore?.CHAINS.Solana?.defaultRpc ?? "https://api.devnet.solana.com"
|
|
1197
|
+
// Last resort fallback
|
|
1198
|
+
);
|
|
1199
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(commitment);
|
|
1200
|
+
const unsignedTx = await setPriorityFeeInstructions(
|
|
1201
|
+
connection,
|
|
1202
|
+
blockhash,
|
|
1203
|
+
lastValidBlockHeight,
|
|
1204
|
+
request,
|
|
1205
|
+
crossChainCore?._dappConfig?.solanaConfig?.priorityFeeConfig
|
|
1206
|
+
);
|
|
1207
|
+
if (!wallet.solanaWallet.signTransaction) {
|
|
1208
|
+
throw new Error("Wallet does not support signing transactions");
|
|
1209
|
+
}
|
|
1210
|
+
const tx = await wallet.solanaWallet.signTransaction(unsignedTx);
|
|
1211
|
+
if (!tx) throw new Error("Failed to sign transaction");
|
|
1212
|
+
if (request.transaction.signers && tx instanceof Transaction2) {
|
|
1213
|
+
tx.partialSign(...request.transaction.signers);
|
|
1214
|
+
}
|
|
1215
|
+
const serializedTx = tx.serialize();
|
|
1216
|
+
const signature = await sendAndConfirmTransaction(
|
|
1217
|
+
serializedTx,
|
|
1218
|
+
blockhash,
|
|
1219
|
+
lastValidBlockHeight,
|
|
1220
|
+
{
|
|
1221
|
+
connection,
|
|
1222
|
+
commitment,
|
|
1223
|
+
retryIntervalMs: 5e3,
|
|
1224
|
+
verbose: false
|
|
1225
|
+
}
|
|
1226
|
+
);
|
|
1227
|
+
return signature;
|
|
1228
|
+
}
|
|
1229
|
+
async function setPriorityFeeInstructions(connection, blockhash, lastValidBlockHeight, request, priorityFeeConfig) {
|
|
1230
|
+
const unsignedTx = request.transaction.transaction;
|
|
1231
|
+
unsignedTx.recentBlockhash = blockhash;
|
|
1232
|
+
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
1233
|
+
await addPriorityFeeInstructions(
|
|
1234
|
+
connection,
|
|
1235
|
+
unsignedTx,
|
|
1236
|
+
priorityFeeConfig,
|
|
1237
|
+
false
|
|
1238
|
+
);
|
|
1239
|
+
return unsignedTx;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
// src/providers/wormhole/signers/SuiSigner.ts
|
|
1243
|
+
async function signAndSendTransaction5(request, wallet) {
|
|
1244
|
+
if (!wallet) {
|
|
1245
|
+
throw new Error("wallet is undefined");
|
|
1308
1246
|
}
|
|
1247
|
+
const suiDerivedWallet = wallet;
|
|
1248
|
+
const signAndExecuteTransactionFeature = suiDerivedWallet.suiWallet.features["sui:signAndExecuteTransaction"];
|
|
1249
|
+
if (!signAndExecuteTransactionFeature) {
|
|
1250
|
+
throw new Error("wallet does not support signAndExecuteTransaction");
|
|
1251
|
+
}
|
|
1252
|
+
const { digest } = await signAndExecuteTransactionFeature.signAndExecuteTransaction({
|
|
1253
|
+
transaction: request.transaction,
|
|
1254
|
+
account: suiDerivedWallet.suiWallet.accounts[0],
|
|
1255
|
+
chain: `sui:${request.network.toLocaleLowerCase()}`
|
|
1256
|
+
});
|
|
1257
|
+
return digest;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// src/providers/wormhole/signers/Signer.ts
|
|
1261
|
+
var Signer = class {
|
|
1262
|
+
_chain;
|
|
1263
|
+
_address;
|
|
1264
|
+
_options;
|
|
1265
|
+
_wallet;
|
|
1266
|
+
_crossChainCore;
|
|
1267
|
+
_sponsorAccount;
|
|
1268
|
+
_onTransactionSigned;
|
|
1269
|
+
_claimedTransactionHashes = [];
|
|
1309
1270
|
/**
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1271
|
+
* When true, signed tx hashes are written to
|
|
1272
|
+
* `_crossChainCore._lastSourceChainTxId` as a recovery side-channel.
|
|
1273
|
+
* Set to false for destination-chain claim signers so they don't
|
|
1274
|
+
* overwrite the source-chain burn hash.
|
|
1312
1275
|
*/
|
|
1276
|
+
_trackAsSourceChain;
|
|
1277
|
+
constructor(chain, address, options, wallet, crossChainCore, sponsorAccount, onTransactionSigned, trackAsSourceChain = true) {
|
|
1278
|
+
this._chain = chain;
|
|
1279
|
+
this._address = address;
|
|
1280
|
+
this._options = options;
|
|
1281
|
+
this._wallet = wallet;
|
|
1282
|
+
this._crossChainCore = crossChainCore;
|
|
1283
|
+
this._sponsorAccount = sponsorAccount;
|
|
1284
|
+
this._onTransactionSigned = onTransactionSigned;
|
|
1285
|
+
this._trackAsSourceChain = trackAsSourceChain;
|
|
1286
|
+
}
|
|
1287
|
+
chain() {
|
|
1288
|
+
return this._chain.key;
|
|
1289
|
+
}
|
|
1290
|
+
address() {
|
|
1291
|
+
return this._address;
|
|
1292
|
+
}
|
|
1313
1293
|
claimedTransactionHashes() {
|
|
1314
1294
|
return this._claimedTransactionHashes.join(",");
|
|
1315
1295
|
}
|
|
@@ -1318,446 +1298,537 @@ var SolanaLocalSigner = class {
|
|
|
1318
1298
|
this._claimedTransactionHashes = [];
|
|
1319
1299
|
for (const tx of txs) {
|
|
1320
1300
|
this._onTransactionSigned?.(tx.description, null);
|
|
1321
|
-
const txId = await
|
|
1301
|
+
const txId = await signAndSendTransaction6(
|
|
1302
|
+
this._chain,
|
|
1303
|
+
tx,
|
|
1304
|
+
this._wallet,
|
|
1305
|
+
this._options,
|
|
1306
|
+
this._crossChainCore,
|
|
1307
|
+
this._sponsorAccount
|
|
1308
|
+
);
|
|
1309
|
+
if (this._trackAsSourceChain) {
|
|
1310
|
+
this._crossChainCore._lastSourceChainTxId = txId;
|
|
1311
|
+
}
|
|
1322
1312
|
this._onTransactionSigned?.(tx.description, txId);
|
|
1323
1313
|
txHashes.push(txId);
|
|
1324
1314
|
this._claimedTransactionHashes.push(txId);
|
|
1325
1315
|
}
|
|
1326
1316
|
return txHashes;
|
|
1327
1317
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1318
|
+
};
|
|
1319
|
+
var signAndSendTransaction6 = async (chain, request, wallet, options = {}, crossChainCore, sponsorAccount) => {
|
|
1320
|
+
if (!wallet) {
|
|
1321
|
+
throw new Error("wallet is undefined");
|
|
1322
|
+
}
|
|
1323
|
+
const dappNetwork = crossChainCore._dappConfig.aptosNetwork;
|
|
1324
|
+
if (chain.context === "Solana") {
|
|
1325
|
+
const signature = await signAndSendTransaction4(
|
|
1326
|
+
request,
|
|
1327
|
+
wallet,
|
|
1328
|
+
options,
|
|
1329
|
+
crossChainCore
|
|
1330
|
+
);
|
|
1331
|
+
return signature;
|
|
1332
|
+
} else if (chain.context === "Ethereum") {
|
|
1333
|
+
const tx = await signAndSendTransaction3(
|
|
1334
|
+
request,
|
|
1335
|
+
wallet,
|
|
1336
|
+
chain.displayName
|
|
1337
|
+
);
|
|
1338
|
+
return tx;
|
|
1339
|
+
} else if (chain.context === "Sui") {
|
|
1340
|
+
const tx = await signAndSendTransaction5(
|
|
1341
|
+
request,
|
|
1342
|
+
wallet
|
|
1343
|
+
);
|
|
1344
|
+
return tx;
|
|
1345
|
+
} else if (chain.context === "Aptos") {
|
|
1346
|
+
const tx = await signAndSendTransaction2(
|
|
1347
|
+
request,
|
|
1348
|
+
wallet,
|
|
1349
|
+
sponsorAccount,
|
|
1350
|
+
dappNetwork,
|
|
1351
|
+
crossChainCore
|
|
1352
|
+
);
|
|
1353
|
+
return tx;
|
|
1354
|
+
} else {
|
|
1355
|
+
throw new Error(`Unsupported chain: ${chain}`);
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
|
|
1359
|
+
// src/providers/wormhole/wormhole.ts
|
|
1360
|
+
var WormholeProvider = class {
|
|
1361
|
+
crossChainCore;
|
|
1362
|
+
_wormholeContext;
|
|
1363
|
+
wormholeRoute;
|
|
1364
|
+
wormholeRequest;
|
|
1365
|
+
wormholeQuote;
|
|
1366
|
+
destinationChain;
|
|
1367
|
+
constructor(core) {
|
|
1368
|
+
this.crossChainCore = core;
|
|
1369
|
+
}
|
|
1370
|
+
get wormholeContext() {
|
|
1371
|
+
return this._wormholeContext;
|
|
1372
|
+
}
|
|
1373
|
+
async setWormholeContext(sourceChain) {
|
|
1374
|
+
const dappNetwork = this.crossChainCore._dappConfig?.aptosNetwork;
|
|
1375
|
+
if (dappNetwork === Network.DEVNET) {
|
|
1376
|
+
throw new Error("Devnet is not supported on Wormhole");
|
|
1341
1377
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
1357
|
-
if (this.priorityFeeConfig) {
|
|
1358
|
-
await addPriorityFeeInstructions(
|
|
1359
|
-
this.connection,
|
|
1360
|
-
unsignedTx,
|
|
1361
|
-
this.priorityFeeConfig,
|
|
1362
|
-
this.verbose
|
|
1363
|
-
);
|
|
1364
|
-
}
|
|
1365
|
-
if (additionalSigners && additionalSigners.length > 0) {
|
|
1366
|
-
unsignedTx.sign(this.keypair, ...additionalSigners);
|
|
1367
|
-
} else {
|
|
1368
|
-
unsignedTx.sign(this.keypair);
|
|
1369
|
-
}
|
|
1370
|
-
} else if (unsignedTx.recentBlockhash !== void 0 || unsignedTx.feePayer !== void 0) {
|
|
1371
|
-
unsignedTx.recentBlockhash = blockhash;
|
|
1372
|
-
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
1373
|
-
if (this.priorityFeeConfig) {
|
|
1374
|
-
await addPriorityFeeInstructions(
|
|
1375
|
-
this.connection,
|
|
1376
|
-
unsignedTx,
|
|
1377
|
-
this.priorityFeeConfig,
|
|
1378
|
-
this.verbose
|
|
1379
|
-
);
|
|
1380
|
-
}
|
|
1381
|
-
if (additionalSigners && additionalSigners.length > 0) {
|
|
1382
|
-
unsignedTx.sign(this.keypair, ...additionalSigners);
|
|
1383
|
-
} else {
|
|
1384
|
-
unsignedTx.sign(this.keypair);
|
|
1378
|
+
if (!sourceChain) {
|
|
1379
|
+
throw new Error("Origin chain not selected");
|
|
1380
|
+
}
|
|
1381
|
+
const isMainnet = dappNetwork === Network.MAINNET;
|
|
1382
|
+
const platforms = [aptos, solana, evm, sui];
|
|
1383
|
+
const dappConfig = this.crossChainCore._dappConfig;
|
|
1384
|
+
const chains = this.crossChainCore.CHAINS;
|
|
1385
|
+
const solanaRpc = dappConfig?.solanaConfig?.rpc ?? chains.Solana?.defaultRpc;
|
|
1386
|
+
const suiRpc = dappConfig?.suiConfig?.rpc ?? chains.Sui?.defaultRpc;
|
|
1387
|
+
const evmChainsConfig = {};
|
|
1388
|
+
for (const name of EVM_CHAIN_NAMES) {
|
|
1389
|
+
const rpc = dappConfig?.evmConfig?.[name]?.rpc ?? chains[name]?.defaultRpc;
|
|
1390
|
+
if (rpc) {
|
|
1391
|
+
evmChainsConfig[name] = { rpc };
|
|
1385
1392
|
}
|
|
1386
|
-
} else {
|
|
1387
|
-
throw new Error(
|
|
1388
|
-
`Unsupported transaction type: ${unsignedTx?.constructor?.name}`
|
|
1389
|
-
);
|
|
1390
1393
|
}
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
{
|
|
1397
|
-
connection: this.connection,
|
|
1398
|
-
commitment: this.commitment,
|
|
1399
|
-
retryIntervalMs: this.retryIntervalMs,
|
|
1400
|
-
verbose: this.verbose
|
|
1394
|
+
const wh = await wormhole(isMainnet ? "Mainnet" : "Testnet", platforms, {
|
|
1395
|
+
chains: {
|
|
1396
|
+
...solanaRpc ? { Solana: { rpc: solanaRpc } } : {},
|
|
1397
|
+
...suiRpc ? { Sui: { rpc: suiRpc } } : {},
|
|
1398
|
+
...evmChainsConfig
|
|
1401
1399
|
}
|
|
1400
|
+
});
|
|
1401
|
+
this._wormholeContext = wh;
|
|
1402
|
+
}
|
|
1403
|
+
async getRoute(sourceChain, destinationChain) {
|
|
1404
|
+
if (!this._wormholeContext) {
|
|
1405
|
+
throw new Error("Wormhole context not initialized");
|
|
1406
|
+
}
|
|
1407
|
+
const { route: cctpRoute, request } = await createCCTPRoute(
|
|
1408
|
+
this._wormholeContext,
|
|
1409
|
+
sourceChain,
|
|
1410
|
+
destinationChain,
|
|
1411
|
+
this.crossChainCore.TOKENS
|
|
1402
1412
|
);
|
|
1403
|
-
|
|
1413
|
+
this.wormholeRoute = cctpRoute;
|
|
1414
|
+
this.wormholeRequest = request;
|
|
1415
|
+
this.destinationChain = destinationChain;
|
|
1416
|
+
return { route: cctpRoute, request };
|
|
1404
1417
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
explorerUrl: "https://sepolia.basescan.org",
|
|
1435
|
-
explorerName: "Basescan",
|
|
1436
|
-
icon: "BaseSepolia",
|
|
1437
|
-
symbol: "BASE",
|
|
1438
|
-
defaultRpc: "https://chain-proxy.wallet.coinbase.com?targetName=base-sepolia"
|
|
1439
|
-
},
|
|
1440
|
-
ArbitrumSepolia: {
|
|
1441
|
-
key: "ArbitrumSepolia",
|
|
1442
|
-
context: "Ethereum" /* ETH */,
|
|
1443
|
-
chainId: 421614,
|
|
1444
|
-
displayName: "Arbitrum Sepolia",
|
|
1445
|
-
explorerUrl: "https://sepolia.arbiscan.io",
|
|
1446
|
-
explorerName: "Etherscan",
|
|
1447
|
-
icon: "Arbitrum",
|
|
1448
|
-
symbol: "ARB",
|
|
1449
|
-
defaultRpc: "https://sepolia-rollup.arbitrum.io/rpc"
|
|
1450
|
-
},
|
|
1451
|
-
Avalanche: {
|
|
1452
|
-
key: "Avalanche",
|
|
1453
|
-
context: "Ethereum" /* ETH */,
|
|
1454
|
-
chainId: 43113,
|
|
1455
|
-
displayName: "Avalanche Fuji",
|
|
1456
|
-
explorerUrl: "https://testnet.snowtrace.io",
|
|
1457
|
-
explorerName: "Avascan",
|
|
1458
|
-
icon: "Avalanche",
|
|
1459
|
-
symbol: "AVAX",
|
|
1460
|
-
defaultRpc: "https://api.avax-test.network/ext/bc/C/rpc"
|
|
1461
|
-
},
|
|
1462
|
-
PolygonSepolia: {
|
|
1463
|
-
key: "PolygonSepolia",
|
|
1464
|
-
context: "Ethereum" /* ETH */,
|
|
1465
|
-
chainId: 80002,
|
|
1466
|
-
displayName: "Polygon",
|
|
1467
|
-
explorerUrl: "https://amoy.polygonscan.com/",
|
|
1468
|
-
explorerName: "PolygonScan",
|
|
1469
|
-
icon: "Polygon",
|
|
1470
|
-
symbol: "MATIC",
|
|
1471
|
-
defaultRpc: "https://rpc-amoy.polygon.technology/"
|
|
1472
|
-
},
|
|
1473
|
-
Solana: {
|
|
1474
|
-
key: "Solana",
|
|
1475
|
-
context: "Solana" /* SOLANA */,
|
|
1476
|
-
displayName: "Solana",
|
|
1477
|
-
explorerUrl: "https://solscan.io",
|
|
1478
|
-
explorerName: "Solscan",
|
|
1479
|
-
chainId: 0,
|
|
1480
|
-
icon: "Solana",
|
|
1481
|
-
symbol: "SOL",
|
|
1482
|
-
defaultRpc: "https://api.devnet.solana.com"
|
|
1483
|
-
},
|
|
1484
|
-
Aptos: {
|
|
1485
|
-
key: "Aptos",
|
|
1486
|
-
context: "Aptos" /* APTOS */,
|
|
1487
|
-
displayName: "Aptos",
|
|
1488
|
-
explorerUrl: "https://explorer.aptoslabs.com?network=testnet",
|
|
1489
|
-
explorerName: "Aptos Explorer",
|
|
1490
|
-
chainId: 0,
|
|
1491
|
-
icon: "Aptos",
|
|
1492
|
-
symbol: "APT",
|
|
1493
|
-
defaultRpc: "https://fullnode.testnet.aptos.dev"
|
|
1494
|
-
},
|
|
1495
|
-
Sui: {
|
|
1496
|
-
key: "Sui",
|
|
1497
|
-
context: "Sui" /* SUI */,
|
|
1498
|
-
displayName: "Sui",
|
|
1499
|
-
explorerUrl: "https://suiscan.xyz/testnet",
|
|
1500
|
-
explorerName: "Suiscan",
|
|
1501
|
-
chainId: 0,
|
|
1502
|
-
icon: "Sui",
|
|
1503
|
-
symbol: "SUI",
|
|
1504
|
-
defaultRpc: "https://fullnode.testnet.sui.io:443"
|
|
1418
|
+
async getQuote(input) {
|
|
1419
|
+
const { amount, originChain, type } = input;
|
|
1420
|
+
if (!this._wormholeContext) {
|
|
1421
|
+
await this.setWormholeContext(originChain);
|
|
1422
|
+
}
|
|
1423
|
+
logger.log("type", type);
|
|
1424
|
+
const sourceChain = type === "transfer" ? originChain : "Aptos";
|
|
1425
|
+
const destinationChain = type === "transfer" ? "Aptos" : originChain;
|
|
1426
|
+
const { route, request } = await this.getRoute(
|
|
1427
|
+
sourceChain,
|
|
1428
|
+
destinationChain
|
|
1429
|
+
);
|
|
1430
|
+
const transferParams = {
|
|
1431
|
+
amount,
|
|
1432
|
+
options: { nativeGas: 0 }
|
|
1433
|
+
};
|
|
1434
|
+
const validated = await route.validate(request, transferParams);
|
|
1435
|
+
if (!validated.valid) {
|
|
1436
|
+
logger.log("invalid", validated.valid);
|
|
1437
|
+
throw new Error(`Invalid quote: ${validated.error}`);
|
|
1438
|
+
}
|
|
1439
|
+
const quote = await route.quote(request, validated.params);
|
|
1440
|
+
if (!quote.success) {
|
|
1441
|
+
logger.log("quote failed", quote.success);
|
|
1442
|
+
throw new Error(`Invalid quote: ${quote.error}`);
|
|
1443
|
+
}
|
|
1444
|
+
this.wormholeQuote = quote;
|
|
1445
|
+
logger.log("quote", quote);
|
|
1446
|
+
return quote;
|
|
1505
1447
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
Sepolia: {
|
|
1511
|
-
symbol: "USDC",
|
|
1512
|
-
icon: "USDC",
|
|
1513
|
-
decimals: 6,
|
|
1514
|
-
tokenId: {
|
|
1515
|
-
chain: "Sepolia",
|
|
1516
|
-
address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
1448
|
+
async submitCCTPTransfer(input) {
|
|
1449
|
+
const { sourceChain, wallet, destinationAddress, onTransactionSigned } = input;
|
|
1450
|
+
if (!this._wormholeContext) {
|
|
1451
|
+
await this.setWormholeContext(sourceChain);
|
|
1517
1452
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
symbol: "USDC",
|
|
1521
|
-
tokenId: {
|
|
1522
|
-
chain: "Solana",
|
|
1523
|
-
address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
|
|
1524
|
-
},
|
|
1525
|
-
icon: "USDC",
|
|
1526
|
-
decimals: 6
|
|
1527
|
-
},
|
|
1528
|
-
Aptos: {
|
|
1529
|
-
symbol: "USDC",
|
|
1530
|
-
decimals: 6,
|
|
1531
|
-
tokenId: {
|
|
1532
|
-
chain: "Aptos",
|
|
1533
|
-
address: "0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832"
|
|
1534
|
-
},
|
|
1535
|
-
icon: "USDC"
|
|
1536
|
-
},
|
|
1537
|
-
BaseSepolia: {
|
|
1538
|
-
symbol: "USDC",
|
|
1539
|
-
icon: "USDC",
|
|
1540
|
-
decimals: 6,
|
|
1541
|
-
tokenId: {
|
|
1542
|
-
chain: "BaseSepolia",
|
|
1543
|
-
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
1453
|
+
if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
|
|
1454
|
+
throw new Error("Wormhole route, request, or quote not initialized");
|
|
1544
1455
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1456
|
+
let signerAddress;
|
|
1457
|
+
const chainContext = this.getChainConfig(sourceChain).context;
|
|
1458
|
+
if (chainContext === "Solana") {
|
|
1459
|
+
signerAddress = wallet.solanaWallet.publicKey?.toBase58() || "";
|
|
1460
|
+
} else if (chainContext === "Ethereum") {
|
|
1461
|
+
[signerAddress] = await wallet.eip1193Provider.request({
|
|
1462
|
+
method: "eth_requestAccounts"
|
|
1463
|
+
});
|
|
1464
|
+
} else if (chainContext === "Sui") {
|
|
1465
|
+
signerAddress = wallet.suiWallet.accounts[0].address || "";
|
|
1466
|
+
} else {
|
|
1467
|
+
throw new Error(`Unsupported chain context: ${chainContext}`);
|
|
1553
1468
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1469
|
+
logger.log("signerAddress", signerAddress);
|
|
1470
|
+
const signer = new Signer(
|
|
1471
|
+
this.getChainConfig(sourceChain),
|
|
1472
|
+
signerAddress,
|
|
1473
|
+
{},
|
|
1474
|
+
wallet,
|
|
1475
|
+
this.crossChainCore,
|
|
1476
|
+
void 0,
|
|
1477
|
+
onTransactionSigned
|
|
1478
|
+
);
|
|
1479
|
+
logger.log("signer", signer);
|
|
1480
|
+
logger.log("wormholeRequest", this.wormholeRequest);
|
|
1481
|
+
logger.log("wormholeQuote", this.wormholeQuote);
|
|
1482
|
+
const receipt = await this.wormholeRoute.initiate(
|
|
1483
|
+
this.wormholeRequest,
|
|
1484
|
+
signer,
|
|
1485
|
+
this.wormholeQuote,
|
|
1486
|
+
Wormhole2.chainAddress("Aptos", destinationAddress.toString())
|
|
1487
|
+
);
|
|
1488
|
+
const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
|
|
1489
|
+
return { originChainTxnId: originChainTxnId || "", receipt };
|
|
1490
|
+
}
|
|
1491
|
+
async claimCCTPTransfer(input) {
|
|
1492
|
+
let { receipt, mainSigner, sponsorAccount, onTransactionSigned } = input;
|
|
1493
|
+
if (!this.wormholeRoute) {
|
|
1494
|
+
throw new Error("Wormhole route not initialized");
|
|
1562
1495
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
decimals: 6,
|
|
1568
|
-
tokenId: {
|
|
1569
|
-
chain: "PolygonSepolia",
|
|
1570
|
-
address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582"
|
|
1496
|
+
if (sponsorAccount && !isAccount(sponsorAccount)) {
|
|
1497
|
+
throw new Error(
|
|
1498
|
+
"AptosLocalSigner does not support GasStationApiKey as a sponsor account. Wormhole claim transactions are script-based and cannot be submitted via the gas station. Please provide an Account instance as the sponsor, or omit the sponsor account."
|
|
1499
|
+
);
|
|
1571
1500
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1501
|
+
logger.log("mainSigner", mainSigner.accountAddress.toString());
|
|
1502
|
+
let retries = 0;
|
|
1503
|
+
const maxRetries = 5;
|
|
1504
|
+
const baseDelay = 1e3;
|
|
1505
|
+
while (retries < maxRetries) {
|
|
1506
|
+
try {
|
|
1507
|
+
for await (receipt of this.wormholeRoute.track(receipt, 120 * 1e3)) {
|
|
1508
|
+
if (receipt.state >= TransferState.SourceInitiated) {
|
|
1509
|
+
logger.log("Receipt is on track ", receipt);
|
|
1510
|
+
try {
|
|
1511
|
+
const signer = new AptosLocalSigner(
|
|
1512
|
+
"Aptos",
|
|
1513
|
+
{},
|
|
1514
|
+
mainSigner,
|
|
1515
|
+
// the account that signs the "claim" transaction
|
|
1516
|
+
sponsorAccount,
|
|
1517
|
+
// the fee payer account
|
|
1518
|
+
this.crossChainCore,
|
|
1519
|
+
onTransactionSigned
|
|
1520
|
+
);
|
|
1521
|
+
if (routes2.isManual(this.wormholeRoute)) {
|
|
1522
|
+
const circleAttestationReceipt = await this.wormholeRoute.complete(signer, receipt);
|
|
1523
|
+
logger.log("Claim receipt: ", circleAttestationReceipt);
|
|
1524
|
+
const destinationChainTxnId = signer.claimedTransactionHashes();
|
|
1525
|
+
return { destinationChainTxnId };
|
|
1526
|
+
} else {
|
|
1527
|
+
return { destinationChainTxnId: "" };
|
|
1528
|
+
}
|
|
1529
|
+
} catch (e) {
|
|
1530
|
+
console.error("Failed to claim", e);
|
|
1531
|
+
return { destinationChainTxnId: "" };
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
} catch (e) {
|
|
1536
|
+
console.error(
|
|
1537
|
+
`Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
|
|
1538
|
+
e
|
|
1539
|
+
);
|
|
1540
|
+
const delay = baseDelay * 2 ** retries;
|
|
1541
|
+
await sleep2(delay);
|
|
1542
|
+
retries++;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return { destinationChainTxnId: "" };
|
|
1581
1546
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1547
|
+
/**
|
|
1548
|
+
* Initiates a transfer of USDC funds from the source chain wallet to the destination chain wallet
|
|
1549
|
+
* @param args
|
|
1550
|
+
* @returns
|
|
1551
|
+
*/
|
|
1552
|
+
async transfer(input) {
|
|
1553
|
+
if (this.crossChainCore._dappConfig?.aptosNetwork === Network.DEVNET) {
|
|
1554
|
+
throw new Error("Devnet is not supported on Wormhole");
|
|
1555
|
+
}
|
|
1556
|
+
if (input.amount) {
|
|
1557
|
+
await this.getQuote({
|
|
1558
|
+
amount: input.amount,
|
|
1559
|
+
originChain: input.sourceChain,
|
|
1560
|
+
type: "transfer"
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
const { originChainTxnId, receipt } = await this.submitCCTPTransfer(input);
|
|
1564
|
+
try {
|
|
1565
|
+
const { destinationChainTxnId } = await this.claimCCTPTransfer({
|
|
1566
|
+
receipt,
|
|
1567
|
+
mainSigner: input.mainSigner,
|
|
1568
|
+
sponsorAccount: input.sponsorAccount,
|
|
1569
|
+
onTransactionSigned: input.onTransactionSigned
|
|
1570
|
+
});
|
|
1571
|
+
return { originChainTxnId, destinationChainTxnId };
|
|
1572
|
+
} catch (error) {
|
|
1573
|
+
throw new TransferError(
|
|
1574
|
+
error?.message ?? "Transfer claim failed after source-chain burn",
|
|
1575
|
+
originChainTxnId,
|
|
1576
|
+
error
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
// --- Split withdraw flow: initiateWithdraw + trackWithdraw + claimWithdraw ---
|
|
1581
|
+
/**
|
|
1582
|
+
* Phase 1: Initiates a withdraw by burning USDC on Aptos.
|
|
1583
|
+
* The user signs the Aptos burn transaction via their wallet.
|
|
1584
|
+
* Returns a receipt that can be tracked and later claimed.
|
|
1585
|
+
*/
|
|
1586
|
+
async initiateWithdraw(input) {
|
|
1587
|
+
const { wallet, destinationAddress, sponsorAccount, onTransactionSigned } = input;
|
|
1588
|
+
if (!this._wormholeContext) {
|
|
1589
|
+
throw new Error("Wormhole context not initialized");
|
|
1590
|
+
}
|
|
1591
|
+
if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
|
|
1592
|
+
throw new Error("Wormhole route, request, or quote not initialized");
|
|
1593
|
+
}
|
|
1594
|
+
const signer = new Signer(
|
|
1595
|
+
this.getChainConfig("Aptos"),
|
|
1596
|
+
(await wallet.features["aptos:account"].account()).address.toString(),
|
|
1597
|
+
{},
|
|
1598
|
+
wallet,
|
|
1599
|
+
this.crossChainCore,
|
|
1600
|
+
sponsorAccount,
|
|
1601
|
+
onTransactionSigned
|
|
1602
|
+
);
|
|
1603
|
+
const wormholeDestAddress = Wormhole2.chainAddress(
|
|
1604
|
+
this.destinationChain,
|
|
1605
|
+
destinationAddress.toString()
|
|
1606
|
+
);
|
|
1607
|
+
const receipt = await this.wormholeRoute.initiate(
|
|
1608
|
+
this.wormholeRequest,
|
|
1609
|
+
signer,
|
|
1610
|
+
this.wormholeQuote,
|
|
1611
|
+
wormholeDestAddress
|
|
1612
|
+
);
|
|
1613
|
+
logger.log("initiateWithdraw receipt", receipt);
|
|
1614
|
+
const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
|
|
1615
|
+
return { originChainTxnId: originChainTxnId || "", receipt };
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Phase 2: Tracks a withdraw receipt until attestation is ready.
|
|
1619
|
+
* This polls Wormhole and returns once the receipt reaches the Attested state.
|
|
1620
|
+
*/
|
|
1621
|
+
async trackWithdraw(receipt) {
|
|
1622
|
+
if (!this.wormholeRoute) {
|
|
1623
|
+
throw new Error("Wormhole route not initialized");
|
|
1624
|
+
}
|
|
1625
|
+
let retries = 0;
|
|
1626
|
+
const maxRetries = 5;
|
|
1627
|
+
const baseDelay = 1e3;
|
|
1628
|
+
while (retries < maxRetries) {
|
|
1629
|
+
try {
|
|
1630
|
+
for await (receipt of this.wormholeRoute.track(receipt, 120 * 1e3)) {
|
|
1631
|
+
if (receipt.state >= TransferState.Attested) {
|
|
1632
|
+
logger.log("trackWithdraw: receipt attested", receipt);
|
|
1633
|
+
return receipt;
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
} catch (e) {
|
|
1637
|
+
console.error(
|
|
1638
|
+
`Error tracking withdraw (attempt ${retries + 1} / ${maxRetries}):`,
|
|
1639
|
+
e
|
|
1640
|
+
);
|
|
1641
|
+
const delay = baseDelay * 2 ** retries;
|
|
1642
|
+
await sleep2(delay);
|
|
1643
|
+
retries++;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
throw new Error("Failed to track withdraw to attested state");
|
|
1673
1647
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
symbol: "USDC",
|
|
1707
|
-
decimals: 6,
|
|
1708
|
-
icon: "USDC",
|
|
1709
|
-
tokenId: {
|
|
1710
|
-
chain: "Base",
|
|
1711
|
-
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
|
|
1648
|
+
/**
|
|
1649
|
+
* Phase 3: Claims the withdraw on the destination chain.
|
|
1650
|
+
*
|
|
1651
|
+
* If the destination is Solana and `solanaConfig.serverClaimUrl` is configured
|
|
1652
|
+
* in the dapp config, the SDK automatically POSTs the attested receipt to that
|
|
1653
|
+
* URL — no wallet popup required. The dapp's server endpoint handles signing
|
|
1654
|
+
* and submitting the claim transaction.
|
|
1655
|
+
*
|
|
1656
|
+
* Otherwise falls back to the wallet-based Signer (triggers wallet popup).
|
|
1657
|
+
*/
|
|
1658
|
+
async claimWithdraw(input) {
|
|
1659
|
+
const { claimChain, destinationAddress, receipt } = input;
|
|
1660
|
+
const serverClaimUrl = this.crossChainCore._dappConfig?.solanaConfig?.serverClaimUrl;
|
|
1661
|
+
if (claimChain === "Solana" && serverClaimUrl && !input.skipServerClaim) {
|
|
1662
|
+
logger.log("claimWithdraw: using server-side claim via", serverClaimUrl);
|
|
1663
|
+
const response = await fetch(serverClaimUrl, {
|
|
1664
|
+
method: "POST",
|
|
1665
|
+
headers: { "Content-Type": "application/json" },
|
|
1666
|
+
body: JSON.stringify({
|
|
1667
|
+
receipt: serializeReceipt(receipt),
|
|
1668
|
+
destinationAddress,
|
|
1669
|
+
claimChain
|
|
1670
|
+
})
|
|
1671
|
+
});
|
|
1672
|
+
if (!response.ok) {
|
|
1673
|
+
const errorData = await response.json().catch(() => ({}));
|
|
1674
|
+
throw new Error(
|
|
1675
|
+
errorData.error || `Server-side claim failed with status ${response.status}`
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
const result = await response.json();
|
|
1679
|
+
return { destinationChainTxnId: result.destinationChainTxnId };
|
|
1712
1680
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
symbol: "USDC",
|
|
1716
|
-
decimals: 6,
|
|
1717
|
-
icon: "USDC",
|
|
1718
|
-
tokenId: {
|
|
1719
|
-
chain: "Arbitrum",
|
|
1720
|
-
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
|
|
1681
|
+
if (!this.wormholeRoute) {
|
|
1682
|
+
throw new Error("Wormhole route not initialized");
|
|
1721
1683
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
icon: "USDC",
|
|
1727
|
-
tokenId: {
|
|
1728
|
-
chain: "Avalanche",
|
|
1729
|
-
address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
|
|
1684
|
+
if (!input.wallet) {
|
|
1685
|
+
throw new Error(
|
|
1686
|
+
"Wallet is required for claim when serverClaimUrl is not configured"
|
|
1687
|
+
);
|
|
1730
1688
|
}
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1689
|
+
const claimSigner = new Signer(
|
|
1690
|
+
this.getChainConfig(claimChain),
|
|
1691
|
+
destinationAddress,
|
|
1692
|
+
{},
|
|
1693
|
+
input.wallet,
|
|
1694
|
+
this.crossChainCore,
|
|
1695
|
+
void 0,
|
|
1696
|
+
input.onTransactionSigned,
|
|
1697
|
+
false
|
|
1698
|
+
);
|
|
1699
|
+
if (routes2.isManual(this.wormholeRoute)) {
|
|
1700
|
+
const circleAttestationReceipt = await this.wormholeRoute.complete(
|
|
1701
|
+
claimSigner,
|
|
1702
|
+
receipt
|
|
1703
|
+
);
|
|
1704
|
+
logger.log("claimWithdraw receipt:", circleAttestationReceipt);
|
|
1705
|
+
const destinationChainTxnId = claimSigner.claimedTransactionHashes();
|
|
1706
|
+
return { destinationChainTxnId };
|
|
1707
|
+
} else {
|
|
1708
|
+
throw new Error("Automatic route not supported for manual claim");
|
|
1739
1709
|
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1710
|
+
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Withdraws USDC from Aptos to a destination chain.
|
|
1713
|
+
* Orchestrates all three phases internally:
|
|
1714
|
+
* 1. Initiate — user signs the Aptos burn transaction
|
|
1715
|
+
* 2. Track — wait for Wormhole attestation
|
|
1716
|
+
* 3. Claim — if serverClaimUrl is configured for Solana, delegates to
|
|
1717
|
+
* the server; otherwise uses the wallet-based signer.
|
|
1718
|
+
*
|
|
1719
|
+
* The optional `onPhaseChange` callback lets the dapp update its UI
|
|
1720
|
+
* as the flow progresses.
|
|
1721
|
+
*/
|
|
1722
|
+
async withdraw(input) {
|
|
1723
|
+
const {
|
|
1724
|
+
sourceChain,
|
|
1725
|
+
wallet,
|
|
1726
|
+
destinationAddress,
|
|
1727
|
+
sponsorAccount,
|
|
1728
|
+
onPhaseChange,
|
|
1729
|
+
onTransactionSigned
|
|
1730
|
+
} = input;
|
|
1731
|
+
onPhaseChange?.("initiating");
|
|
1732
|
+
const { originChainTxnId, receipt } = await this.initiateWithdraw({
|
|
1733
|
+
wallet,
|
|
1734
|
+
destinationAddress,
|
|
1735
|
+
sponsorAccount,
|
|
1736
|
+
onTransactionSigned
|
|
1737
|
+
});
|
|
1738
|
+
let currentPhase = "tracking";
|
|
1739
|
+
try {
|
|
1740
|
+
onPhaseChange?.("tracking");
|
|
1741
|
+
const attestedReceipt = await this.trackWithdraw(receipt);
|
|
1742
|
+
currentPhase = "claiming";
|
|
1743
|
+
onPhaseChange?.("claiming");
|
|
1744
|
+
const { destinationChainTxnId } = await this.claimWithdraw({
|
|
1745
|
+
claimChain: sourceChain,
|
|
1746
|
+
destinationAddress: destinationAddress.toString(),
|
|
1747
|
+
receipt: attestedReceipt,
|
|
1748
|
+
wallet,
|
|
1749
|
+
onTransactionSigned
|
|
1750
|
+
});
|
|
1751
|
+
return { originChainTxnId, destinationChainTxnId };
|
|
1752
|
+
} catch (error) {
|
|
1753
|
+
throw new WithdrawError(
|
|
1754
|
+
error?.message ?? "Withdraw failed after Aptos burn",
|
|
1755
|
+
originChainTxnId,
|
|
1756
|
+
currentPhase,
|
|
1757
|
+
error
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* Retries a failed `claimWithdraw` call with configurable exponential backoff.
|
|
1763
|
+
*
|
|
1764
|
+
* Use this when the claim phase of a withdrawal fails (e.g., RPC instability,
|
|
1765
|
+
* network congestion) but the Aptos burn transaction has already been submitted.
|
|
1766
|
+
* The attested receipt can be recovered from the `WithdrawError` thrown by
|
|
1767
|
+
* `withdraw()` and passed directly to this method.
|
|
1768
|
+
*
|
|
1769
|
+
* @example
|
|
1770
|
+
* ```ts
|
|
1771
|
+
* try {
|
|
1772
|
+
* await provider.withdraw({ ... });
|
|
1773
|
+
* } catch (error) {
|
|
1774
|
+
* if (error instanceof WithdrawError && error.phase === "claiming") {
|
|
1775
|
+
* const result = await provider.retryWithdrawClaim({
|
|
1776
|
+
* sourceChain,
|
|
1777
|
+
* destinationAddress,
|
|
1778
|
+
* receipt: attestedReceipt,
|
|
1779
|
+
* wallet,
|
|
1780
|
+
* maxRetries: 5,
|
|
1781
|
+
* });
|
|
1782
|
+
* }
|
|
1783
|
+
* }
|
|
1784
|
+
* ```
|
|
1785
|
+
*/
|
|
1786
|
+
async retryWithdrawClaim(input) {
|
|
1787
|
+
const {
|
|
1788
|
+
maxRetries = 5,
|
|
1789
|
+
initialDelayMs = 2e3,
|
|
1790
|
+
backoffMultiplier = 2,
|
|
1791
|
+
...claimInput
|
|
1792
|
+
} = input;
|
|
1793
|
+
let lastError;
|
|
1794
|
+
let delay = initialDelayMs;
|
|
1795
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1796
|
+
try {
|
|
1797
|
+
const result = await this.claimWithdraw(claimInput);
|
|
1798
|
+
return { ...result, retriesUsed: attempt };
|
|
1799
|
+
} catch (error) {
|
|
1800
|
+
lastError = error;
|
|
1801
|
+
logger.log(
|
|
1802
|
+
`retryWithdrawClaim: attempt ${attempt + 1}/${maxRetries + 1} failed: ${lastError.message}`
|
|
1803
|
+
);
|
|
1804
|
+
if (attempt < maxRetries) {
|
|
1805
|
+
await sleep2(delay);
|
|
1806
|
+
delay *= backoffMultiplier;
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
throw new Error(
|
|
1811
|
+
`Claim failed after ${maxRetries + 1} attempts: ${lastError?.message}`
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
getChainConfig(chain) {
|
|
1815
|
+
const chainConfig = this.crossChainCore.CHAINS[chain];
|
|
1816
|
+
if (!chainConfig) {
|
|
1817
|
+
throw new Error(`Chain config not found for chain: ${chain}`);
|
|
1818
|
+
}
|
|
1819
|
+
return chainConfig;
|
|
1749
1820
|
}
|
|
1750
1821
|
};
|
|
1751
1822
|
|
|
1752
1823
|
// src/utils/getUsdcBalance.ts
|
|
1753
1824
|
import { Aptos as Aptos3, AptosConfig as AptosConfig3, Network as Network2 } from "@aptos-labs/ts-sdk";
|
|
1754
|
-
import { Connection as Connection4, PublicKey } from "@solana/web3.js";
|
|
1755
|
-
import { ethers as ethers2, JsonRpcProvider } from "ethers";
|
|
1756
1825
|
import { SuiClient } from "@mysten/sui/client";
|
|
1826
|
+
import { Connection as Connection2, PublicKey } from "@solana/web3.js";
|
|
1827
|
+
import { ethers as ethers2, JsonRpcProvider } from "ethers";
|
|
1757
1828
|
var getSolanaWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
|
|
1758
1829
|
const address = new PublicKey(walletAddress);
|
|
1759
|
-
const tokenAddress = aptosNetwork === Network2.MAINNET ? mainnetTokens
|
|
1760
|
-
const connection = new
|
|
1830
|
+
const tokenAddress = aptosNetwork === Network2.MAINNET ? mainnetTokens.Solana.tokenId.address : testnetTokens.Solana.tokenId.address;
|
|
1831
|
+
const connection = new Connection2(rpc);
|
|
1761
1832
|
const splToken = await connection.getTokenAccountsByOwner(address, {
|
|
1762
1833
|
mint: new PublicKey(tokenAddress)
|
|
1763
1834
|
});
|
|
@@ -1779,7 +1850,7 @@ var getEthereumWalletUSDCBalance = async (walletAddress, aptosNetwork, chain, rp
|
|
|
1779
1850
|
return ethers2.formatUnits(balance, token.decimals).toString();
|
|
1780
1851
|
};
|
|
1781
1852
|
var getAptosWalletUSDCBalance = async (walletAddress, aptosNetwork) => {
|
|
1782
|
-
const token = aptosNetwork === Network2.MAINNET ? mainnetTokens
|
|
1853
|
+
const token = aptosNetwork === Network2.MAINNET ? mainnetTokens.Aptos : testnetTokens.Aptos;
|
|
1783
1854
|
const tokenAddress = token.tokenId.address;
|
|
1784
1855
|
const aptosConfig = new AptosConfig3({ network: aptosNetwork });
|
|
1785
1856
|
const connection = new Aptos3(aptosConfig);
|
|
@@ -1797,7 +1868,7 @@ var getAptosWalletUSDCBalance = async (walletAddress, aptosNetwork) => {
|
|
|
1797
1868
|
return ethers2.formatUnits(BigInt(response[0].amount), token.decimals);
|
|
1798
1869
|
};
|
|
1799
1870
|
var getSuiWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
|
|
1800
|
-
const token = aptosNetwork === Network2.MAINNET ? mainnetTokens
|
|
1871
|
+
const token = aptosNetwork === Network2.MAINNET ? mainnetTokens.Sui : testnetTokens.Sui;
|
|
1801
1872
|
const client = new SuiClient({
|
|
1802
1873
|
url: rpc
|
|
1803
1874
|
});
|
|
@@ -1836,13 +1907,20 @@ var EthereumChainIdToMainnetChain = {
|
|
|
1836
1907
|
43114: mainnetChains.Avalanche,
|
|
1837
1908
|
137: mainnetChains.Polygon
|
|
1838
1909
|
};
|
|
1839
|
-
var
|
|
1910
|
+
var CrossChainCore = class {
|
|
1911
|
+
_dappConfig = {
|
|
1912
|
+
aptosNetwork: Network3.TESTNET
|
|
1913
|
+
};
|
|
1914
|
+
CHAINS = testnetChains;
|
|
1915
|
+
TOKENS = testnetTokens;
|
|
1916
|
+
/**
|
|
1917
|
+
* Last known source-chain transaction ID, set by signers immediately after
|
|
1918
|
+
* a transaction is submitted. Acts as a recovery side-channel so that
|
|
1919
|
+
* callers can retrieve the tx hash even when the orchestration layer throws
|
|
1920
|
+
* before returning it (e.g. claim failure after a successful burn).
|
|
1921
|
+
*/
|
|
1922
|
+
_lastSourceChainTxId;
|
|
1840
1923
|
constructor(args) {
|
|
1841
|
-
this._dappConfig = {
|
|
1842
|
-
aptosNetwork: Network3.TESTNET
|
|
1843
|
-
};
|
|
1844
|
-
this.CHAINS = testnetChains;
|
|
1845
|
-
this.TOKENS = testnetTokens;
|
|
1846
1924
|
this._dappConfig = args.dappConfig;
|
|
1847
1925
|
if (args.dappConfig?.aptosNetwork === Network3.MAINNET) {
|
|
1848
1926
|
this.CHAINS = mainnetChains;
|
|
@@ -1903,13 +1981,10 @@ var CrossChainCore2 = class {
|
|
|
1903
1981
|
}
|
|
1904
1982
|
}
|
|
1905
1983
|
};
|
|
1906
|
-
|
|
1907
|
-
// src/index.ts
|
|
1908
|
-
import { Network as Network4 } from "@aptos-labs/ts-sdk";
|
|
1909
1984
|
export {
|
|
1910
1985
|
AptosLocalSigner,
|
|
1911
1986
|
Context,
|
|
1912
|
-
|
|
1987
|
+
CrossChainCore,
|
|
1913
1988
|
EVM_CHAIN_NAMES,
|
|
1914
1989
|
EthereumChainIdToMainnetChain,
|
|
1915
1990
|
EthereumChainIdToTestnetChain,
|