@aptos-labs/cross-chain-core 5.8.2 → 6.0.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.
Files changed (52) hide show
  1. package/README.md +26 -0
  2. package/dist/CrossChainCore.d.ts +95 -0
  3. package/dist/CrossChainCore.d.ts.map +1 -1
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +908 -404
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +914 -409
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/providers/wormhole/index.d.ts +2 -0
  11. package/dist/providers/wormhole/index.d.ts.map +1 -1
  12. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +9 -7
  13. package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -1
  14. package/dist/providers/wormhole/signers/AptosSigner.d.ts +2 -1
  15. package/dist/providers/wormhole/signers/AptosSigner.d.ts.map +1 -1
  16. package/dist/providers/wormhole/signers/EthereumSigner.d.ts +1 -1
  17. package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -1
  18. package/dist/providers/wormhole/signers/Signer.d.ts +11 -3
  19. package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -1
  20. package/dist/providers/wormhole/signers/SolanaLocalSigner.d.ts +69 -0
  21. package/dist/providers/wormhole/signers/SolanaLocalSigner.d.ts.map +1 -0
  22. package/dist/providers/wormhole/signers/SolanaSigner.d.ts +12 -20
  23. package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -1
  24. package/dist/providers/wormhole/signers/solanaUtils.d.ts +68 -0
  25. package/dist/providers/wormhole/signers/solanaUtils.d.ts.map +1 -0
  26. package/dist/providers/wormhole/types.d.ts +120 -0
  27. package/dist/providers/wormhole/types.d.ts.map +1 -1
  28. package/dist/providers/wormhole/utils.d.ts +26 -0
  29. package/dist/providers/wormhole/utils.d.ts.map +1 -0
  30. package/dist/providers/wormhole/wormhole.d.ts +62 -6
  31. package/dist/providers/wormhole/wormhole.d.ts.map +1 -1
  32. package/dist/utils/receiptSerialization.d.ts +38 -0
  33. package/dist/utils/receiptSerialization.d.ts.map +1 -0
  34. package/dist/version.d.ts +1 -1
  35. package/package.json +3 -3
  36. package/src/CrossChainCore.ts +110 -3
  37. package/src/config/mainnet/chains.ts +2 -2
  38. package/src/config/testnet/chains.ts +2 -2
  39. package/src/index.ts +1 -0
  40. package/src/providers/wormhole/index.ts +2 -0
  41. package/src/providers/wormhole/signers/AptosLocalSigner.ts +31 -18
  42. package/src/providers/wormhole/signers/AptosSigner.ts +11 -2
  43. package/src/providers/wormhole/signers/EthereumSigner.ts +59 -8
  44. package/src/providers/wormhole/signers/Signer.ts +23 -6
  45. package/src/providers/wormhole/signers/SolanaLocalSigner.ts +250 -0
  46. package/src/providers/wormhole/signers/SolanaSigner.ts +49 -338
  47. package/src/providers/wormhole/signers/solanaUtils.ts +446 -0
  48. package/src/providers/wormhole/types.ts +167 -0
  49. package/src/providers/wormhole/utils.ts +72 -0
  50. package/src/providers/wormhole/wormhole.ts +309 -137
  51. package/src/utils/receiptSerialization.ts +141 -0
  52. package/src/version.ts +1 -1
package/dist/index.mjs CHANGED
@@ -3,9 +3,8 @@ import { Network as Network3 } from "@aptos-labs/ts-sdk";
3
3
 
4
4
  // src/providers/wormhole/wormhole.ts
5
5
  import {
6
- chainToPlatform,
7
- routes,
8
- Wormhole,
6
+ routes as routes3,
7
+ Wormhole as Wormhole2,
9
8
  wormhole,
10
9
  TransferState
11
10
  } from "@wormhole-foundation/sdk";
@@ -34,19 +33,134 @@ var logger = {
34
33
  }
35
34
  };
36
35
 
36
+ // src/utils/receiptSerialization.ts
37
+ import {
38
+ UniversalAddress
39
+ } from "@wormhole-foundation/sdk";
40
+ function uint8ArrayToBase64(bytes) {
41
+ let binary = "";
42
+ for (let i = 0; i < bytes.length; i++) {
43
+ binary += String.fromCharCode(bytes[i]);
44
+ }
45
+ return btoa(binary);
46
+ }
47
+ function base64ToUint8Array(base64) {
48
+ const binary = atob(base64);
49
+ const bytes = new Uint8Array(binary.length);
50
+ for (let i = 0; i < binary.length; i++) {
51
+ bytes[i] = binary.charCodeAt(i);
52
+ }
53
+ return bytes;
54
+ }
55
+ function serializeReceipt(receipt) {
56
+ return JSON.parse(
57
+ JSON.stringify(receipt, (_key, value) => {
58
+ if (typeof value === "bigint") {
59
+ return { __type: "bigint", value: value.toString() };
60
+ }
61
+ if (value instanceof UniversalAddress) {
62
+ return {
63
+ __type: "UniversalAddress",
64
+ value: uint8ArrayToBase64(value.toUint8Array())
65
+ };
66
+ }
67
+ if (value instanceof Uint8Array) {
68
+ return {
69
+ __type: "Uint8Array",
70
+ value: uint8ArrayToBase64(value)
71
+ };
72
+ }
73
+ return value;
74
+ })
75
+ );
76
+ }
77
+ function deserializeReceipt(obj) {
78
+ function revive(value, key) {
79
+ if (value && typeof value === "object") {
80
+ const objValue = value;
81
+ if ("__type" in objValue) {
82
+ if (objValue.__type === "bigint") {
83
+ return BigInt(objValue.value);
84
+ }
85
+ if (objValue.__type === "UniversalAddress") {
86
+ return new UniversalAddress(
87
+ base64ToUint8Array(objValue.value)
88
+ );
89
+ }
90
+ if (objValue.__type === "Uint8Array") {
91
+ return base64ToUint8Array(objValue.value);
92
+ }
93
+ }
94
+ const addressFields = [
95
+ "sender",
96
+ "recipient",
97
+ "destinationCaller",
98
+ "burnToken",
99
+ "mintRecipient",
100
+ "messageSender"
101
+ ];
102
+ if (key && addressFields.includes(key) && "address" in objValue) {
103
+ const addressBytes = revive(objValue.address);
104
+ if (addressBytes instanceof Uint8Array) {
105
+ return new UniversalAddress(addressBytes);
106
+ }
107
+ }
108
+ if (Array.isArray(value)) {
109
+ return value.map((v, i) => revive(v, String(i)));
110
+ }
111
+ const result = {};
112
+ for (const k in objValue) {
113
+ result[k] = revive(objValue[k], k);
114
+ }
115
+ return result;
116
+ }
117
+ return value;
118
+ }
119
+ return revive(obj);
120
+ }
121
+
37
122
  // src/providers/wormhole/signers/AptosLocalSigner.ts
38
123
  import {
39
124
  Aptos,
40
125
  AptosConfig
41
126
  } from "@aptos-labs/ts-sdk";
