@aptos-labs/cross-chain-core 4.23.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 (66) hide show
  1. package/LICENSE +201 -0
  2. package/dist/CrossChainCore.d.ts +36 -0
  3. package/dist/CrossChainCore.d.ts.map +1 -0
  4. package/dist/config/index.d.ts +4 -0
  5. package/dist/config/index.d.ts.map +1 -0
  6. package/dist/config/mainnet/chains.d.ts +17 -0
  7. package/dist/config/mainnet/chains.d.ts.map +1 -0
  8. package/dist/config/mainnet/index.d.ts +3 -0
  9. package/dist/config/mainnet/index.d.ts.map +1 -0
  10. package/dist/config/mainnet/tokens.d.ts +4 -0
  11. package/dist/config/mainnet/tokens.d.ts.map +1 -0
  12. package/dist/config/testnet/chains.d.ts +19 -0
  13. package/dist/config/testnet/chains.d.ts.map +1 -0
  14. package/dist/config/testnet/index.d.ts +3 -0
  15. package/dist/config/testnet/index.d.ts.map +1 -0
  16. package/dist/config/testnet/tokens.d.ts +4 -0
  17. package/dist/config/testnet/tokens.d.ts.map +1 -0
  18. package/dist/config/types.d.ts +41 -0
  19. package/dist/config/types.d.ts.map +1 -0
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +989 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/index.mjs +957 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/providers/wormhole/index.d.ts +5 -0
  27. package/dist/providers/wormhole/index.d.ts.map +1 -0
  28. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +18 -0
  29. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -0
  30. package/dist/providers/wormhole/signers/EthereumSigner.d.ts +5 -0
  31. package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -0
  32. package/dist/providers/wormhole/signers/Signer.d.ts +17 -0
  33. package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -0
  34. package/dist/providers/wormhole/signers/SolanaSigner.d.ts +28 -0
  35. package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -0
  36. package/dist/providers/wormhole/types.d.ts +39 -0
  37. package/dist/providers/wormhole/types.d.ts.map +1 -0
  38. package/dist/providers/wormhole/wormhole.d.ts +35 -0
  39. package/dist/providers/wormhole/wormhole.d.ts.map +1 -0
  40. package/dist/utils/getUsdcBalance.d.ts +5 -0
  41. package/dist/utils/getUsdcBalance.d.ts.map +1 -0
  42. package/dist/utils/logger.d.ts +6 -0
  43. package/dist/utils/logger.d.ts.map +1 -0
  44. package/dist/version.d.ts +2 -0
  45. package/dist/version.d.ts.map +1 -0
  46. package/package.json +83 -0
  47. package/src/CrossChainCore.ts +130 -0
  48. package/src/config/index.ts +3 -0
  49. package/src/config/mainnet/chains.ts +64 -0
  50. package/src/config/mainnet/index.ts +2 -0
  51. package/src/config/mainnet/tokens.ts +43 -0
  52. package/src/config/testnet/chains.ts +69 -0
  53. package/src/config/testnet/index.ts +2 -0
  54. package/src/config/testnet/tokens.ts +43 -0
  55. package/src/config/types.ts +45 -0
  56. package/src/index.ts +5 -0
  57. package/src/providers/wormhole/index.ts +4 -0
  58. package/src/providers/wormhole/signers/AptosLocalSigner.ts +136 -0
  59. package/src/providers/wormhole/signers/EthereumSigner.ts +49 -0
  60. package/src/providers/wormhole/signers/Signer.ts +102 -0
  61. package/src/providers/wormhole/signers/SolanaSigner.ts +418 -0
  62. package/src/providers/wormhole/types.ts +59 -0
  63. package/src/providers/wormhole/wormhole.ts +320 -0
  64. package/src/utils/getUsdcBalance.ts +82 -0
  65. package/src/utils/logger.ts +17 -0
  66. package/src/version.ts +1 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,957 @@
