@aptos-labs/cross-chain-core 4.25.0 → 5.0.1

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.
Files changed (40) hide show
  1. package/README.md +11 -0
  2. package/dist/CrossChainCore.d.ts +3 -3
  3. package/dist/CrossChainCore.d.ts.map +1 -1
  4. package/dist/config/mainnet/chains.d.ts +0 -14
  5. package/dist/config/mainnet/chains.d.ts.map +1 -1
  6. package/dist/config/mainnet/tokens.d.ts +0 -1
  7. package/dist/config/mainnet/tokens.d.ts.map +1 -1
  8. package/dist/config/testnet/chains.d.ts +0 -16
  9. package/dist/config/testnet/chains.d.ts.map +1 -1
  10. package/dist/config/testnet/tokens.d.ts +0 -1
  11. package/dist/config/testnet/tokens.d.ts.map +1 -1
  12. package/dist/index.js +272 -92
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +263 -73
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -1
  17. package/dist/providers/wormhole/signers/AptosSigner.d.ts +7 -0
  18. package/dist/providers/wormhole/signers/AptosSigner.d.ts.map +1 -0
  19. package/dist/providers/wormhole/signers/Signer.d.ts +7 -2
  20. package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -1
  21. package/dist/providers/wormhole/types.d.ts +14 -3
  22. package/dist/providers/wormhole/types.d.ts.map +1 -1
  23. package/dist/providers/wormhole/wormhole.d.ts +7 -9
  24. package/dist/providers/wormhole/wormhole.d.ts.map +1 -1
  25. package/dist/utils/getUsdcBalance.d.ts.map +1 -1
  26. package/dist/version.d.ts +1 -1
  27. package/dist/version.d.ts.map +1 -1
  28. package/package.json +9 -9
  29. package/src/CrossChainCore.ts +18 -19
  30. package/src/config/mainnet/chains.ts +15 -15
  31. package/src/config/mainnet/tokens.ts +10 -11
  32. package/src/config/testnet/chains.ts +15 -16
  33. package/src/config/testnet/tokens.ts +10 -11
  34. package/src/providers/wormhole/signers/AptosLocalSigner.ts +4 -3
  35. package/src/providers/wormhole/signers/AptosSigner.ts +139 -0
  36. package/src/providers/wormhole/signers/Signer.ts +26 -2
  37. package/src/providers/wormhole/types.ts +16 -3
  38. package/src/providers/wormhole/wormhole.ts +165 -29
  39. package/src/utils/getUsdcBalance.ts +9 -11
  40. package/src/version.ts +1 -1
@@ -24,13 +24,15 @@ import { ChainConfig } from "../../config";
24
24
  import {
25
25
  WormholeQuoteRequest,
26
26
  WormholeQuoteResponse,
27
- WormholeInitiateTransferRequest,
28
- WormholeInitiateTransferResponse,
27
+ WormholeTransferRequest,
28
+ WormholeTransferResponse,
29
29
  WormholeRouteResponse,
30
30
  WormholeRequest,
31
31
  WormholeSubmitTransferRequest,
32
32
  WormholeStartTransferResponse,
33
33
  WormholeClaimTransferRequest,
34
+ WormholeWithdrawRequest,
35
+ WormholeWithdrawResponse,
34
36
  } from "./types";
35
37
  import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
36
38
  import { EIP1193DerivedWallet } from "@aptos-labs/derived-wallet-ethereum";
@@ -40,8 +42,10 @@ export class WormholeProvider
40
42
  CrossChainProvider<
41
43
  WormholeQuoteRequest,
42
44
  WormholeQuoteResponse,
43
- WormholeInitiateTransferRequest,
44
- WormholeInitiateTransferResponse
45
+ WormholeTransferRequest,
46
+ WormholeTransferResponse,
47
+ WormholeWithdrawRequest,
48
+ WormholeWithdrawResponse
45
49
  >
46
50
  {
47
51
  private crossChainCore: CrossChainCore;
@@ -60,7 +64,7 @@ export class WormholeProvider
60
64
  return this._wormholeContext;
61
65
  }
62
66
 