127
+
128
+ // src/providers/wormhole/types.ts
129
+ function validateExpireTimestamp(value) {
130
+ if (!Number.isInteger(value) || value < 0) {
131
+ throw new Error(
132
+ `getExpireTimestamp returned an invalid value (${value}). Expected a non-negative integer (epoch seconds).`
133
+ );
134
+ }
135
+ }
136
+ var TransferError = class extends Error {
137
+ constructor(message, originChainTxnId, cause) {
138
+ super(message);
139
+ this.name = "TransferError";
140
+ this.originChainTxnId = originChainTxnId;
141
+ this.cause = cause;
142
+ }
143
+ };
144
+ var WithdrawError = class extends Error {
145
+ constructor(message, originChainTxnId, phase, cause) {
146
+ super(message);
147
+ this.name = "WithdrawError";
148
+ this.originChainTxnId = originChainTxnId;
149
+ this.phase = phase;
150
+ this.cause = cause;
151
+ }
152
+ };
153
+
154
+ // src/providers/wormhole/signers/AptosLocalSigner.ts
42
155
  var AptosLocalSigner = class {
43
- constructor(chain, options, wallet, feePayerAccount, dappNetwork) {
156
+ constructor(chain, options, wallet, feePayerAccount, crossChainCore, onTransactionSigned) {
157
+ this._claimedTransactionHashes = [];
44
158
  this._chain = chain;
45
159
  this._options = options;
46
160
  this._wallet = wallet;
47
161
  this._sponsorAccount = feePayerAccount;
48
- this._claimedTransactionHashes = "";
49
- this._dappNetwork = dappNetwork;
162
+ this._crossChainCore = crossChainCore;
163
+ this._onTransactionSigned = onTransactionSigned;
50
164
  }
51
165
  chain() {
52
166
  return this._chain;
@@ -55,24 +169,27 @@ var AptosLocalSigner = class {
55
169
  return this._wallet.accountAddress.toString();
56
170
  }
57
171
  claimedTransactionHashes() {
58
- return this._claimedTransactionHashes;
172
+ return this._claimedTransactionHashes.join(",");
59
173
  }
60
174
  async signAndSend(txs) {
61
175
  const txHashes = [];
176
+ this._claimedTransactionHashes = [];
62
177
  for (const tx of txs) {
178
+ this._onTransactionSigned?.(tx.description, null);
63
179
  const txId = await signAndSendTransaction(
64
180
  tx,
65
181
  this._wallet,
66
182
  this._sponsorAccount,
67
- this._dappNetwork
183
+ this._crossChainCore
68
184
  );
185
+ this._onTransactionSigned?.(tx.description, txId);
69
186
  txHashes.push(txId);
70
- this._claimedTransactionHashes = txId;
187
+ this._claimedTransactionHashes.push(txId);
71
188
  }
72
189
  return txHashes;
73
190
  }
74
191
  };
75
- async function signAndSendTransaction(request, wallet, sponsorAccount, dappNetwork) {
192
+ async function signAndSendTransaction(request, wallet, sponsorAccount, crossChainCore) {
76
193
  if (!wallet) {
77
194
  throw new Error("Wallet is undefined");
78
195
  }
@@ -86,14 +203,20 @@ async function signAndSendTransaction(request, wallet, sponsorAccount, dappNetwo
86
203
  return a;
87
204
  }
88
205
  });
206
+ const dappNetwork = crossChainCore._dappConfig.aptosNetwork;
89
207
  const aptosConfig = new AptosConfig({
90
208
  network: dappNetwork
91
209
  });
92
210
  const aptos2 = new Aptos(aptosConfig);
211
+ const expireTimestamp = crossChainCore._dappConfig.getExpireTimestamp?.();
212
+ if (typeof expireTimestamp !== "undefined") {
213
+ validateExpireTimestamp(expireTimestamp);
214
+ }
93
215
  const txnToSign = await aptos2.transaction.build.simple({
94
216
  data: payload,
95
217
  sender: wallet.accountAddress.toString(),
96
- withFeePayer: sponsorAccount ? true : false
218
+ withFeePayer: sponsorAccount ? true : false,
219
+ ...typeof expireTimestamp !== "undefined" ? { options: { expireTimestamp } } : {}
97
220
  });
98
221
  const senderAuthenticator = await aptos2.transaction.sign({
99
222
  signer: wallet,
@@ -117,126 +240,241 @@ async function signAndSendTransaction(request, wallet, sponsorAccount, dappNetwo
117
240
  return tx.hash;
118
241
  }
119
242
 
243
+ // src/providers/wormhole/signers/AptosSigner.ts
244
+ import {
245
+ AccountAddress,
246
+ Aptos as Aptos2,
247
+ AptosConfig as AptosConfig2,
248
+ Deserializer
249
+ } from "@aptos-labs/ts-sdk";
250
+ import { UserResponseStatus } from "@aptos-labs/wallet-standard";
251
+ import { GasStationClient, GasStationTransactionSubmitter } from "@aptos-labs/gas-station-client";
252
+ async function signAndSendTransaction2(request, wallet, sponsorAccount, dappNetwork, crossChainCore) {
253
+ if (!wallet) {
254
+ throw new Error("wallet.sendTransaction is undefined");
255
+ }
256
+ const payload = request.transaction;
257
+ payload.functionArguments = payload.functionArguments.map((a) => {
258
+ if (a instanceof Uint8Array) {
259
+ return Array.from(a);
260
+ } else if (typeof a === "bigint") {
261
+ return a.toString();
262
+ } else {
263
+ return a;
264
+ }
265
+ });
266
+ let aptosConfig;
267
+ const useGasStation = sponsorAccount && !isAccount(sponsorAccount);
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
293
+ };
294
+ const expireTimestamp = crossChainCore?._dappConfig?.getExpireTimestamp?.();
295
+ if (typeof expireTimestamp !== "undefined") {
296
+ validateExpireTimestamp(expireTimestamp);
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
+
120
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
121
346
  import {
122
347
  ComputeBudgetProgram,
123
348
  LAMPORTS_PER_SOL
124
349
  } from "@solana/web3.js";
125
- import { Transaction } from "@solana/web3.js";
126
350
  import {
127
351
  determinePriorityFee,
128
352
  determinePriorityFeeTritonOne
129
353
  } 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
- if (!wallet || !(wallet instanceof SolanaDerivedWallet)) {
134
- throw new Error("Invalid wallet type or missing Solana wallet").message;
135
- }
136
- const commitment = options?.commitment ?? "finalized";
137
- const connection = new Connection(
138
- crossChainCore?._dappConfig?.solanaConfig?.rpc ?? crossChainCore?.CHAINS["Solana"]?.defaultRpc ?? "https://api.devnet.solana.com"
139
- // Last resort fallback
140
- );
141
- const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(commitment);
142
- const unsignedTx = await setPriorityFeeInstructions(
143
- connection,
144
- blockhash,
145
- lastValidBlockHeight,
146
- request,
147
- crossChainCore
148
- );
149
- let confirmTransactionPromise = null;
150
- let confirmedTx = null;
151
- let txSendAttempts = 1;
152
- let signature = "";
153
- if (!wallet.solanaWallet.signTransaction) {
154
- throw new Error("Wallet does not support signing transactions").message;
155
- }
156
- const tx = await wallet.solanaWallet.signTransaction(unsignedTx);
157
- if (!tx) throw new Error("Failed to sign transaction").message;
158
- if (request.transaction.signers && tx instanceof Transaction) {
159
- tx.partialSign(...request.transaction.signers);
160
- }
161
- const serializedTx = tx.serialize();
354
+ async function sendAndConfirmTransaction(serializedTx, blockhash, lastValidBlockHeight, config) {
355
+ const { connection, commitment, retryIntervalMs = 5e3, verbose = false } = config;
162
356
  const sendOptions = {
163
357
  skipPreflight: true,
164
358
  maxRetries: 0,
165
- preFlightCommitment: commitment
166
- // See PR and linked issue for why setting this matters: https://github.com/anza-xyz/agave/pull/483
359
+ preflightCommitment: commitment
167
360
  };
168
- signature = await connection.sendRawTransaction(serializedTx, sendOptions);
169
- confirmTransactionPromise = connection.confirmTransaction(
170
- {
171
- signature,
172
- blockhash,
173
- lastValidBlockHeight
174
- },
361
+ const signature = await connection.sendRawTransaction(serializedTx, sendOptions);
362
+ const confirmTransactionPromise = connection.confirmTransaction(
363
+ { signature, blockhash, lastValidBlockHeight },
175
364
  commitment
176
365
  );
177
- const txRetryInterval = 5e3;
178
- while (!confirmedTx) {
179
- confirmedTx = await Promise.race([
180
- confirmTransactionPromise,
181
- new Promise(
182
- (resolve) => setTimeout(() => {
183
- resolve(null);
184
- }, txRetryInterval)
185
- )
186
- ]);
187
- if (confirmedTx) {
188
- break;
189
- }
190
- console.log(
191
- `Tx not confirmed after ${txRetryInterval * txSendAttempts++}ms, resending`
192
- );
193
- try {
194
- await connection.sendRawTransaction(serializedTx, sendOptions);
195
- } catch (e) {
196
- console.error("Failed to resend transaction:", e);
197
- }
198
- }
199
- if (confirmedTx.value.err) {
200
- let errorMessage = `Transaction failed: ${confirmedTx.value.err}`;
201
- if (typeof confirmedTx.value.err === "object") {
366
+ let confirmedTx = null;
367
+ let txSendAttempts = 1;
368
+ try {
369
+ while (!confirmedTx) {
370
+ confirmedTx = await Promise.race([
371
+ confirmTransactionPromise,
372
+ new Promise(
373
+ (resolve) => setTimeout(() => resolve(null), retryIntervalMs)
374
+ )
375
+ ]);
376
+ if (confirmedTx) break;
377
+ if (verbose) {
378
+ console.log(
379
+ `Tx not confirmed after ${retryIntervalMs * txSendAttempts++}ms, resending`
380
+ );
381
+ }
202
382
  try {
203
- errorMessage = `Transaction failed: ${JSON.stringify(
204
- confirmedTx.value.err,
205
- (_key, value) => typeof value === "bigint" ? value.toString() : value
206
- // Handle bigint props
207
- )}`;
383
+ await connection.sendRawTransaction(serializedTx, sendOptions);
208
384
  } catch (e) {
209
- errorMessage = `Transaction failed: Unknown error`;
385
+ if (verbose) {
386
+ console.error("Failed to resend transaction:", e);
387
+ }
210
388
  }
211
389
  }
212
- throw new Error(`Transaction failed: ${errorMessage}`).message;
390
+ } catch (e) {
391
+ const message = e instanceof Error ? e.message.toLowerCase() : "";
392
+ if (message.includes("block height exceeded") || message.includes("blockheightexceeded")) {
393
+ if (verbose) {
394
+ console.warn(
395
+ "Block height exceeded but tx was already sent, returning signature:",
396
+ signature
397
+ );
398
+ }
399
+ return signature;
400
+ }
401
+ throw e;
402
+ }
403
+ if (confirmedTx.value.err) {
404
+ const errorMessage = formatTransactionError(confirmedTx.value.err);
405
+ throw new Error(errorMessage);
213
406
  }
214
407
  return signature;
215
408
  }
216
- async function setPriorityFeeInstructions(connection, blockhash, lastValidBlockHeight, request, crossChainCore) {
217
- const unsignedTx = request.transaction.transaction;
409
+ function formatTransactionError(err) {
410
+ if (typeof err === "object" && err !== null) {
411
+ try {
412
+ return `Transaction failed: ${JSON.stringify(
413
+ err,
414
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
415
+ )}`;
416
+ } catch {
417
+ return "Transaction failed: Unknown error";
418
+ }
419
+ }
420
+ return `Transaction failed: ${err}`;
421
+ }
422
+ async function addPriorityFeeInstructions(connection, transaction, priorityFeeConfig, verbose = false) {
218
423
  const computeBudgetIxFilter = (ix) => ix.programId.toString() !== "ComputeBudget111111111111111111111111111111";
219
- unsignedTx.recentBlockhash = blockhash;
220
- unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
221
- unsignedTx.instructions = unsignedTx.instructions.filter(
222
- computeBudgetIxFilter
424
+ transaction.instructions = transaction.instructions.filter(computeBudgetIxFilter);
425
+ const instructions = await createPriorityFeeInstructions(
426
+ connection,
427
+ transaction,
428
+ priorityFeeConfig,
429
+ verbose
223
430
  );
224
- unsignedTx.add(
225
- ...await createPriorityFeeInstructions(
226
- connection,
227
- unsignedTx,
228
- crossChainCore
229
- )
431
+ transaction.add(...instructions);
432
+ return transaction;
433
+ }
434
+ async function createPriorityFeeInstructions(connection, transaction, priorityFeeConfig, verbose = false) {
435
+ const unitsUsed = await simulateAndGetComputeUnits(connection, transaction);
436
+ const unitBudget = Math.floor(unitsUsed * 1.2);
437
+ const instructions = [];
438
+ instructions.push(
439
+ ComputeBudgetProgram.setComputeUnitLimit({
440
+ units: unitBudget
441
+ })
230
442
  );
231
- return unsignedTx;
443
+ const {
444
+ percentile = 0.9,
445
+ percentileMultiple = 1,
446
+ min = 1e5,
447
+ max = 1e8
448
+ } = priorityFeeConfig ?? {};
449
+ const rpcProvider = determineRpcProvider(connection.rpcEndpoint);
450
+ const { fee, methodUsed } = await calculatePriorityFee(
451
+ connection,
452
+ transaction,
453
+ rpcProvider,
454
+ { percentile, percentileMultiple, min, max }
455
+ );
456
+ if (verbose) {
457
+ const maxFeeInSol = fee / 1e6 / LAMPORTS_PER_SOL * unitBudget;
458
+ console.table({
459
+ "RPC Provider": rpcProvider,
460
+ "Method used": methodUsed,
461
+ "Percentile used": percentile,
462
+ "Multiple used": percentileMultiple,
463
+ "Compute budget": unitBudget,
464
+ "Priority fee": fee,
465
+ "Max fee in SOL": maxFeeInSol
466
+ });
467
+ }
468
+ instructions.push(
469
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: fee })
470
+ );
471
+ return instructions;
232
472
  }
233
- async function createPriorityFeeInstructions(connection, transaction, crossChainCore) {
473
+ async function simulateAndGetComputeUnits(connection, transaction) {
234
474
  let unitsUsed = 2e5;
235
475
  let simulationAttempts = 0;
236
476
  simulationLoop: while (true) {
237
- const response = await connection.simulateTransaction(
238
- transaction
239
- );
477
+ const response = await connection.simulateTransaction(transaction);
240
478
  if (response.value.err) {
241
479
  if (checkKnownSimulationError(response.value)) {
242
480
  if (simulationAttempts < 5) {
@@ -253,7 +491,7 @@ async function createPriorityFeeInstructions(connection, transaction, crossChain
253
491
  `Simulation failed: ${JSON.stringify(response.value.err)}
254
492
  Logs:
255
493
  ${(response.value.logs || []).join("\n ")}`
256
- ).message;
494
+ );
257
495
  } else {
258
496
  if (response.value.unitsConsumed) {
259
497
  unitsUsed = response.value.unitsConsumed;
@@ -261,41 +499,13 @@ ${(response.value.logs || []).join("\n ")}`
261
499
  break;
262
500
  }
263
501
  }
264
- const unitBudget = Math.floor(unitsUsed * 1.2);
265
- const instructions = [];
266
- instructions.push(
267
- ComputeBudgetProgram.setComputeUnitLimit({
268
- // Set compute budget to 120% of the units used in the simulated transaction
269
- units: unitBudget
270
- })
271
- );
272
- const {
273
- percentile = 0.9,
274
- percentileMultiple = 1,
275
- min = 1e5,
276
- max = 1e8
277
- } = crossChainCore?._dappConfig?.solanaConfig?.priorityFeeConfig ?? {};
278
- const calculateFee = async (rpcProvider2) => {
279
- if (rpcProvider2 === "triton") {
280
- try {
281
- const fee2 = await determinePriorityFeeTritonOne(
282
- connection,
283
- transaction,
284
- percentile,
285
- percentileMultiple,
286
- min,
287
- max
288
- );
289
- return {
290
- fee: fee2,
291
- methodUsed: "triton"
292
- };
293
- } catch (e) {
294
- console.warn(`Failed to determine priority fee using Triton RPC:`, e);
295
- }
296
- }
502
+ return unitsUsed;
503
+ }
504
+ async function calculatePriorityFee(connection, transaction, rpcProvider, config) {
505
+ const { percentile, percentileMultiple, min, max } = config;
506
+ if (rpcProvider === "triton") {
297
507
  try {
298
- const fee2 = await determinePriorityFee(
508
+ const fee = await determinePriorityFeeTritonOne(
299
509
  connection,
300
510
  transaction,
301
511
  percentile,
@@ -303,37 +513,25 @@ ${(response.value.logs || []).join("\n ")}`
303
513
  min,
304
514
  max
305
515
  );
306
- return {
307
- fee: fee2,
308
- methodUsed: "default"
309
- };
516
+ return { fee, methodUsed: "triton" };
310
517
  } catch (e) {
311
518
  console.warn(`Failed to determine priority fee using Triton RPC:`, e);
312
- return {
313
- fee: min,
314
- methodUsed: "minimum"
315
- };
316
519
  }
317
- };
318
- const rpcProvider = determineRpcProvider(connection.rpcEndpoint);
319
- const { fee, methodUsed } = await calculateFee(rpcProvider);
320
- const maxFeeInSol = fee / // convert microlamports to lamports
321
- 1e6 / // convert lamports to SOL
322
- LAMPORTS_PER_SOL * // multiply by maximum compute units used
323
- unitBudget;
324
- console.table({
325
- "RPC Provider": rpcProvider,
326
- "Method used": methodUsed,
327
- "Percentile used": percentile,
328
- "Multiple used": percentileMultiple,
329
- "Compute budget": unitBudget,
330
- "Priority fee": fee,
331
- "Max fee in SOL": maxFeeInSol
332
- });
333
- instructions.push(
334
- ComputeBudgetProgram.setComputeUnitPrice({ microLamports: fee })
335
- );
336
- return instructions;
520
+ }
521
+ try {
522
+ const fee = await determinePriorityFee(
523
+ connection,
524
+ transaction,
525
+ percentile,
526
+ percentileMultiple,
527
+ min,
528
+ max
529
+ );
530
+ return { fee, methodUsed: "default" };
531
+ } catch (e) {
532
+ console.warn(`Failed to determine priority fee:`, e);
533
+ return { fee: min, methodUsed: "minimum" };
534
+ }
337
535
  }
338
536
  function checkKnownSimulationError(response) {
339
537
  const errors = {};
@@ -350,159 +548,148 @@ function checkKnownSimulationError(response) {
350
548
  }
351
549
  }
352
550
  }
353
- if (isEmptyObject(errors)) {
551
+ if (Object.keys(errors).length === 0) {
354
552
  return false;
355
553
  }
356
554
  console.table(errors);
357
555
  return true;
358
556
  }
359
- async function sleep(timeout) {
360
- return new Promise((resolve) => setTimeout(resolve, timeout));
557
+ function isHostOrSubdomainOf(hostname, base) {
558
+ return hostname === base || hostname.endsWith(`.${base}`);
361
559
  }
362
- var isEmptyObject = (value) => {
363
- if (value === null || value === void 0) {
364
- return true;
365
- }
366
- for (const key in value) {
367
- if (value.hasOwnProperty.call(value, key)) {
368
- return false;
369
- }
370
- }
371
- return true;
372
- };
373
560
  function determineRpcProvider(endpoint) {
374
561
  try {
375
562
  const url = new URL(endpoint);
376
563
  const hostname = url.hostname;
377
- if (hostname === "rpcpool.com") {
564
+ if (isHostOrSubdomainOf(hostname, "rpcpool.com") || isHostOrSubdomainOf(hostname, "triton.one")) {
378
565
  return "triton";
379
- } else if (hostname === "helius-rpc.com") {
566
+ } else if (isHostOrSubdomainOf(hostname, "helius-rpc.com") || isHostOrSubdomainOf(hostname, "helius.xyz")) {
380
567
  return "helius";
381
- } else if (hostname === "rpc.ankr.com") {
568
+ } else if (isHostOrSubdomainOf(hostname, "ankr.com")) {
382
569
  return "ankr";
383
570
  } else {
384
571
  return "unknown";
385
572
  }
386
- } catch (e) {
387
- return "unknown";
388
- }
573
+ } catch {
574
+ return "unknown";
575
+ }
576
+ }
577
+ async function sleep(timeout) {
578
+ return new Promise((resolve) => setTimeout(resolve, timeout));
579
+ }
580
+
581
+ // src/providers/wormhole/signers/SolanaSigner.ts
582
+ async function signAndSendTransaction3(request, wallet, options, crossChainCore) {
583
+ if (!wallet || !(wallet instanceof SolanaDerivedWallet)) {
584
+ throw new Error("Invalid wallet type or missing Solana wallet");
585
+ }
586
+ const commitment = options?.commitment ?? crossChainCore?._dappConfig?.solanaConfig?.commitment ?? "finalized";
587
+ const connection = new Connection2(
588
+ crossChainCore?._dappConfig?.solanaConfig?.rpc ?? crossChainCore?.CHAINS["Solana"]?.defaultRpc ?? "https://api.devnet.solana.com"
589
+ // Last resort fallback
590
+ );
591
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(commitment);
592
+ const unsignedTx = await setPriorityFeeInstructions(
593
+ connection,
594
+ blockhash,
595
+ lastValidBlockHeight,
596
+ request,
597
+ crossChainCore?._dappConfig?.solanaConfig?.priorityFeeConfig
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;
389
632
  }
390
633
 
391
634
  // src/providers/wormhole/signers/EthereumSigner.ts
392
635
  import { ethers, getBigInt } from "ethers";
393
- async function signAndSendTransaction3(request, wallet, chainName, options) {
636
+ async function signAndSendTransaction4(request, wallet, chainName) {
394
637
  if (!wallet) {
395
- throw new Error("wallet.sendTransaction is undefined").message;
638
+ throw new Error("wallet.sendTransaction is undefined");
396
639
  }
397
640
  const chainId = await wallet.eip1193Provider.request({
398
641
  method: "eth_chainId"
399
642
  });
400
643
  const actualChainId = parseInt(chainId, 16);
401
- if (!actualChainId)
402
- throw new Error("No signer found for chain" + chainName).message;
644
+ if (!actualChainId) throw new Error("No signer found for chain" + chainName);
403
645
  const expectedChainId = request.transaction.chainId ? getBigInt(request.transaction.chainId) : void 0;
404
646
  if (!actualChainId || !expectedChainId || BigInt(actualChainId) !== expectedChainId) {
405
647
  throw new Error(
406
648
  `Signer is not connected to the right chain. Expected ${expectedChainId}, got ${actualChainId}`
407
- ).message;
649
+ );
408
650
  }
409
651
  const provider = new ethers.BrowserProvider(
410
652
  wallet.eip1193Provider
411
653
  );
412
654
  const signer = await provider.getSigner();
413
- const response = await signer.sendTransaction(request.transaction);
414
- const receipt = await response.wait();
415
- return receipt?.hash || "";
416
- }
417
-
418
- // src/providers/wormhole/signers/AptosSigner.ts
419
- import {
420
- AccountAddress,
421
- Aptos as Aptos2,
422
- AptosConfig as AptosConfig2,
423
- Deserializer
424
- } from "@aptos-labs/ts-sdk";
425
- import { UserResponseStatus } from "@aptos-labs/wallet-standard";
426
- import { GasStationClient, GasStationTransactionSubmitter } from "@aptos-labs/gas-station-client";
427
- async function signAndSendTransaction4(request, wallet, sponsorAccount, dappNetwork) {
428
- if (!wallet) {
429
- throw new Error("wallet.sendTransaction is undefined").message;
430
- }
431
- const payload = request.transaction;
432
- payload.functionArguments = payload.functionArguments.map((a) => {
433
- if (a instanceof Uint8Array) {
434
- return Array.from(a);
435
- } else if (typeof a === "bigint") {
436
- return a.toString();
437
- } else {
438
- return a;
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];
439
664
  }
440
- });
441
- let aptosConfig;
442
- const useGasStation = sponsorAccount && !isAccount(sponsorAccount);
443
- if (useGasStation) {
444
- const gasStationClient = new GasStationClient({
445
- network: dappNetwork,
446
- apiKey: sponsorAccount[dappNetwork]
447
- });
448
- const transactionSubmitter = new GasStationTransactionSubmitter(gasStationClient);
449
- aptosConfig = new AptosConfig2({
450
- network: dappNetwork,
451
- pluginSettings: {
452
- TRANSACTION_SUBMITTER: transactionSubmitter
453
- }
454
- });
455
- } else {
456
- aptosConfig = new AptosConfig2({
457
- network: dappNetwork
458
- });
459
- }
460
- const aptos2 = new Aptos2(aptosConfig);
461
- const functionArguments = extractFunctionArguments(
462
- payload.functionArguments
463
- );
464
- const withdrawFunction = "0x5e2d961f06cd27aa07554a39d55f5ce1e58dff35d803c3529b1cd5c4fa3ab584::withdraw::deposit_for_burn";
465
- const transactionData = {
466
- function: withdrawFunction,
467
- functionArguments
468
- };
469
- const txnToSign = await aptos2.transaction.build.simple({
470
- data: transactionData,
471
- sender: (await wallet.features["aptos:account"]?.account()).address.toString(),
472
- withFeePayer: sponsorAccount ? true : false
473
- });
474
- const response = await wallet.features["aptos:signTransaction"]?.signTransaction(txnToSign);
475
- if (response?.status === UserResponseStatus.REJECTED) {
476
- throw new Error("User has rejected the request");
665
+ throw e;
477
666
  }
478
- const txnToSubmit = {
479
- transaction: txnToSign,
480
- senderAuthenticator: response.args
481
- };
482
- if (sponsorAccount && isAccount(sponsorAccount)) {
483
- const feePayerSignerAuthenticator = aptos2.transaction.signAsFeePayer({
484
- signer: sponsorAccount,
485
- transaction: txnToSign
486
- });
487
- txnToSubmit.feePayerAuthenticator = feePayerSignerAuthenticator;
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;
488
692
  }
489
- const txnSubmitted = await aptos2.transaction.submit.simple(txnToSubmit);
490
- const tx = await aptos2.waitForTransaction({
491
- transactionHash: txnSubmitted.hash
492
- });
493
- return tx.hash;
494
- }
495
- function extractFunctionArguments(functionArguments) {
496
- const deserializer1 = new Deserializer(functionArguments[0].bcsToBytes());
497
- const amount = deserializer1.deserializeU64();
498
- const deserializer2 = new Deserializer(functionArguments[1].bcsToBytes());
499
- const destination_domain = deserializer2.deserializeU32();
500
- const mint_recipient = new AccountAddress(functionArguments[2].bcsToBytes());
501
- const burn_token = new AccountAddress(functionArguments[3].bcsToBytes());
502
- return [amount, destination_domain, mint_recipient, burn_token];
503
- }
504
- function isAccount(obj) {
505
- return "accountAddress" in obj;
506
693
  }
507
694
 
508
695
  // src/providers/wormhole/signers/SuiSigner.ts
@@ -525,14 +712,16 @@ async function signAndSendTransaction5(request, wallet) {
525
712
 
526
713
  // src/providers/wormhole/signers/Signer.ts
527
714
  var Signer = class {
528
- constructor(chain, address, options, wallet, crossChainCore, sponsorAccount) {
715
+ constructor(chain, address, options, wallet, crossChainCore, sponsorAccount, onTransactionSigned, trackAsSourceChain = true) {
716
+ this._claimedTransactionHashes = [];
529
717
  this._chain = chain;
530
718
  this._address = address;
531
719
  this._options = options;
532
720
  this._wallet = wallet;
533
721
  this._crossChainCore = crossChainCore;
534
722
  this._sponsorAccount = sponsorAccount;
535
- this._claimedTransactionHashes = "";
723
+ this._onTransactionSigned = onTransactionSigned;
724
+ this._trackAsSourceChain = trackAsSourceChain;
536
725
  }
537
726
  chain() {
538
727
  return this._chain.key;
@@ -541,11 +730,13 @@ var Signer = class {
541
730
  return this._address;
542
731
  }
543
732
  claimedTransactionHashes() {
544
- return this._claimedTransactionHashes;
733
+ return this._claimedTransactionHashes.join(",");
545
734
  }
546
735
  async signAndSend(txs) {
547
736
  const txHashes = [];
737
+ this._claimedTransactionHashes = [];
548
738
  for (const tx of txs) {
739
+ this._onTransactionSigned?.(tx.description, null);
549
740
  const txId = await signAndSendTransaction6(
550
741
  this._chain,
551
742
  tx,
@@ -554,8 +745,12 @@ var Signer = class {
554
745
  this._crossChainCore,
555
746
  this._sponsorAccount
556
747
  );
748
+ if (this._trackAsSourceChain) {
749
+ this._crossChainCore._lastSourceChainTxId = txId;
750
+ }
751
+ this._onTransactionSigned?.(tx.description, txId);
557
752
  txHashes.push(txId);
558
- this._claimedTransactionHashes = txId;
753
+ this._claimedTransactionHashes.push(txId);
559
754
  }
560
755
  return txHashes;
561
756
  }
@@ -566,7 +761,7 @@ var signAndSendTransaction6 = async (chain, request, wallet, options = {}, cross
566
761
  }
567
762
  const dappNetwork = crossChainCore._dappConfig.aptosNetwork;
568
763
  if (chain.context === "Solana") {
569
- const signature = await signAndSendTransaction2(
764
+ const signature = await signAndSendTransaction3(
570
765
  request,
571
766
  wallet,
572
767
  options,
@@ -574,11 +769,10 @@ var signAndSendTransaction6 = async (chain, request, wallet, options = {}, cross
574
769
  );
575
770
  return signature;
576
771
  } else if (chain.context === "Ethereum") {
577
- const tx = await signAndSendTransaction3(
772
+ const tx = await signAndSendTransaction4(
578
773
  request,
579
774
  wallet,
580
- chain.displayName,
581
- options
775
+ chain.displayName
582
776
  );
583
777
  return tx;
584
778
  } else if (chain.context === "Sui") {
@@ -588,11 +782,12 @@ var signAndSendTransaction6 = async (chain, request, wallet, options = {}, cross
588
782
  );
589
783
  return tx;
590
784
  } else if (chain.context === "Aptos") {
591
- const tx = await signAndSendTransaction4(
785
+ const tx = await signAndSendTransaction2(
592
786
  request,
593
787
  wallet,
594
788
  sponsorAccount,
595
- dappNetwork
789
+ dappNetwork,
790
+ crossChainCore
596
791
  );
597
792
  return tx;
598
793
  } else {
@@ -600,6 +795,38 @@ var signAndSendTransaction6 = async (chain, request, wallet, options = {}, cross
600
795
  }
601
796
  };
602
797
 
798
+ // src/providers/wormhole/utils.ts
799
+ import {
800
+ chainToPlatform,
801
+ routes as routes2,
802
+ Wormhole
803
+ } from "@wormhole-foundation/sdk";
804
+ async function createCCTPRoute(wh, sourceChain, destChain, tokens) {
805
+ const sourceToken = Wormhole.tokenId(
806
+ sourceChain,
807
+ tokens[sourceChain].tokenId.address
808
+ );
809
+ const destToken = Wormhole.tokenId(
810
+ destChain,
811
+ tokens[destChain].tokenId.address
812
+ );
813
+ const destContext = wh.getPlatform(chainToPlatform(destChain)).getChain(destChain);
814
+ const sourceContext = wh.getPlatform(chainToPlatform(sourceChain)).getChain(sourceChain);
815
+ const request = await routes2.RouteTransferRequest.create(
816
+ wh,
817
+ { source: sourceToken, destination: destToken },
818
+ sourceContext,
819
+ destContext
820
+ );
821
+ const resolver = wh.resolver([routes2.CCTPRoute]);
822
+ const foundRoutes = await resolver.findRoutes(request);
823
+ const cctpRoute = foundRoutes[0];
824
+ if (!cctpRoute || !routes2.isManual(cctpRoute)) {
825
+ throw new Error("Expected manual CCTP route");
826
+ }
827
+ return { route: cctpRoute, request };
828
+ }
829
+
603
830
  // src/providers/wormhole/wormhole.ts
604
831
  var WormholeProvider = class {
605
832
  constructor(core) {
@@ -618,12 +845,22 @@ var WormholeProvider = class {
618
845
  }
619
846
  const isMainnet = dappNetwork === Network.MAINNET;
620
847
  const platforms = [aptos, solana, evm, sui];
621
- const solanaRpc = this.crossChainCore._dappConfig?.solanaConfig?.rpc ?? this.crossChainCore.CHAINS["Solana"]?.defaultRpc;
848
+ const dappConfig = this.crossChainCore._dappConfig;
849
+ const chains = this.crossChainCore.CHAINS;
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
+ }
858
+ }
622
859
  const wh = await wormhole(isMainnet ? "Mainnet" : "Testnet", platforms, {
623
860
  chains: {
624
- Solana: {
625
- rpc: solanaRpc
626
- }
861
+ ...solanaRpc ? { Solana: { rpc: solanaRpc } } : {},
862
+ ...suiRpc ? { Sui: { rpc: suiRpc } } : {},
863
+ ...evmChainsConfig
627
864
  }
628
865
  });
629
866
  this._wormholeContext = wh;
@@ -632,33 +869,15 @@ var WormholeProvider = class {
632
869
  if (!this._wormholeContext) {
633
870
  throw new Error("Wormhole context not initialized");
634
871
  }
635
- const { sourceToken, destToken } = this.getTokenInfo(
636
- sourceChain,
637
- destinationChain
638
- );
639
- const destContext = this._wormholeContext.getPlatform(chainToPlatform(destinationChain)).getChain(destinationChain);
640
- const sourceContext = this._wormholeContext.getPlatform(chainToPlatform(sourceChain)).getChain(sourceChain);
641
- logger.log("sourceContext", sourceContext);
642
- logger.log("sourceToken", sourceToken);
643
- logger.log("destContext", destContext);
644
- logger.log("destToken", destToken);
645
- const request = await routes.RouteTransferRequest.create(
872
+ const { route: cctpRoute, request } = await createCCTPRoute(
646
873
  this._wormholeContext,
647
- {
648
- source: sourceToken,
649
- destination: destToken
650
- },
651
- sourceContext,
652
- destContext
874
+ sourceChain,
875
+ destinationChain,
876
+ this.crossChainCore.TOKENS
653
877
  );
654
- const resolver = this._wormholeContext.resolver([
655
- routes.CCTPRoute
656
- // manual CCTP
657
- ]);
658
- const route = await resolver.findRoutes(request);
659
- const cctpRoute = route[0];
660
878
  this.wormholeRoute = cctpRoute;
661
879
  this.wormholeRequest = request;
880
+ this.destinationChain = destinationChain;
662
881
  return { route: cctpRoute, request };
663
882
  }
664
883
  async getQuote(input) {
@@ -680,19 +899,19 @@ var WormholeProvider = class {
680
899
  const validated = await route.validate(request, transferParams);
681
900
  if (!validated.valid) {
682
901
  logger.log("invalid", validated.valid);
683
- throw new Error(`Invalid quote: ${validated.error}`).message;
902
+ throw new Error(`Invalid quote: ${validated.error}`);
684
903
  }
685
904
  const quote = await route.quote(request, validated.params);
686
905
  if (!quote.success) {
687
906
  logger.log("quote failed", quote.success);
688
- throw new Error(`Invalid quote: ${quote.error}`).message;
907
+ throw new Error(`Invalid quote: ${quote.error}`);
689
908
  }
690
909
  this.wormholeQuote = quote;
691
910
  logger.log("quote", quote);
692
911
  return quote;
693
912
  }
694
913
  async submitCCTPTransfer(input) {
695
- const { sourceChain, wallet, destinationAddress } = input;
914
+ const { sourceChain, wallet, destinationAddress, onTransactionSigned } = input;
696
915
  if (!this._wormholeContext) {
697
916
  await this.setWormholeContext(sourceChain);
698
917
  }
@@ -718,7 +937,9 @@ var WormholeProvider = class {
718
937
  signerAddress,
719
938
  {},
720
939
  wallet,
721
- this.crossChainCore
940
+ this.crossChainCore,
941
+ void 0,
942
+ onTransactionSigned
722
943
  );
723
944
  logger.log("signer", signer);
724
945
  logger.log("wormholeRequest", this.wormholeRequest);
@@ -727,16 +948,21 @@ var WormholeProvider = class {
727
948
  this.wormholeRequest,
728
949
  signer,
729
950
  this.wormholeQuote,
730
- Wormhole.chainAddress("Aptos", destinationAddress.toString())
951
+ Wormhole2.chainAddress("Aptos", destinationAddress.toString())
731
952
  );
732
953
  const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
733
954
  return { originChainTxnId: originChainTxnId || "", receipt };
734
955
  }
735
956
  async claimCCTPTransfer(input) {
736
- let { receipt, mainSigner, sponsorAccount } = input;
957
+ let { receipt, mainSigner, sponsorAccount, onTransactionSigned } = input;
737
958
  if (!this.wormholeRoute) {
738
959
  throw new Error("Wormhole route not initialized");
739
960
  }
961
+ if (sponsorAccount && !isAccount(sponsorAccount)) {
962
+ throw new Error(
963
+ "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."
964
+ );
965
+ }
740
966
  logger.log("mainSigner", mainSigner.accountAddress.toString());
741
967
  let retries = 0;
742
968
  const maxRetries = 5;
@@ -754,9 +980,10 @@ var WormholeProvider = class {
754
980
  // the account that signs the "claim" transaction
755
981
  sponsorAccount,
756
982
  // the fee payer account
757
- this.crossChainCore._dappConfig?.aptosNetwork
983
+ this.crossChainCore,
984
+ onTransactionSigned
758
985
  );
759
- if (routes.isManual(this.wormholeRoute)) {
986
+ if (routes3.isManual(this.wormholeRoute)) {
760
987
  const circleAttestationReceipt = await this.wormholeRoute.complete(signer, receipt);
761
988
  logger.log("Claim receipt: ", circleAttestationReceipt);
762
989
  const destinationChainTxnId = signer.claimedTransactionHashes();
@@ -799,22 +1026,30 @@ var WormholeProvider = class {
799
1026
  });
800
1027
  }
801
1028
  let { originChainTxnId, receipt } = await this.submitCCTPTransfer(input);
802
- const { destinationChainTxnId } = await this.claimCCTPTransfer({
803
- receipt,
804
- mainSigner: input.mainSigner,
805
- sponsorAccount: input.sponsorAccount
806
- });
807
- return { originChainTxnId, destinationChainTxnId };
808
- }
809
- async withdraw(input) {
810
- const { sourceChain, wallet, destinationAddress, sponsorAccount } = input;
811
- logger.log("sourceChain", sourceChain);
812
- logger.log("wallet", wallet);
813
- logger.log("destinationAddress", destinationAddress);
814
- logger.log("sponsorAccount", sponsorAccount);
815
- if (!this._wormholeContext) {
816
- await this.setWormholeContext(sourceChain);
1029
+ try {
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
+ );
817
1043
  }
1044
+ }
1045
+ // --- Split withdraw flow: initiateWithdraw + trackWithdraw + claimWithdraw ---
1046
+ /**
1047
+ * Phase 1: Initiates a withdraw by burning USDC on Aptos.
1048
+ * The user signs the Aptos burn transaction via their wallet.
1049
+ * Returns a receipt that can be tracked and later claimed.
1050
+ */
1051
+ async initiateWithdraw(input) {
1052
+ const { wallet, destinationAddress, sponsorAccount, onTransactionSigned } = input;
818
1053
  if (!this._wormholeContext) {
819
1054
  throw new Error("Wormhole context not initialized");
820
1055
  }
@@ -823,69 +1058,49 @@ var WormholeProvider = class {
823
1058
  }
824
1059
  const signer = new Signer(
825
1060
  this.getChainConfig("Aptos"),
826
- (await input.wallet.features["aptos:account"].account()).address.toString(),
1061
+ (await wallet.features["aptos:account"].account()).address.toString(),
827
1062
  {},
828
- input.wallet,
1063
+ wallet,
829
1064
  this.crossChainCore,
830
- sponsorAccount
1065
+ sponsorAccount,
1066
+ onTransactionSigned
831
1067
  );
832
- logger.log("signer", signer);
833
- logger.log("wormholeRequest", this.wormholeRequest);
834
- logger.log("wormholeQuote", this.wormholeQuote);
835
- logger.log(
836
- "Wormhole.chainAddress",
837
- Wormhole.chainAddress(sourceChain, input.destinationAddress.toString())
1068
+ const wormholeDestAddress = Wormhole2.chainAddress(
1069
+ this.destinationChain,
1070
+ destinationAddress.toString()
838
1071
  );
839
- let receipt = await this.wormholeRoute.initiate(
1072
+ const receipt = await this.wormholeRoute.initiate(
840
1073
  this.wormholeRequest,
841
1074
  signer,
842
1075
  this.wormholeQuote,
843
- Wormhole.chainAddress(sourceChain, input.destinationAddress.toString())
1076
+ wormholeDestAddress
844
1077
  );
845
- logger.log("receipt", receipt);
1078
+ logger.log("initiateWithdraw receipt", receipt);
846
1079
  const originChainTxnId = "originTxs" in receipt ? receipt.originTxs[receipt.originTxs.length - 1].txid : void 0;
1080
+ return { originChainTxnId: originChainTxnId || "", receipt };
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
+ }
847
1090
  let retries = 0;
848
1091
  const maxRetries = 5;
849
1092
  const baseDelay = 1e3;
850
1093
  while (retries < maxRetries) {
851
1094
  try {
852
1095
  for await (receipt of this.wormholeRoute.track(receipt, 120 * 1e3)) {
853
- if (receipt.state >= TransferState.SourceInitiated) {
854
- logger.log("Receipt is on track ", receipt);
855
- try {
856
- const signer2 = new Signer(
857
- this.getChainConfig(sourceChain),
858
- destinationAddress.toString(),
859
- {},
860
- wallet,
861
- this.crossChainCore
862
- );
863
- if (routes.isManual(this.wormholeRoute)) {
864
- const circleAttestationReceipt = await this.wormholeRoute.complete(signer2, receipt);
865
- logger.log("Claim receipt: ", circleAttestationReceipt);
866
- const destinationChainTxnId = signer2.claimedTransactionHashes();
867
- return {
868
- originChainTxnId: originChainTxnId || "",
869
- destinationChainTxnId
870
- };
871
- } else {
872
- return {
873
- originChainTxnId: originChainTxnId || "",
874
- destinationChainTxnId: ""
875
- };
876
- }
877
- } catch (e) {
878
- console.error("Failed to claim", e);
879
- return {
880
- originChainTxnId: originChainTxnId || "",
881
- destinationChainTxnId: ""
882
- };
883
- }
1096
+ if (receipt.state >= TransferState.Attested) {
1097
+ logger.log("trackWithdraw: receipt attested", receipt);
1098
+ return receipt;
884
1099
  }
885
1100
  }
886
1101
  } catch (e) {
887
1102
  console.error(
888
- `Error tracking transfer (attempt ${retries + 1} / ${maxRetries}):`,
1103
+ `Error tracking withdraw (attempt ${retries + 1} / ${maxRetries}):`,
889
1104
  e
890
1105
  );
891
1106
  const delay = baseDelay * Math.pow(2, retries);
@@ -893,10 +1108,173 @@ var WormholeProvider = class {
893
1108
  retries++;
894
1109
  }
895
1110
  }
896
- return {
897
- originChainTxnId: originChainTxnId || "",
898
- destinationChainTxnId: ""
899
- };
1111
+ throw new Error("Failed to track withdraw to attested state");
1112
+ }
1113
+ /**
1114
+ * Phase 3: Claims the withdraw on the destination chain.
1115
+ *
1116
+ * If the destination is Solana and `solanaConfig.serverClaimUrl` is configured
1117
+ * in the dapp config, the SDK automatically POSTs the attested receipt to that
1118
+ * URL — no wallet popup required. The dapp's server endpoint handles signing
1119
+ * and submitting the claim transaction.
1120
+ *
1121
+ * Otherwise falls back to the wallet-based Signer (triggers wallet popup).
1122
+ */
1123
+ async claimWithdraw(input) {
1124
+ const { claimChain, destinationAddress, receipt } = input;
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
+ }
1175
+ }
1176
+ /**
1177
+ * Withdraws USDC from Aptos to a destination chain.
1178
+ * Orchestrates all three phases internally:
1179
+ * 1. Initiate — user signs the Aptos burn transaction
1180
+ * 2. Track — wait for Wormhole attestation
1181
+ * 3. Claim — if serverClaimUrl is configured for Solana, delegates to
1182
+ * the server; otherwise uses the wallet-based signer.
1183
+ *
1184
+ * The optional `onPhaseChange` callback lets the dapp update its UI
1185
+ * as the flow progresses.
1186
+ */
1187
+ async withdraw(input) {
1188
+ const {
1189
+ sourceChain,
1190
+ wallet,
1191
+ destinationAddress,
1192
+ sponsorAccount,
1193
+ onPhaseChange,
1194
+ onTransactionSigned
1195
+ } = input;
1196
+ onPhaseChange?.("initiating");
1197
+ const { originChainTxnId, receipt } = await this.initiateWithdraw({
1198
+ wallet,
1199
+ destinationAddress,
1200
+ sponsorAccount,
1201
+ onTransactionSigned
1202
+ });
1203
+ let currentPhase = "tracking";
1204
+ try {
1205
+ onPhaseChange?.("tracking");
1206
+ const attestedReceipt = await this.trackWithdraw(receipt);
1207
+ currentPhase = "claiming";
1208
+ onPhaseChange?.("claiming");
1209
+ const { destinationChainTxnId } = await this.claimWithdraw({
1210
+ claimChain: sourceChain,
1211
+ destinationAddress: destinationAddress.toString(),
1212
+ receipt: attestedReceipt,
1213
+ wallet,
1214
+ onTransactionSigned
1215
+ });
1216
+ return { originChainTxnId, destinationChainTxnId };
1217
+ } catch (error) {
1218
+ throw new WithdrawError(
1219
+ error?.message ?? "Withdraw failed after Aptos burn",
1220
+ originChainTxnId,
1221
+ currentPhase,
1222
+ error
1223
+ );
1224
+ }
1225
+ }
1226
+ /**
1227
+ * Retries a failed `claimWithdraw` call with configurable exponential backoff.
1228
+ *
1229
+ * Use this when the claim phase of a withdrawal fails (e.g., RPC instability,
1230
+ * network congestion) but the Aptos burn transaction has already been submitted.
1231
+ * The attested receipt can be recovered from the `WithdrawError` thrown by
1232
+ * `withdraw()` and passed directly to this method.
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * try {
1237
+ * await provider.withdraw({ ... });
1238
+ * } catch (error) {
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;
1272
+ }
1273
+ }
1274
+ }
1275
+ throw new Error(
1276
+ `Claim failed after ${maxRetries + 1} attempts: ${lastError?.message}`
1277
+ );
900
1278
  }
901
1279
  getChainConfig(chain) {
902
1280
  const chainConfig = this.crossChainCore.CHAINS[chain];
@@ -905,16 +1283,124 @@ var WormholeProvider = class {
905
1283
  }
906
1284
  return chainConfig;
907
1285
  }
908
- getTokenInfo(sourceChain, destinationChain) {
909
- const sourceToken = Wormhole.tokenId(
910
- this.crossChainCore.TOKENS[sourceChain].tokenId.chain,
911
- this.crossChainCore.TOKENS[sourceChain].tokenId.address
912
- );
913
- const destToken = Wormhole.tokenId(
914
- this.crossChainCore.TOKENS[destinationChain].tokenId.chain,
915
- this.crossChainCore.TOKENS[destinationChain].tokenId.address
1286
+ };
1287
+
1288
+ // src/providers/wormhole/signers/SolanaLocalSigner.ts
1289
+ import {
1290
+ Transaction as Transaction3
1291
+ } from "@solana/web3.js";
1292
+ var SolanaLocalSigner = class {
1293
+ constructor(config) {
1294
+ this._claimedTransactionHashes = [];
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";
1305
+ }
1306
+ address() {
1307
+ return this.keypair.publicKey.toBase58();
1308
+ }
1309
+ /**
1310
+ * Returns all transaction hashes from the most recent signAndSend call,
1311
+ * joined by comma. If only one transaction was signed, returns a single hash string.
1312
+ */
1313
+ claimedTransactionHashes() {
1314
+ return this._claimedTransactionHashes.join(",");
1315
+ }
1316
+ async signAndSend(txs) {
1317
+ const txHashes = [];
1318
+ this._claimedTransactionHashes = [];
1319
+ for (const tx of txs) {
1320
+ this._onTransactionSigned?.(tx.description, null);
1321
+ const txId = await this.signAndSendTransaction(tx);
1322
+ this._onTransactionSigned?.(tx.description, txId);
1323
+ txHashes.push(txId);
1324
+ this._claimedTransactionHashes.push(txId);
1325
+ }
1326
+ return txHashes;
1327
+ }
1328
+ async signAndSendTransaction(request) {
1329
+ const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash(this.commitment);
1330
+ let unsignedTx = request.transaction ?? request;
1331
+ const additionalSigners = request.transaction?.signers;
1332
+ const MAX_UNWRAP_DEPTH = 10;
1333
+ let unwrapDepth = 0;
1334
+ while (unsignedTx && typeof unsignedTx === "object" && "transaction" in unsignedTx && !(unsignedTx instanceof Transaction3) && !("signatures" in unsignedTx && "message" in unsignedTx)) {
1335
+ if (++unwrapDepth > MAX_UNWRAP_DEPTH) {
1336
+ throw new Error(
1337
+ "Transaction unwrapping exceeded maximum depth \u2014 possible circular nesting"
1338
+ );
1339
+ }
1340
+ unsignedTx = unsignedTx.transaction;
1341
+ }
1342
+ const isVersioned = unsignedTx.message !== void 0 && unsignedTx.signatures !== void 0 && typeof unsignedTx.message.recentBlockhash !== "undefined";
1343
+ if (isVersioned) {
1344
+ unsignedTx.message.recentBlockhash = blockhash;
1345
+ if (this.verbose || this.priorityFeeConfig) {
1346
+ console.warn(
1347
+ "SolanaLocalSigner: Versioned transaction detected \u2014 priority fees are not applied. Consider using legacy transactions if priority fees are required."
1348
+ );
1349
+ }
1350
+ unsignedTx.sign([this.keypair]);
1351
+ if (additionalSigners && additionalSigners.length > 0) {
1352
+ unsignedTx.sign(additionalSigners);
1353
+ }
1354
+ } else if (unsignedTx instanceof Transaction3) {
1355
+ unsignedTx.recentBlockhash = blockhash;
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);
1385
+ }
1386
+ } else {
1387
+ throw new Error(
1388
+ `Unsupported transaction type: ${unsignedTx?.constructor?.name}`
1389
+ );
1390
+ }
1391
+ const serializedTx = unsignedTx.serialize();
1392
+ const signature = await sendAndConfirmTransaction(
1393
+ serializedTx,
1394
+ blockhash,
1395
+ lastValidBlockHeight,
1396
+ {
1397
+ connection: this.connection,
1398
+ commitment: this.commitment,
1399
+ retryIntervalMs: this.retryIntervalMs,
1400
+ verbose: this.verbose
1401
+ }
916
1402
  );
917
- return { sourceToken, destToken };
1403
+ return signature;
918
1404
  }
919
1405
  };
920
1406
 
@@ -988,8 +1474,8 @@ var testnetChains = {
988
1474
  key: "Solana",
989
1475
  context: "Solana" /* SOLANA */,
990
1476
  displayName: "Solana",
991
- explorerUrl: "https://explorer.solana.com/",
992
- explorerName: "Solana Explorer",
1477
+ explorerUrl: "https://solscan.io",
1478
+ explorerName: "Solscan",
993
1479
  chainId: 0,
994
1480
  icon: "Solana",
995
1481
  symbol: "SOL",
@@ -1112,8 +1598,8 @@ var mainnetChains = {
1112
1598
  key: "Solana",
1113
1599
  context: "Solana" /* SOLANA */,
1114
1600
  displayName: "Solana",
1115
- explorerUrl: "https://explorer.solana.com/",
1116
- explorerName: "Solana Explorer",
1601
+ explorerUrl: "https://solscan.io",
1602
+ explorerName: "Solscan",
1117
1603
  chainId: 0,
1118
1604
  icon: "Solana",
1119
1605
  symbol: "SOL",
@@ -1265,13 +1751,13 @@ var mainnetTokens = {
1265
1751
 
1266
1752
  // src/utils/getUsdcBalance.ts
1267
1753
  import { Aptos as Aptos3, AptosConfig as AptosConfig3, Network as Network2 } from "@aptos-labs/ts-sdk";
1268
- import { Connection as Connection2, PublicKey } from "@solana/web3.js";
1754
+ import { Connection as Connection4, PublicKey } from "@solana/web3.js";
1269
1755
  import { ethers as ethers2, JsonRpcProvider } from "ethers";
1270
1756
  import { SuiClient } from "@mysten/sui/client";
1271
1757
  var getSolanaWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
1272
1758
  const address = new PublicKey(walletAddress);
1273
1759
  const tokenAddress = aptosNetwork === Network2.MAINNET ? mainnetTokens["Solana"].tokenId.address : testnetTokens["Solana"].tokenId.address;
1274
- const connection = new Connection2(rpc);
1760
+ const connection = new Connection4(rpc);
1275
1761
  const splToken = await connection.getTokenAccountsByOwner(address, {
1276
1762
  mint: new PublicKey(tokenAddress)
1277
1763
  });
@@ -1324,6 +1810,18 @@ var getSuiWalletUSDCBalance = async (walletAddress, aptosNetwork, rpc) => {
1324
1810
 
1325
1811
  // src/CrossChainCore.ts
1326
1812
  import { NetworkToChainId, NetworkToNodeAPI } from "@aptos-labs/ts-sdk";
1813
+ var _evmChainRecord = {
1814
+ Ethereum: true,
1815
+ Sepolia: true,
1816
+ BaseSepolia: true,
1817
+ ArbitrumSepolia: true,
1818
+ Avalanche: true,
1819
+ Base: true,
1820
+ Arbitrum: true,
1821
+ PolygonSepolia: true,
1822
+ Polygon: true
1823
+ };
1824
+ var EVM_CHAIN_NAMES = Object.keys(_evmChainRecord);
1327
1825
  var EthereumChainIdToTestnetChain = {
1328
1826
  11155111: testnetChains.Sepolia,
1329
1827
  84532: testnetChains.BaseSepolia,
@@ -1338,7 +1836,7 @@ var EthereumChainIdToMainnetChain = {
1338
1836
  43114: mainnetChains.Avalanche,
1339
1837
  137: mainnetChains.Polygon
1340
1838
  };
1341
- var CrossChainCore = class {
1839
+ var CrossChainCore2 = class {
1342
1840
  constructor(args) {
1343
1841
  this._dappConfig = {
1344
1842
  aptosNetwork: Network3.TESTNET
@@ -1392,14 +1890,13 @@ var CrossChainCore = class {
1392
1890
  walletAddress,
1393
1891
  this._dappConfig.aptosNetwork,
1394
1892
  sourceChain,
1395
- // TODO: maybe let the user config it
1396
- this.CHAINS[sourceChain].defaultRpc
1893
+ this._dappConfig?.evmConfig?.[sourceChain]?.rpc ?? this.CHAINS[sourceChain].defaultRpc
1397
1894
  );
1398
1895
  case "Sui":
1399
1896
  return await getSuiWalletUSDCBalance(
1400
1897
  walletAddress,
1401
1898
  this._dappConfig.aptosNetwork,
1402
- this.CHAINS[sourceChain].defaultRpc
1899
+ this._dappConfig?.suiConfig?.rpc ?? this.CHAINS[sourceChain].defaultRpc
1403
1900
  );
1404
1901
  default:
1405
1902
  throw new Error(`Unsupported chain: ${sourceChain}`);
@@ -1412,17 +1909,25 @@ import { Network as Network4 } from "@aptos-labs/ts-sdk";
1412
1909
  export {
1413
1910
  AptosLocalSigner,
1414
1911
  Context,
1415
- CrossChainCore,
1912
+ CrossChainCore2 as CrossChainCore,
1913
+ EVM_CHAIN_NAMES,
1416
1914
  EthereumChainIdToMainnetChain,
1417
1915
  EthereumChainIdToTestnetChain,
1418
1916
  Network4 as Network,
1419
1917
  NetworkToChainId,
1420
1918
  NetworkToNodeAPI,
1919
+ SolanaLocalSigner,
1920
+ TransferError,
1921
+ WithdrawError,
1421
1922
  WormholeProvider,
1923
+ createCCTPRoute,
1924
+ deserializeReceipt,
1422
1925
  mainnetChains,
1423
1926
  mainnetTokens,
1927
+ serializeReceipt,
1424
1928
  signAndSendTransaction,
1425
1929
  testnetChains,
1426
- testnetTokens
1930
+ testnetTokens,
1931
+ validateExpireTimestamp
1427
1932
  };
1428
1933
  //# sourceMappingURL=index.mjs.map