1
+ // src/CrossChainCore.ts
2
+ import { Network as Network3 } from "@aptos-labs/ts-sdk";
3
+
4
+ // src/providers/wormhole/wormhole.ts
5
+ import {
6
+ chainToPlatform,
7
+ routes,
8
+ Wormhole,
9
+ wormhole,
10
+ TransferState
11
+ } from "@wormhole-foundation/sdk";
12
+ import { Network, sleep as sleep2 } from "@aptos-labs/ts-sdk";
13
+ import aptos from "@wormhole-foundation/sdk/aptos";
14
+ import solana from "@wormhole-foundation/sdk/solana";
15
+ import evm from "@wormhole-foundation/sdk/evm";
16
+
17
+ // src/utils/logger.ts
18
+ var logger = {
19
+ log: (...args) => {
20
+ if (process.env.NODE_ENV === "development") {
21
+ console.log(...args);
22
+ }
23
+ },
24
+ warn: (...args) => {
25
+ if (process.env.NODE_ENV === "development") {
26
+ console.warn(...args);
27
+ }
28
+ },
29
+ error: (...args) => {
30
+ if (process.env.NODE_ENV === "development") {
31
+ console.error(...args);
32
+ }
33
+ }
34
+ };
35
+
36
+ // src/providers/wormhole/signers/AptosLocalSigner.ts
37
+ import {
38
+ Aptos,
39
+ AptosConfig,
40
+ Network as AptosNetwork
41
+ } from "@aptos-labs/ts-sdk";
42
+ var AptosLocalSigner = class {
43
+ constructor(chain, options, wallet, feePayerAccount) {
44
+ this._chain = chain;
45
+ this._options = options;
46
+ this._wallet = wallet;
47
+ this._sponsorAccount = feePayerAccount;
48
+ this._claimedTransactionHashes = "";
49
+ }
50
+ chain() {
51
+ return this._chain;
52
+ }
53
+ address() {
54
+ return this._wallet.accountAddress.toString();
55
+ }
56
+ claimedTransactionHashes() {
57
+ return this._claimedTransactionHashes;
58
+ }
59
+ async signAndSend(txs) {
60
+ const txHashes = [];
61
+ for (const tx of txs) {
62
+ const txId = await signAndSendTransaction(
63
+ tx,
64
+ this._wallet,
65
+ this._sponsorAccount
66
+ );
67
+ txHashes.push(txId);
68
+ this._claimedTransactionHashes = txId;
69
+ }
70
+ return txHashes;
71
+ }
72
+ };
73
+ async function signAndSendTransaction(request, wallet, sponsorAccount) {
74
+ if (!wallet) {
75
+ throw new Error("Wallet is undefined");
76
+ }
77
+ const payload = request.transaction;
78
+ payload.functionArguments = payload.functionArguments.map((a) => {
79
+ if (a instanceof Uint8Array) {
80
+ return Array.from(a);
81
+ } else if (typeof a === "bigint") {
82
+ return a.toString();
83
+ } else {
84
+ return a;
85
+ }
86
+ });
87
+ const aptosConfig = new AptosConfig({
88
+ network: AptosNetwork.TESTNET
89
+ });
90
+ const aptos2 = new Aptos(aptosConfig);
91
+ const txnToSign = await aptos2.transaction.build.simple({
92
+ data: payload,
93
+ sender: wallet.accountAddress.toString(),
94
+ withFeePayer: sponsorAccount ? true : false
95
+ });
96
+ const senderAuthenticator = await aptos2.transaction.sign({
97
+ signer: wallet,
98
+ transaction: txnToSign
99
+ });
100
+ const txnToSubmit = {
101
+ transaction: txnToSign,
102
+ senderAuthenticator
103
+ };
104
+ if (sponsorAccount) {
105
+ if (typeof sponsorAccount === "string") {
106
+ } else {
107
+ const feePayerSignerAuthenticator = aptos2.transaction.signAsFeePayer({
108
+ signer: sponsorAccount,
109
+ transaction: txnToSign
110
+ });
111
+ txnToSubmit.feePayerAuthenticator = feePayerSignerAuthenticator;
112
+ }
113
+ }
114
+ const response = await aptos2.transaction.submit.simple(txnToSubmit);
115
+ const tx = await aptos2.waitForTransaction({
116
+ transactionHash: response.hash
117
+ });
118
+ return tx.hash;
119
+ }
120
+
121
+ // src/providers/wormhole/signers/SolanaSigner.ts
122
+ import {
123
+ ComputeBudgetProgram,
124
+ LAMPORTS_PER_SOL
125
+ } from "@solana/web3.js";
126
+ import {
127
+ determinePriorityFee,
128
+ determinePriorityFeeTritonOne
129
+ } from "@wormhole-foundation/sdk-solana";
130
+ import { Connection } from "@solana/web3.js";
131
+ import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
132
+ async function signAndSendTransaction2(request, wallet, options, crossChainCore) {
133
+ var _a, _b, _c, _d;
134
+ if (!wallet || !(wallet instanceof SolanaDerivedWallet)) {
135
+ throw new Error("Invalid wallet type or missing Solana wallet").message;
136
+ }
137
+ const commitment = (_a = options == null ? void 0 : options.commitment) != null ? _a : "finalized";
138
+ const connection = new Connection(
139
+ (_d = (_c = (_b = crossChainCore == null ? void 0 : crossChainCore._dappConfig) == null ? void 0 : _b.solanaConfig) == null ? void 0 : _c.rpc) != null ? _d : "https://api.devnet.solana.com"
140
+ );
141
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(commitment);
142
+ const transaction = request.transaction.transaction;
143
+ const unsignedTx = await setPriorityFeeInstructions(
144
+ connection,
145
+ blockhash,
146
+ lastValidBlockHeight,
147
+ request,
148
+ crossChainCore
149
+ );
150
+ let confirmTransactionPromise = null;
151
+ let confirmedTx = null;
152
+ let txSendAttempts = 1;
153
+ let signature = "";
154
+ if (!wallet.solanaWallet.signTransaction) {
155
+ throw new Error("Wallet does not support signing transactions").message;
156
+ }
157
+ const tx = await wallet.solanaWallet.signTransaction(unsignedTx);
158
+ if (!tx)
159
+ throw new Error("Failed to sign transaction").message;
160
+ const serializedTx = tx.serialize();
161
+ const sendOptions = {
162
+ skipPreflight: true,
163
+ maxRetries: 0,
164
+ preFlightCommitment: commitment
165
+ };
166
+ signature = await connection.sendRawTransaction(serializedTx, sendOptions);
167
+ confirmTransactionPromise = connection.confirmTransaction(
168
+ {
169
+ signature,
170
+ blockhash,
171
+ lastValidBlockHeight
172
+ },
173
+ commitment
174
+ );
175
+ const txRetryInterval = 5e3;
176
+ while (!confirmedTx) {
177
+ confirmedTx = await Promise.race([
178
+ confirmTransactionPromise,
179
+ new Promise(
180
+ (resolve) => setTimeout(() => {
181
+ resolve(null);
182
+ }, txRetryInterval)
183
+ )
184
+ ]);
185
+ if (confirmedTx) {
186
+ break;
187
+ }
188
+ console.log(
189
+ `Tx not confirmed after ${txRetryInterval * txSendAttempts++}ms, resending`
190
+ );
191
+ try {
192
+ await connection.sendRawTransaction(serializedTx, sendOptions);
193
+ } catch (e) {
194
+ console.error("Failed to resend transaction:", e);
195
+ }
196
+ }
197
+ if (confirmedTx.value.err) {
198
+ let errorMessage = `Transaction failed: ${confirmedTx.value.err}`;
199
+ if (typeof confirmedTx.value.err === "object") {
200
+ try {
201
+ errorMessage = `Transaction failed: ${JSON.stringify(
202
+ confirmedTx.value.err,
203
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
204
+ )}`;
205
+ } catch (e) {
206
+ errorMessage = `Transaction failed: Unknown error`;
207
+ }
208
+ }
209
+ throw new Error(`Transaction failed: ${errorMessage}`).message;
210
+ }
211
+ return signature;
212
+ }
213
+ async function setPriorityFeeInstructions(connection, blockhash, lastValidBlockHeight, request, crossChainCore) {
214
+ const unsignedTx = request.transaction.transaction;
215
+ const computeBudgetIxFilter = (ix) => ix.programId.toString() !== "ComputeBudget111111111111111111111111111111";
216
+ unsignedTx.recentBlockhash = blockhash;
217
+ unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
218
+ unsignedTx.instructions = unsignedTx.instructions.filter(
219
+ computeBudgetIxFilter
220
+ );
221
+ unsignedTx.add(
222
+ ...await createPriorityFeeInstructions(
223
+ connection,
224
+ unsignedTx,
225
+ crossChainCore
226
+ )
227
+ );
228
+ if (request.transaction.signers) {
229
+ unsignedTx.partialSign(...request.transaction.signers);
230
+ }
231
+ return unsignedTx;
232
+ }
233
+ async function createPriorityFeeInstructions(connection, transaction, crossChainCore) {
234
+ var _a, _b, _c;
235
+ let unitsUsed = 2e5;
236
+ let simulationAttempts = 0;
237
+ simulationLoop:
238
+ while (true) {
239
+ const response = await connection.simulateTransaction(
240
+ transaction
241
+ );
242
+ if (response.value.err) {
243
+ if (checkKnownSimulationError(response.value)) {
244
+ if (simulationAttempts < 5) {
245
+ simulationAttempts++;
246
+ await sleep(1e3);
247
+ continue simulationLoop;
248
+ }
249
+ } else if (simulationAttempts < 3) {
250
+ simulationAttempts++;
251
+ await sleep(1e3);
252
+ continue simulationLoop;
253
+ }
254
+ throw new Error(
255
+ `Simulation failed: ${JSON.stringify(response.value.err)}
256
+ Logs:
257
+ ${(response.value.logs || []).join("\n ")}`
258
+ ).message;
259
+ } else {
260
+ if (response.value.unitsConsumed) {
261
+ unitsUsed = response.value.unitsConsumed;
262
+ }
263
+ break;
264
+ }
265
+ }
266
+ const unitBudget = Math.floor(unitsUsed * 1.2);
267
+ const instructions = [];
268
+ instructions.push(
269
+ ComputeBudgetProgram.setComputeUnitLimit({
270
+ units: unitBudget
271
+ })
272
+ );
273
+ const {
274
+ percentile = 0.9,
275
+ percentileMultiple = 1,
276
+ min = 1e5,
277
+ max = 1e8
278
+ } = (_c = (_b = (_a = crossChainCore == null ? void 0 : crossChainCore._dappConfig) == null ? void 0 : _a.solanaConfig) == null ? void 0 : _b.priorityFeeConfig) != null ? _c : {};
279
+ const calculateFee = async (rpcProvider2) => {
280
+ if (rpcProvider2 === "triton") {
281
+ try {
282
+ const fee2 = await determinePriorityFeeTritonOne(
283
+ connection,
284
+ transaction,
285
+ percentile,
286
+ percentileMultiple,
287
+ min,
288
+ max
289
+ );
290
+ return {
291
+ fee: fee2,
292
+ methodUsed: "triton"
293
+ };
294
+ } catch (e) {
295
+ console.warn(`Failed to determine priority fee using Triton RPC:`, e);
296
+ }
297
+ }
298
+ try {
299
+ const fee2 = await determinePriorityFee(
300
+ connection,
301
+ transaction,
302
+ percentile,
303
+ percentileMultiple,
304
+ min,
305
+ max
306
+ );
307
+ return {
308
+ fee: fee2,
309
+ methodUsed: "default"
310
+ };
311
+ } catch (e) {
312
+ console.warn(`Failed to determine priority fee using Triton RPC:`, e);
313
+ return {
314
+ fee: min,
315
+ methodUsed: "minimum"
316
+ };
317
+ }
318
+ };
319
+ const rpcProvider = determineRpcProvider(connection.rpcEndpoint);
320
+ const { fee, methodUsed } = await calculateFee(rpcProvider);
321
+ const maxFeeInSol = fee / 1e6 / LAMPORTS_PER_SOL * unitBudget;
322
+ console.table({
323
+ "RPC Provider": rpcProvider,
324
+ "Method used": methodUsed,
325
+ "Percentile used": percentile,
326
+ "Multiple used": percentileMultiple,
327
+ "Compute budget": unitBudget,
328
+ "Priority fee": fee,
329
+ "Max fee in SOL": maxFeeInSol
330
+ });
331
+ instructions.push(
332
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: fee })
333
+ );
334
+ return instructions;
335
+ }
336
+ function checkKnownSimulationError(response) {
337
+ const errors = {};
338
+ if (response.err === "BlockhashNotFound") {
339
+ errors["BlockhashNotFound"] = "Blockhash not found during simulation. Trying again.";
340
+ }
341
+ if (response.logs) {
342
+ for (const line of response.logs) {
343
+ if (line.includes("SlippageToleranceExceeded")) {
344
+ errors["SlippageToleranceExceeded"] = "Slippage failure during simulation. Trying again.";
345
+ }
346
+ if (line.includes("RequireGteViolated")) {
347
+ errors["RequireGteViolated"] = "Swap instruction failure during simulation. Trying again.";
348
+ }
349
+ }
350
+ }
351
+ if (isEmptyObject(errors)) {
352
+ return false;
353
+ }
354
+ console.table(errors);
355
+ return true;
356
+ }
357
+ async function sleep(timeout) {
358
+ return new Promise((resolve) => setTimeout(resolve, timeout));
359
+ }
360
+ var isEmptyObject = (value) => {
361
+ if (value === null || value === void 0) {
362
+ return true;
363
+ }
364
+ for (const key in value) {
365
+ if (value.hasOwnProperty.call(value, key)) {
366
+ return false;
367
+ }
368
+ }
369
+ return true;
370
+ };
371
+ function determineRpcProvider(endpoint) {
372
+ try {
373
+ const url = new URL(endpoint);
374
+ const hostname = url.hostname;
375
+ if (hostname === "rpcpool.com") {
376
+ return "triton";
377
+ } else if (hostname === "helius-rpc.com") {
378
+ return "helius";
379
+ } else if (hostname === "rpc.ankr.com") {
380
+ return "ankr";
381
+ } else {
382
+ return "unknown";
383
+ }
384
+ } catch (e) {
385
+ return "unknown";
386
+ }
387
+ }
388
+
389
+ // src/providers/wormhole/signers/EthereumSigner.ts
390
+ import { ethers, getBigInt } from "ethers";
391
+ async function signAndSendTransaction3(request, wallet, chainName, options) {
392
+ if (!wallet) {
393
+ throw new Error("wallet.sendTransaction is undefined").message;
394
+ }
395
+ const chainId = await wallet.eip1193Provider.request({
396
+ method: "eth_chainId"
397
+ });
398
+ const actualChainId = parseInt(chainId, 16);
399
+ if (!actualChainId)
400
+ throw new Error("No signer found for chain" + chainName).message;
401
+ const expectedChainId = request.transaction.chainId ? getBigInt(request.transaction.chainId) : void 0;
402
+ if (!actualChainId || !expectedChainId || BigInt(actualChainId) !== expectedChainId) {
403
+ throw new Error(
404
+ `Signer is not connected to the right chain. Expected ${expectedChainId}, got ${actualChainId}`
405
+ ).message;
406
+ }
407
+ const provider = new ethers.BrowserProvider(
408
+ wallet.eip1193Provider
409
+ );
410
+ const signer = await provider.getSigner();
411
+ const response = await signer.sendTransaction(request.transaction);
412
+ const receipt = await response.wait();
413
+ return (receipt == null ? void 0 : receipt.hash) || "";
414
+ }
415
+
416
+ // src/providers/wormhole/signers/Signer.ts
417
+ var Signer = class {
418
+ constructor(chain, address, options, wallet, crossChainCore) {
419
+ this._chain = chain;
420
+ this._address = address;
421
+ this._options = options;
422
+ this._wallet = wallet;
423
+ this._crossChainCore = crossChainCore;
424
+ }
425
+ chain() {
426
+ return this._chain.displayName;
427
+ }
428
+ address() {
429
+ return this._address;
430
+ }
431
+ async signAndSend(txs) {
432
+ const txHashes = [];
433
+ for (const tx of txs) {
434
+ const txId = await signAndSendTransaction4(
435
+ this._chain,
436
+ tx,
437
+ this._wallet,
438
+ this._options,
439
+ this._crossChainCore
440
+ );
441
+ txHashes.push(txId);
442
+ }
443
+ return txHashes;
444
+ }
445
+ };
446
+ var signAndSendTransaction4 = async (chain, request, wallet, options = {}, crossChainCore) => {
447
+ if (!wallet) {
448
+ throw new Error("wallet is undefined");
449
+ }
450
+ if (chain.context === "Solana") {
451
+ const signature = await signAndSendTransaction2(
452
+ request,
453
+ wallet,
454
+ options,
455
+ crossChainCore
456
+ );
457
+ return signature;
458
+ } else if (chain.context === "Ethereum") {
459
+ const tx = await signAndSendTransaction3(
460
+ request,
461
+ wallet,
462
+ chain.displayName,
463
+ options
464
+ );
465
+ return tx;
466
+ } else {
467
+ throw new Error(`Unsupported chain: ${chain}`);
468
+ }
469
+ };
470
+
471
+ // src/providers/wormhole/wormhole.ts
472
+ var WormholeProvider = class {
473
+ constructor(core) {
474
+ this.crossChainCore = core;
475
+ }
476
+ get wormholeContext() {
477
+ return this._wormholeContext;
478
+ }
479
+ async setWormholeContext(sourceChain) {
480
+ var _a;
481
+ const dappNetwork = (_a = this.crossChainCore._dappConfig) == null ? void 0 : _a.aptosNetwork;
482
+ if (dappNetwork === Network.DEVNET) {
483
+ throw new Error("Devnet is not supported on Wormhole");
484
+ }
485
+ if (!sourceChain) {
486
+ throw new Error("Origin chain not selected");
487
+ }
488
+ const isMainnet = dappNetwork === Network.MAINNET;
489
+ const platforms = [aptos, solana, evm];
490
+ const wh = await wormhole(isMainnet ? "Mainnet" : "Testnet", platforms);
491
+ this._wormholeContext = wh;
492
+ }
493
+ async getRoute(sourceChain) {
494
+ if (!this._wormholeContext) {
495
+ throw new Error("Wormhole context not initialized");
496
+ }
497
+ const { sourceToken, destToken } = this.getTokenInfo(sourceChain);
498
+ const sourceContext = this._wormholeContext.getPlatform(chainToPlatform(sourceChain)).getChain(sourceChain);
499
+ logger.log("sourceContext", sourceContext);
500
+ const destContext = this._wormholeContext.getPlatform(chainToPlatform("Aptos")).getChain("Aptos");
501
+ logger.log("destContext", destContext);
502
+ const request = await routes.RouteTransferRequest.create(
503
+ this._wormholeContext,
504
+ {
505
+ source: sourceToken,
506
+ destination: destToken
507
+ },
508
+ sourceContext,
509
+ destContext
510
+ );
511
+ const resolver = this._wormholeContext.resolver([
512
+ routes.CCTPRoute
513
+ ]);
514
+ const route = await resolver.findRoutes(request);
515
+ const cctpRoute = route[0];
516
+ this.wormholeRoute = cctpRoute;
517
+ this.wormholeRequest = request;
518
+ return { route: cctpRoute, request };
519
+ }
520
+ async getQuote(input) {
521
+ const { amount, sourceChain } = input;
522
+ if (!this._wormholeContext) {
523
+ await this.setWormholeContext(sourceChain);
524
+ }
525
+ const { route, request } = await this.getRoute(sourceChain);
526
+ const transferParams = {
527
+ amount,
528
+ options: { nativeGas: 0 }
529
+ };
530
+ const validated = await route.validate(request, transferParams);
531
+ if (!validated.valid) {
532
+ logger.log("invalid", validated.valid);
533
+ throw new Error(`Invalid quote: ${validated.error}`).message;
534
+ }
535
+ const quote = await route.quote(request, validated.params);
536
+ if (!quote.success) {
537
+ logger.log("quote failed", quote.success);
538
+ throw new Error(`Invalid quote: ${quote.error}`).message;
539
+ }
540
+ this.wormholeQuote = quote;
541
+ logger.log("quote", quote);
542
+ return quote;
543
+ }
544
+ async submitCCTPTransfer(input) {
545
+ var _a;
546
+ const { sourceChain, wallet, destinationAddress } = input;
547
+ if (!this._wormholeContext) {
548
+ await this.setWormholeContext(sourceChain);
549
+ }
550
+ if (!this.wormholeRoute || !this.wormholeRequest || !this.wormholeQuote) {
551
+ throw new Error("Wormhole route, request, or quote not initialized");
552
+ }
553
+ let signerAddress;
554
+ const chainContext = this.getChainConfig(sourceChain).context;
555
+ if (chainContext === "Solana") {
556
+ signerAddress = ((_a = wallet.solanaWallet.publicKey) == null ? void 0 : _a.toBase58()) || "";
557
+ } else {
558
+ [signerAddress] = await wallet.eip1193Provider.request({
559
+ method: "eth_requestAccounts"
560
+ });
561
+ }
562
+ logger.log("signerAddress", signerAddress);
563
+ const signer = new Signer(
564
+ this.getChainConfig(sourceChain),
565
+ signerAddress,
566
+ {},
567
+ wallet
568
+ );
569
+ let receipt = await this.wormholeRoute.initiate(
570
+ this.wormholeRequest,
571
+ signer,
572
+ this.wormholeQuote,
573
+ Wormhole.chainAddress("Aptos", destinationAddress.toString())
574
+ );
575
+ const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
576
+ return { originChainTxnId: originChainTxnId || "", receipt };
577
+ }
578
+ async claimCCTPTransfer(input) {
579
+ let { receipt, mainSigner, sponsorAccount } = input;
580
+ if (!this.wormholeRoute) {
581
+ throw new Error("Wormhole route not initialized");
582
+ }
583
+ logger.log("mainSigner", mainSigner.accountAddress.toString());
584
+ let retries = 0;
585
+ const maxRetries = 5;
586
+ const baseDelay = 1e3;
587
+ while (retries < maxRetries) {
588
+ try {
589
+ for await (receipt of this.wormholeRoute.track(receipt, 120 * 1e3)) {
590
+ if (receipt.state >= TransferState.SourceInitiated) {
591
+ logger.log("Receipt is on track ", receipt);
592
+ try {
593
+ const signer = new AptosLocalSigner(
594
+ "Aptos",
595
+ {},
596
+ mainSigner,
597
+ sponsorAccount ? sponsorAccount : void 0
598
+ );
599
+ if (routes.isManual(this.wormholeRoute)) {
600
+ const circleAttestationReceipt = await this.wormholeRoute.complete(signer, receipt);
601
+ logger.log("Claim receipt: ", circleAttestationReceipt);
602
+ const destinationChainTxnId = signer.claimedTransactionHashes();
603
+ return { destinationChainTxnId };
604
+ } else {
605
+ return { destinationChainTxnId: "" };
606
+ }
607
+ } catch (e) {
608
+ console.error("Failed to claim", e);
609
+ return { destinationChainTxnId: "" };
610
+ }
611
+ }
612
+ }
613
+ } catch (e) {
614
+ console.error(
615
+ `Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
616
+ e
617
+ );
618
+ const delay = baseDelay * Math.pow(2, retries);
619
+ await sleep2(delay);
620
+ retries++;
621
+ }
622
+ }
623
+ return { destinationChainTxnId: "" };
624
+ }
625
+ async initiateCCTPTransfer(input) {
626
+ var _a;
627
+ if (((_a = this.crossChainCore._dappConfig) == null ? void 0 : _a.aptosNetwork) === Network.DEVNET) {
628
+ throw new Error("Devnet is not supported on Wormhole");
629
+ }
630
+ if (input.amount) {
631
+ await this.getQuote({
632
+ amount: input.amount,
633
+ sourceChain: input.sourceChain
634
+ });
635
+ }
636
+ let { originChainTxnId, receipt } = await this.submitCCTPTransfer(input);
637
+ const { destinationChainTxnId } = await this.claimCCTPTransfer({
638
+ receipt,
639
+ mainSigner: input.mainSigner,
640
+ sponsorAccount: input.sponsorAccount
641
+ });
642
+ return { originChainTxnId, destinationChainTxnId };
643
+ }
644
+ getChainConfig(chain) {
645
+ const chainConfig = this.crossChainCore.CHAINS[chain];
646
+ if (!chainConfig) {
647
+ throw new Error(`Chain config not found for chain: ${chain}`);
648
+ }
649
+ return chainConfig;
650
+ }
651
+ getTokenInfo(sourceChain) {
652
+ const sourceToken = Wormhole.tokenId(
653
+ this.crossChainCore.TOKENS[sourceChain].tokenId.chain,
654
+ this.crossChainCore.TOKENS[sourceChain].tokenId.address
655
+ );
656
+ const destToken = Wormhole.tokenId(
657
+ this.crossChainCore.APTOS_TOKEN.tokenId.chain,
658
+ this.crossChainCore.APTOS_TOKEN.tokenId.address
659
+ );
660
+ return { sourceToken, destToken };
661
+ }
662
+ };
663
+
664
+ // src/config/types.ts
665
+ var Context = /* @__PURE__ */ ((Context2) => {
666
+ Context2["ETH"] = "Ethereum";
667
+ Context2["SOLANA"] = "Solana";
668
+ Context2["APTOS"] = "Aptos";
669
+ return Context2;
670
+ })(Context || {});
671
+
672
+ // src/config/testnet/chains.ts
673
+ var testnetChains = {
674
+ Sepolia: {
675
+ key: "Sepolia",
676
+ id: 10002,
677
+ context: "Ethereum" /* ETH */,
678
+ finalityThreshold: 0,
679
+ displayName: "Sepolia",
680
+ explorerUrl: "https://sepolia.etherscan.io/",
681
+ explorerName: "Etherscan",
682
+ gasToken: "ETHsepolia",
683
+ chainId: 11155111,
684
+ icon: "Ethereum",
685
+ maxBlockSearch: 2e3,
686
+ symbol: "ETH",
687
+ defaultRpc: "https://eth-sepolia.public.blastapi.io",
688
+ wrappedGasToken: "0xeef12A83EE5b7161D3873317c8E0E7B76e0B5D9c"
689
+ },
690
+ Solana: {
691
+ key: "Solana",
692
+ id: 1,
693
+ context: "Solana" /* SOLANA */,
694
+ finalityThreshold: 32,
695
+ displayName: "Solana",
696
+ explorerUrl: "https://explorer.solana.com/",
697
+ explorerName: "Solana Explorer",
698
+ gasToken: "SOL",
699
+ chainId: 0,
700
+ icon: "Solana",
701
+ maxBlockSearch: 2e3,
702
+ symbol: "SOL",
703
+ defaultRpc: "https://api.devnet.solana.com",
704
+ wrappedGasToken: "So11111111111111111111111111111111111111112"
705
+ }
706
+ };
707
+ var AptosTestnetChain = {
708
+ key: "Aptos",
709
+ id: 22,
710
+ context: "Aptos" /* APTOS */,
711
+ finalityThreshold: 0,
712
+ displayName: "Aptos",
713
+ explorerUrl: "https://explorer.aptoslabs.com?network=testnet",
714
+ explorerName: "Aptos Explorer",
715
+ gasToken: "APT",
716
+ chainId: 0,
717
+ icon: "Aptos",
718
+ maxBlockSearch: 0,
719
+ symbol: "APT",
720
+ sdkName: "Aptos"
721
+ };
722
+
723
+ // src/config/testnet/tokens.ts
724
+ var testnetTokens = {
725
+ Sepolia: {
726
+ symbol: "USDC",
727
+ icon: "USDC",
728
+ decimals: 6,
729
+ tokenId: {
730
+ chain: "Sepolia",
731
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
732
+ }
733
+ },
734
+ Solana: {
735
+ symbol: "USDC",
736
+ tokenId: {
737
+ chain: "Solana",
738
+ address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
739
+ },
740
+ icon: "USDC",
741
+ decimals: 6
742
+ }
743
+ };
744
+ var AptosTestnetUSDCToken = {
745
+ symbol: "USDC",
746
+ decimals: 6,
747
+ tokenId: {
748
+ chain: "Aptos",
749
+ address: "0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832"
750
+ },
751
+ icon: "USDC"
752
+ };
753
+
754
+ // src/config/mainnet/chains.ts
755
+ var mainnetChains = {
756
+ Ethereum: {
757
+ key: "Ethereum",
758
+ id: 2,
759
+ context: "Ethereum" /* ETH */,
760
+ finalityThreshold: 64,
761
+ displayName: "Ethereum",
762
+ explorerUrl: "https://etherscan.io/",
763
+ explorerName: "Etherscan",
764
+ gasToken: "ETH",
765
+ chainId: 1,
766
+ icon: "Ethereum",
767
+ maxBlockSearch: 2e3,
768
+ symbol: "ETH",
769
+ defaultRpc: "https://rpc.ankr.com/eth"
770
+ },
771
+ Solana: {
772
+ key: "Solana",
773
+ id: 1,
774
+ context: "Solana" /* SOLANA */,
775
+ finalityThreshold: 32,
776
+ displayName: "Solana",
777
+ explorerUrl: "https://explorer.solana.com/",
778
+ explorerName: "Solana Explorer",
779
+ gasToken: "SOL",
780
+ chainId: 0,
781
+ icon: "Solana",
782
+ maxBlockSearch: 2e3,
783
+ symbol: "SOL",
784
+ defaultRpc: "https://solana-mainnet.rpc.extrnode.com"
785
+ }
786
+ };
787
+ var AptosMainnetChain = {
788
+ key: "Aptos",
789
+ id: 22,
790
+ context: "Aptos",
791
+ finalityThreshold: 0,
792
+ displayName: "Aptos",
793
+ explorerUrl: "https://explorer.aptoslabs.com/",
794
+ explorerName: "Aptos Explorer",
795
+ gasToken: "APT",
796
+ chainId: 0,
797
+ icon: "Aptos",
798
+ maxBlockSearch: 0,
799
+ symbol: "APT"
800
+ };
801
+
802
+ // src/config/mainnet/tokens.ts
803
+ var mainnetTokens = {
804
+ Ethereum: {
805
+ symbol: "USDC",
806
+ tokenId: {
807
+ chain: "Ethereum",
808
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
809
+ },
810
+ icon: "USDC",
811
+ decimals: 6
812
+ },
813
+ Solana: {
814
+ symbol: "USDC",
815
+ tokenId: {
816
+ chain: "Solana",
817
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
818
+ },
819
+ icon: "USDC",
820
+ decimals: 6
821
+ }
822
+ };
823
+ var AptosMainnetUSDCToken = {
824
+ symbol: "USDC",
825
+ tokenId: {
826
+ chain: "Aptos",
827
+ address: "0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b"
828
+ },
829
+ icon: "USDC",
830
+ decimals: 6
831
+ };
832
+
833
+ // src/utils/getUsdcBalance.ts
834
+ import { Aptos as Aptos2, AptosConfig as AptosConfig2, Network as Network2 } from "@aptos-labs/ts-sdk";
835
+ import { Connection as Connection2, PublicKey } from "@solana/web3.js";
836
+ import { ethers as ethers2, JsonRpcProvider } from "ethers";
837
+ var getSolanaWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
838
+ var _a;
839
+ const address = new PublicKey(walletAddress);
840
+ const tokenAddress = aptosNetwork === Network2.MAINNET ? mainnetTokens["Solana"].tokenId.address : testnetTokens["Solana"].tokenId.address;
841
+ const connection = new Connection2(rpc);
842
+ const splToken = await connection.getTokenAccountsByOwner(address, {
843
+ mint: new PublicKey(tokenAddress)
844
+ });
845
+ const checkAddress = splToken.value.length > 0 ? splToken.value[0].pubkey : address;
846
+ const balance = await connection.getTokenAccountBalance(checkAddress);
847
+ console.log("balance", balance);
848
+ return (_a = balance.value.uiAmountString) != null ? _a : (Number(balance.value.amount) / 10 ** balance.value.decimals).toString();
849
+ };
850
+ var getEthereumWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
851
+ const token = aptosNetwork === Network2.MAINNET ? mainnetTokens["Ethereum"] : testnetTokens["Sepolia"];
852
+ const tokenAddress = token.tokenId.address;
853
+ const connection = new JsonRpcProvider(rpc);
854
+ const abi = ["function balanceOf(address owner) view returns (uint256)"];
855
+ const contract = new ethers2.Contract(tokenAddress, abi, connection);
856
+ const balance = await contract.balanceOf(walletAddress);
857
+ return ethers2.formatUnits(balance, token.decimals).toString();
858
+ };
859
+ var getAptosWalletUSDCBalance = async (walletAddress, aptosNetwork) => {
860
+ const token = aptosNetwork === Network2.MAINNET ? AptosMainnetUSDCToken : AptosTestnetUSDCToken;
861
+ const tokenAddress = token.tokenId.address;
862
+ const aptosConfig = new AptosConfig2({ network: aptosNetwork });
863
+ const connection = new Aptos2(aptosConfig);
864
+ const response = await connection.getCurrentFungibleAssetBalances({
865
+ options: {
866
+ where: {
867
+ owner_address: { _eq: walletAddress },
868
+ asset_type: { _eq: tokenAddress }
869
+ }
870
+ }
871
+ });
872
+ const balance = (Number(response[0].amount) / 10 ** token.decimals).toString();
873
+ return balance;
874
+ };
875
+
876
+ // src/CrossChainCore.ts
877
+ import { NetworkToChainId, NetworkToNodeAPI } from "@aptos-labs/ts-sdk";
878
+ var CrossChainCore = class {
879
+ constructor(args) {
880
+ this._dappConfig = {
881
+ aptosNetwork: Network3.TESTNET
882
+ };
883
+ this.CHAINS = testnetChains;
884
+ this.TOKENS = testnetTokens;
885
+ this.APTOS_TOKEN = AptosTestnetUSDCToken;
886
+ var _a;
887
+ this._dappConfig = args.dappConfig;
888
+ if (((_a = args.dappConfig) == null ? void 0 : _a.aptosNetwork) === Network3.MAINNET) {
889
+ this.CHAINS = mainnetChains;
890
+ this.TOKENS = mainnetTokens;
891
+ this.APTOS_TOKEN = AptosMainnetUSDCToken;
892
+ } else {
893
+ this.CHAINS = testnetChains;
894
+ this.TOKENS = testnetTokens;
895
+ this.APTOS_TOKEN = AptosTestnetUSDCToken;
896
+ }
897
+ }
898
+ getProvider(providerType) {
899
+ switch (providerType) {
900
+ case "Wormhole":
901
+ return new WormholeProvider(this);
902
+ default:
903
+ throw new Error(`Unknown provider: ${providerType}`);
904
+ }
905
+ }
906
+ async getWalletUSDCBalance(walletAddress, sourceChain) {
907
+ var _a, _b, _c;
908
+ if (sourceChain === "Aptos") {
909
+ return await getAptosWalletUSDCBalance(
910
+ walletAddress,
911
+ this._dappConfig.aptosNetwork
912
+ );
913
+ }
914
+ if (!this.CHAINS[sourceChain]) {
915
+ throw new Error(`Unsupported chain: ${sourceChain}`);
916
+ }
917
+ switch (sourceChain) {
918
+ case "Solana":
919
+ return await getSolanaWalletUSDCBalance(
920
+ walletAddress,
921
+ this._dappConfig.aptosNetwork,
922
+ (_c = (_b = (_a = this._dappConfig) == null ? void 0 : _a.solanaConfig) == null ? void 0 : _b.rpc) != null ? _c : this.CHAINS[sourceChain].defaultRpc
923
+ );
924
+ case "Ethereum":
925
+ case "Sepolia":
926
+ return await getEthereumWalletUSDCBalance(
927
+ walletAddress,
928
+ this._dappConfig.aptosNetwork,
929
+ this.CHAINS[sourceChain].defaultRpc
930
+ );
931
+ default:
932
+ throw new Error(`Unsupported chain: ${sourceChain}`);
933
+ }
934
+ }
935
+ };
936
+
937
+ // src/index.ts
938
+ import { Network as Network4 } from "@aptos-labs/ts-sdk";
939
+ export {
940
+ AptosLocalSigner,
941
+ AptosMainnetChain,
942
+ AptosMainnetUSDCToken,
943
+ AptosTestnetChain,
944
+ AptosTestnetUSDCToken,
945
+ Context,
946
+ CrossChainCore,
947
+ Network4 as Network,
948
+ NetworkToChainId,
949
+ NetworkToNodeAPI,
950
+ WormholeProvider,
951
+ mainnetChains,
952
+ mainnetTokens,
953
+ signAndSendTransaction,
954
+ testnetChains,
955
+ testnetTokens
956
+ };
957
+ //# sourceMappingURL=index.mjs.map