63
- async setWormholeContext(sourceChain: Chain) {
67
+ private async setWormholeContext(sourceChain: Chain) {
64
68
  const dappNetwork = this.crossChainCore._dappConfig?.aptosNetwork;
65
69
  if (dappNetwork === Network.DEVNET) {
66
70
  throw new Error("Devnet is not supported on Wormhole");
@@ -74,7 +78,10 @@ export class WormholeProvider
74
78
  this._wormholeContext = wh;
75
79
  }
76
80
 
77
- async getRoute(sourceChain: Chain): Promise<{
81
+ private async getRoute(
82
+ sourceChain: Chain,
83
+ destinationChain: Chain
84
+ ): Promise<{
78
85
  route: WormholeRouteResponse;
79
86
  request: WormholeRequest;
80
87
  }> {
@@ -82,19 +89,23 @@ export class WormholeProvider
82
89
  throw new Error("Wormhole context not initialized");
83
90
  }
84
91
 
85
- const { sourceToken, destToken } = this.getTokenInfo(sourceChain);
92
+ const { sourceToken, destToken } = this.getTokenInfo(
93
+ sourceChain,
94
+ destinationChain
95
+ );
86
96
 
97
+ const destContext = this._wormholeContext
98
+ .getPlatform(chainToPlatform(destinationChain))
99
+ .getChain(destinationChain);
87
100
  const sourceContext = this._wormholeContext
88
101
  .getPlatform(chainToPlatform(sourceChain))
89
102
  .getChain(sourceChain);
90
103
 
91
104
  logger.log("sourceContext", sourceContext);
92
-
93
- const destContext = this._wormholeContext
94
- .getPlatform(chainToPlatform("Aptos"))
95
- .getChain("Aptos");
105
+ logger.log("sourceToken", sourceToken);
96
106
 
97
107
  logger.log("destContext", destContext);
108
+ logger.log("destToken", destToken);
98
109
 
99
110
  const request = await routes.RouteTransferRequest.create(
100
111
  this._wormholeContext,
@@ -103,7 +114,7 @@ export class WormholeProvider
103
114
  destination: destToken,
104
115
  },
105
116
  sourceContext,
106
- destContext,
117
+ destContext
107
118
  );
108
119
 
109
120
  const resolver = this._wormholeContext.resolver([
@@ -120,13 +131,22 @@ export class WormholeProvider
120
131
  }
121
132
 
122
133
  async getQuote(input: WormholeQuoteRequest): Promise<WormholeQuoteResponse> {
123
- const { amount, sourceChain } = input;
134
+ const { amount, originChain, type } = input;
124
135
 
125
136
  if (!this._wormholeContext) {
126
- await this.setWormholeContext(sourceChain);
137
+ await this.setWormholeContext(originChain);
127
138
  }
128
139
 
129
- const { route, request } = await this.getRoute(sourceChain);
140
+ logger.log("type", type);
141
+ // If the type of the transaction is "transfer", we want to transfer from a x-chain wallet to the Aptos wallet
142
+ // If the type of the transaction is "withdraw", we want to transfer from the Aptos wallet to a x-chain wallet
143
+ const sourceChain = type === "transfer" ? originChain : "Aptos";
144
+ const destinationChain = type === "transfer" ? "Aptos" : originChain;
145
+
146
+ const { route, request } = await this.getRoute(
147
+ sourceChain,
148
+ destinationChain
149
+ );
130
150
 
131
151
  // TODO what is nativeGas for?
132
152
  const transferParams = {
@@ -150,7 +170,7 @@ export class WormholeProvider
150
170
  }
151
171
 
152
172
  async submitCCTPTransfer(
153
- input: WormholeSubmitTransferRequest,
173
+ input: WormholeSubmitTransferRequest
154
174
  ): Promise<WormholeStartTransferResponse> {
155
175
  const { sourceChain, wallet, destinationAddress } = input;
156
176
 
@@ -184,14 +204,14 @@ export class WormholeProvider
184
204
  this.getChainConfig(sourceChain),
185
205
  signerAddress,
186
206
  {},
187
- wallet,
207
+ wallet
188
208
  );
189
209
 
190
210
  let receipt = await this.wormholeRoute.initiate(
191
211
  this.wormholeRequest,
192
212
  signer,
193
213
  this.wormholeQuote,
194
- Wormhole.chainAddress("Aptos", destinationAddress.toString()),
214
+ Wormhole.chainAddress("Aptos", destinationAddress.toString())
195
215
  );
196
216
 
197
217
  const originChainTxnId =
@@ -203,7 +223,7 @@ export class WormholeProvider
203
223
  }
204
224
 
205
225
  async claimCCTPTransfer(
206
- input: WormholeClaimTransferRequest,
226
+ input: WormholeClaimTransferRequest
207
227
  ): Promise<{ destinationChainTxnId: string }> {
208
228
  let { receipt, mainSigner, sponsorAccount } = input;
209
229
  if (!this.wormholeRoute) {
@@ -227,7 +247,7 @@ export class WormholeProvider
227
247
  "Aptos",
228
248
  {},
229
249
  mainSigner, // the account that signs the "claim" transaction
230
- sponsorAccount ? sponsorAccount : undefined, // the fee payer account
250
+ sponsorAccount ? sponsorAccount : undefined // the fee payer account
231
251
  );
232
252
 
233
253
  if (routes.isManual(this.wormholeRoute)) {
@@ -249,7 +269,7 @@ export class WormholeProvider
249
269
  } catch (e) {
250
270
  console.error(
251
271
  `Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
252
- e,
272
+ e
253
273
  );
254
274
  const delay = baseDelay * Math.pow(2, retries); // Exponential backoff
255
275
  await sleep(delay);
@@ -265,9 +285,9 @@ export class WormholeProvider
265
285
  * @param args
266
286
  * @returns
267
287
  */
268
- async initiateCCTPTransfer(
269
- input: WormholeInitiateTransferRequest,
270
- ): Promise<WormholeInitiateTransferResponse> {
288
+ async transfer(
289
+ input: WormholeTransferRequest
290
+ ): Promise<WormholeTransferResponse> {
271
291
  if (this.crossChainCore._dappConfig?.aptosNetwork === Network.DEVNET) {
272
292
  throw new Error("Devnet is not supported on Wormhole");
273
293
  }
@@ -276,7 +296,8 @@ export class WormholeProvider
276
296
  if (input.amount) {
277
297
  await this.getQuote({
278
298
  amount: input.amount,
279
- sourceChain: input.sourceChain,
299
+ originChain: input.sourceChain,
300
+ type: "transfer",
280
301
  });
281
302
  }
282
303
  // Submit transfer transaction from origin chain
@@ -290,6 +311,118 @@ export class WormholeProvider
290
311
  return { originChainTxnId, destinationChainTxnId };
291
312
  }
292
313
 
314
+ async withdraw(
315
+ input: WormholeWithdrawRequest
316
+ ): Promise<WormholeWithdrawResponse> {
317
+ const { sourceChain, wallet, destinationAddress, sponsorAccount } = input;
318
+ logger.log("sourceChain", sourceChain);
319
+ logger.log("wallet", wallet);
320
+ logger.log("destinationAddress", destinationAddress);
321
+ logger.log("sponsorAccount", sponsorAccount);
322
+
323
+ if (!this._wormholeContext) {
324
+ await this.setWormholeContext(sourceChain);
325
+ }
326
+ if (!this._wormholeContext) {
327
+ throw new Error("Wormhole context not initialized");
328
+ }
329
+ if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
330
+ throw new Error("Wormhole route, request, or quote not initialized");
331
+ }
332
+
333
+ const signer = new Signer(
334
+ this.getChainConfig("Aptos"),
335
+ (
336
+ await input.wallet.features["aptos:account"].account()
337
+ ).address.toString(),
338
+ {},
339
+ input.wallet,
340
+ undefined,
341
+ sponsorAccount
342
+ );
343
+
344
+ logger.log("signer", signer);
345
+ logger.log("wormholeRequest", this.wormholeRequest);
346
+ logger.log("wormholeQuote", this.wormholeQuote);
347
+ logger.log(
348
+ "Wormhole.chainAddress",
349
+ Wormhole.chainAddress(sourceChain, input.destinationAddress.toString())
350
+ );
351
+
352
+ let receipt = await this.wormholeRoute.initiate(
353
+ this.wormholeRequest,
354
+ signer,
355
+ this.wormholeQuote,
356
+ Wormhole.chainAddress(sourceChain, input.destinationAddress.toString())
357
+ );
358
+ logger.log("receipt", receipt);
359
+
360
+ const originChainTxnId =
361
+ "originTxs" in receipt
362
+ ? receipt.originTxs[receipt.originTxs.length - 1].txid
363
+ : undefined;
364
+
365
+ let retries = 0;
366
+ const maxRetries = 5;
367
+ const baseDelay = 1000; // Initial delay of 1 second
368
+
369
+ while (retries < maxRetries) {
370
+ try {
371
+ for await (receipt of this.wormholeRoute.track(receipt, 120 * 1000)) {
372
+ if (receipt.state >= TransferState.SourceInitiated) {
373
+ logger.log("Receipt is on track ", receipt);
374
+
375
+ try {
376
+ const signer = new Signer(
377
+ this.getChainConfig(sourceChain),
378
+ destinationAddress.toString(),
379
+ {},
380
+ wallet
381
+ );
382
+
383
+ if (routes.isManual(this.wormholeRoute)) {
384
+ const circleAttestationReceipt =
385
+ await this.wormholeRoute.complete(signer, receipt);
386
+ logger.log("Claim receipt: ", circleAttestationReceipt);
387
+
388
+ const destinationChainTxnId = signer.claimedTransactionHashes();
389
+ return {
390
+ originChainTxnId: originChainTxnId || "",
391
+ destinationChainTxnId,
392
+ };
393
+ } else {
394
+ // Should be unreachable
395
+ return {
396
+ originChainTxnId: originChainTxnId || "",
397
+ destinationChainTxnId: "",
398
+ };
399
+ }
400
+ } catch (e) {
401
+ console.error("Failed to claim", e);
402
+ return {
403
+ originChainTxnId: originChainTxnId || "",
404
+ destinationChainTxnId: "",
405
+ };
406
+ }
407
+ }
408
+ }
409
+ } catch (e) {
410
+ console.error(
411
+ `Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
412
+ e
413
+ );
414
+ const delay = baseDelay * Math.pow(2, retries); // Exponential backoff
415
+ await sleep(delay);
416
+ retries++;
417
+ }
418
+ }
419
+
420
+ return {
421
+ originChainTxnId: originChainTxnId || "",
422
+ destinationChainTxnId: "",
423
+ };
424
+ }
425
+
293
426
  getChainConfig(chain: Chain): ChainConfig {
294
427
  const chainConfig =
295
428
  this.crossChainCore.CHAINS[
@@ -301,18 +434,21 @@ export class WormholeProvider
301
434
  return chainConfig;
302
435
  }
303
436
 
304
- getTokenInfo(sourceChain: Chain): {
437
+ getTokenInfo(
438
+ sourceChain: Chain,
439
+ destinationChain: Chain
440
+ ): {
305
441
  sourceToken: TokenId;
306
442
  destToken: TokenId;
307
443
  } {
308
444
  const sourceToken: TokenId = Wormhole.tokenId(
309
445
  this.crossChainCore.TOKENS[sourceChain].tokenId.chain as Chain,
310
- this.crossChainCore.TOKENS[sourceChain].tokenId.address,
446
+ this.crossChainCore.TOKENS[sourceChain].tokenId.address
311
447
  );
312
448
 
313
449
  const destToken: TokenId = Wormhole.tokenId(
314
- this.crossChainCore.APTOS_TOKEN.tokenId.chain as Chain,
315
- this.crossChainCore.APTOS_TOKEN.tokenId.address,
450
+ this.crossChainCore.TOKENS[destinationChain].tokenId.chain as Chain,
451
+ this.crossChainCore.TOKENS[destinationChain].tokenId.address
316
452
  );
317
453
 
318
454
  return { sourceToken, destToken };
@@ -1,17 +1,12 @@
1
1
  import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
2
2
  import { Connection, PublicKey } from "@solana/web3.js";
3
- import {
4
- AptosMainnetUSDCToken,
5
- AptosTestnetUSDCToken,
6
- mainnetTokens,
7
- testnetTokens,
8
- } from "../config";
3
+ import { mainnetTokens, testnetTokens } from "../config";
9
4
  import { ethers, JsonRpcProvider } from "ethers";
10
5
 
11
6
  export const getSolanaWalletUSDCBalance = async (
12
7
  walletAddress: string,
13
8
  aptosNetwork: Network,
14
- rpc: string,
9
+ rpc: string
15
10
  ): Promise<string> => {
16
11
  const address = new PublicKey(walletAddress);
17
12
  const tokenAddress =
@@ -40,7 +35,7 @@ export const getSolanaWalletUSDCBalance = async (
40
35
  export const getEthereumWalletUSDCBalance = async (
41
36
  walletAddress: string,
42
37
  aptosNetwork: Network,
43
- rpc: string,
38
+ rpc: string
44
39
  ): Promise<string> => {
45
40
  const token =
46
41
  aptosNetwork === Network.MAINNET
@@ -57,12 +52,12 @@ export const getEthereumWalletUSDCBalance = async (
57
52
 
58
53
  export const getAptosWalletUSDCBalance = async (
59
54
  walletAddress: string,
60
- aptosNetwork: Network,
55
+ aptosNetwork: Network
61
56
  ): Promise<string> => {
62
57
  const token =
63
58
  aptosNetwork === Network.MAINNET
64
- ? AptosMainnetUSDCToken
65
- : AptosTestnetUSDCToken;
59
+ ? mainnetTokens["Aptos"]
60
+ : testnetTokens["Aptos"];
66
61
  const tokenAddress = token.tokenId.address;
67
62
  const aptosConfig = new AptosConfig({ network: aptosNetwork });
68
63
  const connection = new Aptos(aptosConfig);
@@ -74,6 +69,9 @@ export const getAptosWalletUSDCBalance = async (
74
69
  },
75
70
  },
76
71
  });
72
+ if (response.length === 0) {
73
+ return "0";
74
+ }
77
75
  const balance = (
78
76
  Number(response[0].amount) /
79
77
  10 ** token.decimals
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const CROSS_CHAIN_CORE_VERSION = "4.25.0";
1
+ export const CROSS_CHAIN_CORE_VERSION = "5.0.1";