@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.
- package/LICENSE +201 -0
- package/dist/CrossChainCore.d.ts +36 -0
- package/dist/CrossChainCore.d.ts.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/mainnet/chains.d.ts +17 -0
- package/dist/config/mainnet/chains.d.ts.map +1 -0
- package/dist/config/mainnet/index.d.ts +3 -0
- package/dist/config/mainnet/index.d.ts.map +1 -0
- package/dist/config/mainnet/tokens.d.ts +4 -0
- package/dist/config/mainnet/tokens.d.ts.map +1 -0
- package/dist/config/testnet/chains.d.ts +19 -0
- package/dist/config/testnet/chains.d.ts.map +1 -0
- package/dist/config/testnet/index.d.ts +3 -0
- package/dist/config/testnet/index.d.ts.map +1 -0
- package/dist/config/testnet/tokens.d.ts +4 -0
- package/dist/config/testnet/tokens.d.ts.map +1 -0
- package/dist/config/types.d.ts +41 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +989 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +957 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/wormhole/index.d.ts +5 -0
- package/dist/providers/wormhole/index.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts +18 -0
- package/dist/providers/wormhole/signers/AptosLocalSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts +5 -0
- package/dist/providers/wormhole/signers/EthereumSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/Signer.d.ts +17 -0
- package/dist/providers/wormhole/signers/Signer.d.ts.map +1 -0
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts +28 -0
- package/dist/providers/wormhole/signers/SolanaSigner.d.ts.map +1 -0
- package/dist/providers/wormhole/types.d.ts +39 -0
- package/dist/providers/wormhole/types.d.ts.map +1 -0
- package/dist/providers/wormhole/wormhole.d.ts +35 -0
- package/dist/providers/wormhole/wormhole.d.ts.map +1 -0
- package/dist/utils/getUsdcBalance.d.ts +5 -0
- package/dist/utils/getUsdcBalance.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +83 -0
- package/src/CrossChainCore.ts +130 -0
- package/src/config/index.ts +3 -0
- package/src/config/mainnet/chains.ts +64 -0
- package/src/config/mainnet/index.ts +2 -0
- package/src/config/mainnet/tokens.ts +43 -0
- package/src/config/testnet/chains.ts +69 -0
- package/src/config/testnet/index.ts +2 -0
- package/src/config/testnet/tokens.ts +43 -0
- package/src/config/types.ts +45 -0
- package/src/index.ts +5 -0
- package/src/providers/wormhole/index.ts +4 -0
- package/src/providers/wormhole/signers/AptosLocalSigner.ts +136 -0
- package/src/providers/wormhole/signers/EthereumSigner.ts +49 -0
- package/src/providers/wormhole/signers/Signer.ts +102 -0
- package/src/providers/wormhole/signers/SolanaSigner.ts +418 -0
- package/src/providers/wormhole/types.ts +59 -0
- package/src/providers/wormhole/wormhole.ts +320 -0
- package/src/utils/getUsdcBalance.ts +82 -0
- package/src/utils/logger.ts +17 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
// This function signs and sends the transaction while constantly checking for confirmation
|
|
2
|
+
// and resending the transaction if it hasn't been confirmed after the specified interval
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
AddressLookupTableAccount,
|
|
6
|
+
Commitment,
|
|
7
|
+
ComputeBudgetProgram,
|
|
8
|
+
ConfirmOptions,
|
|
9
|
+
LAMPORTS_PER_SOL,
|
|
10
|
+
SimulatedTransactionResponse,
|
|
11
|
+
TransactionInstruction,
|
|
12
|
+
TransactionMessage,
|
|
13
|
+
VersionedTransaction,
|
|
14
|
+
} from "@solana/web3.js";
|
|
15
|
+
|
|
16
|
+
import { Transaction } from "@solana/web3.js";
|
|
17
|
+
import { RpcResponseAndContext, SignatureResult } from "@solana/web3.js";
|
|
18
|
+
import {
|
|
19
|
+
determinePriorityFee,
|
|
20
|
+
determinePriorityFeeTritonOne,
|
|
21
|
+
SolanaUnsignedTransaction,
|
|
22
|
+
} from "@wormhole-foundation/sdk-solana";
|
|
23
|
+
|
|
24
|
+
import { Connection } from "@solana/web3.js";
|
|
25
|
+
import { Network } from "@wormhole-foundation/sdk";
|
|
26
|
+
import { AdapterWallet } from "@aptos-labs/wallet-adapter-core";
|
|
27
|
+
import { CrossChainCore } from "../../../CrossChainCore";
|
|
28
|
+
import { SolanaDerivedWallet } from "@aptos-labs/derived-wallet-solana";
|
|
29
|
+
|
|
30
|
+
export type SolanaRpcProvider = "triton" | "helius" | "ankr" | "unknown";
|
|
31
|
+
|
|
32
|
+
// See https://docs.triton.one/chains/solana/sending-txs for more information
|
|
33
|
+
export async function signAndSendTransaction(
|
|
34
|
+
request: SolanaUnsignedTransaction<Network>,
|
|
35
|
+
wallet: AdapterWallet | undefined,
|
|
36
|
+
options?: ConfirmOptions,
|
|
37
|
+
crossChainCore?: CrossChainCore
|
|
38
|
+
) {
|
|
39
|
+
if (!wallet || !(wallet instanceof SolanaDerivedWallet)) {
|
|
40
|
+
throw new Error("Invalid wallet type or missing Solana wallet").message;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const commitment = options?.commitment ?? "finalized";
|
|
44
|
+
// Solana rpc should come from dapp config
|
|
45
|
+
const connection = new Connection(
|
|
46
|
+
crossChainCore?._dappConfig?.solanaConfig?.rpc ??
|
|
47
|
+
"https://api.devnet.solana.com"
|
|
48
|
+
);
|
|
49
|
+
const { blockhash, lastValidBlockHeight } =
|
|
50
|
+
await connection.getLatestBlockhash(commitment);
|
|
51
|
+
|
|
52
|
+
// Circle Manual CCTP on Wormhole is always of a Trnasaction type
|
|
53
|
+
// https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/f7d992e04f844edcc4128659f12f75ade3553717/platforms/solana/protocols/cctp/src/circleBridge.ts#L173
|
|
54
|
+
const transaction = request.transaction.transaction as Transaction;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* TODO: Priority Fee is supported, but needs to come from dapp config
|
|
58
|
+
*/
|
|
59
|
+
const unsignedTx = await setPriorityFeeInstructions(
|
|
60
|
+
connection,
|
|
61
|
+
blockhash,
|
|
62
|
+
lastValidBlockHeight,
|
|
63
|
+
request,
|
|
64
|
+
crossChainCore
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
let confirmTransactionPromise: Promise<
|
|
68
|
+
RpcResponseAndContext<SignatureResult>
|
|
69
|
+
> | null = null;
|
|
70
|
+
let confirmedTx: RpcResponseAndContext<SignatureResult> | null = null;
|
|
71
|
+
let txSendAttempts = 1;
|
|
72
|
+
let signature = "";
|
|
73
|
+
|
|
74
|
+
// transaction.recentBlockhash = blockhash;
|
|
75
|
+
// if (request.transaction.signers) {
|
|
76
|
+
// transaction.partialSign(...request.transaction.signers);
|
|
77
|
+
// }
|
|
78
|
+
|
|
79
|
+
if (!wallet.solanaWallet.signTransaction) {
|
|
80
|
+
throw new Error("Wallet does not support signing transactions").message;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const tx = await wallet.solanaWallet.signTransaction(unsignedTx);
|
|
84
|
+
|
|
85
|
+
if (!tx) throw new Error("Failed to sign transaction").message;
|
|
86
|
+
const serializedTx = tx.serialize();
|
|
87
|
+
const sendOptions = {
|
|
88
|
+
skipPreflight: true,
|
|
89
|
+
maxRetries: 0,
|
|
90
|
+
preFlightCommitment: commitment, // See PR and linked issue for why setting this matters: https://github.com/anza-xyz/agave/pull/483
|
|
91
|
+
};
|
|
92
|
+
signature = await connection.sendRawTransaction(serializedTx, sendOptions);
|
|
93
|
+
confirmTransactionPromise = connection.confirmTransaction(
|
|
94
|
+
{
|
|
95
|
+
signature,
|
|
96
|
+
blockhash,
|
|
97
|
+
lastValidBlockHeight,
|
|
98
|
+
},
|
|
99
|
+
commitment
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// This loop will break once the transaction has been confirmed or the block height is exceeded.
|
|
103
|
+
// An exception will be thrown if the block height is exceeded by the confirmTransactionPromise.
|
|
104
|
+
// The transaction will be resent if it hasn't been confirmed after the interval.
|
|
105
|
+
const txRetryInterval = 5000;
|
|
106
|
+
while (!confirmedTx) {
|
|
107
|
+
confirmedTx = await Promise.race([
|
|
108
|
+
confirmTransactionPromise,
|
|
109
|
+
new Promise<null>((resolve) =>
|
|
110
|
+
setTimeout(() => {
|
|
111
|
+
resolve(null);
|
|
112
|
+
}, txRetryInterval)
|
|
113
|
+
),
|
|
114
|
+
]);
|
|
115
|
+
if (confirmedTx) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
console.log(
|
|
119
|
+
`Tx not confirmed after ${
|
|
120
|
+
txRetryInterval * txSendAttempts++
|
|
121
|
+
}ms, resending`
|
|
122
|
+
);
|
|
123
|
+
try {
|
|
124
|
+
await connection.sendRawTransaction(serializedTx, sendOptions);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error("Failed to resend transaction:", e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (confirmedTx.value.err) {
|
|
131
|
+
let errorMessage = `Transaction failed: ${confirmedTx.value.err}`;
|
|
132
|
+
if (typeof confirmedTx.value.err === "object") {
|
|
133
|
+
try {
|
|
134
|
+
errorMessage = `Transaction failed: ${JSON.stringify(
|
|
135
|
+
confirmedTx.value.err,
|
|
136
|
+
(_key, value) =>
|
|
137
|
+
typeof value === "bigint" ? value.toString() : value // Handle bigint props
|
|
138
|
+
)}`;
|
|
139
|
+
} catch (e: unknown) {
|
|
140
|
+
// Most likely a circular reference error, we can't stringify this error object.
|
|
141
|
+
// See for more details:
|
|
142
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#exceptions
|
|
143
|
+
errorMessage = `Transaction failed: Unknown error`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Transaction failed: ${errorMessage}`).message;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return signature;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function setPriorityFeeInstructions(
|
|
153
|
+
connection: Connection,
|
|
154
|
+
blockhash: string,
|
|
155
|
+
lastValidBlockHeight: number,
|
|
156
|
+
request: SolanaUnsignedTransaction<Network>,
|
|
157
|
+
crossChainCore?: CrossChainCore
|
|
158
|
+
): Promise<Transaction | VersionedTransaction> {
|
|
159
|
+
const unsignedTx = request.transaction.transaction as Transaction;
|
|
160
|
+
|
|
161
|
+
const computeBudgetIxFilter = (ix: TransactionInstruction) =>
|
|
162
|
+
ix.programId.toString() !== "ComputeBudget111111111111111111111111111111";
|
|
163
|
+
|
|
164
|
+
unsignedTx.recentBlockhash = blockhash;
|
|
165
|
+
unsignedTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
166
|
+
|
|
167
|
+
// Remove existing compute budget instructions if they were added by the SDK
|
|
168
|
+
unsignedTx.instructions = unsignedTx.instructions.filter(
|
|
169
|
+
computeBudgetIxFilter
|
|
170
|
+
);
|
|
171
|
+
unsignedTx.add(
|
|
172
|
+
...(await createPriorityFeeInstructions(
|
|
173
|
+
connection,
|
|
174
|
+
unsignedTx,
|
|
175
|
+
crossChainCore
|
|
176
|
+
))
|
|
177
|
+
);
|
|
178
|
+
if (request.transaction.signers) {
|
|
179
|
+
unsignedTx.partialSign(...request.transaction.signers);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return unsignedTx;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// This will throw if the simulation fails
|
|
186
|
+
async function createPriorityFeeInstructions(
|
|
187
|
+
connection: Connection,
|
|
188
|
+
transaction: Transaction | VersionedTransaction,
|
|
189
|
+
crossChainCore?: CrossChainCore
|
|
190
|
+
) {
|
|
191
|
+
let unitsUsed = 200_000;
|
|
192
|
+
let simulationAttempts = 0;
|
|
193
|
+
|
|
194
|
+
simulationLoop: while (true) {
|
|
195
|
+
const response = await connection.simulateTransaction(
|
|
196
|
+
transaction as Transaction
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
if (response.value.err) {
|
|
200
|
+
if (checkKnownSimulationError(response.value)) {
|
|
201
|
+
// Number of attempts will be at most 5 for known errors
|
|
202
|
+
if (simulationAttempts < 5) {
|
|
203
|
+
simulationAttempts++;
|
|
204
|
+
await sleep(1000);
|
|
205
|
+
continue simulationLoop;
|
|
206
|
+
}
|
|
207
|
+
} else if (simulationAttempts < 3) {
|
|
208
|
+
// Number of attempts will be at most 3 for unknown errors
|
|
209
|
+
simulationAttempts++;
|
|
210
|
+
await sleep(1000);
|
|
211
|
+
continue simulationLoop;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Still failing after multiple attempts for both known and unknown errors
|
|
215
|
+
// We should throw in that case
|
|
216
|
+
throw new Error(
|
|
217
|
+
`Simulation failed: ${JSON.stringify(response.value.err)}\nLogs:\n${(
|
|
218
|
+
response.value.logs || []
|
|
219
|
+
).join("\n ")}`
|
|
220
|
+
).message;
|
|
221
|
+
} else {
|
|
222
|
+
// Simulation was successful
|
|
223
|
+
if (response.value.unitsConsumed) {
|
|
224
|
+
unitsUsed = response.value.unitsConsumed;
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const unitBudget = Math.floor(unitsUsed * 1.2); // Budget in 20% headroom
|
|
231
|
+
|
|
232
|
+
const instructions: TransactionInstruction[] = [];
|
|
233
|
+
instructions.push(
|
|
234
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
235
|
+
// Set compute budget to 120% of the units used in the simulated transaction
|
|
236
|
+
units: unitBudget,
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const {
|
|
241
|
+
percentile = 0.9,
|
|
242
|
+
percentileMultiple = 1,
|
|
243
|
+
min = 100_000,
|
|
244
|
+
max = 100_000_000,
|
|
245
|
+
} = crossChainCore?._dappConfig?.solanaConfig?.priorityFeeConfig ?? {};
|
|
246
|
+
|
|
247
|
+
const calculateFee = async (
|
|
248
|
+
rpcProvider?: SolanaRpcProvider
|
|
249
|
+
): Promise<{ fee: number; methodUsed: "triton" | "default" | "minimum" }> => {
|
|
250
|
+
if (rpcProvider === "triton") {
|
|
251
|
+
// Triton has an experimental RPC method that accepts a percentile paramater
|
|
252
|
+
// and usually gives more accurate fee numbers.
|
|
253
|
+
try {
|
|
254
|
+
const fee = await determinePriorityFeeTritonOne(
|
|
255
|
+
connection,
|
|
256
|
+
transaction,
|
|
257
|
+
percentile,
|
|
258
|
+
percentileMultiple,
|
|
259
|
+
min,
|
|
260
|
+
max
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
fee,
|
|
265
|
+
methodUsed: "triton",
|
|
266
|
+
};
|
|
267
|
+
} catch (e) {
|
|
268
|
+
console.warn(`Failed to determine priority fee using Triton RPC:`, e);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
// By default, use generic Solana RPC method
|
|
274
|
+
const fee = await determinePriorityFee(
|
|
275
|
+
connection,
|
|
276
|
+
transaction,
|
|
277
|
+
percentile,
|
|
278
|
+
percentileMultiple,
|
|
279
|
+
min,
|
|
280
|
+
max
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
fee,
|
|
285
|
+
methodUsed: "default",
|
|
286
|
+
};
|
|
287
|
+
} catch (e) {
|
|
288
|
+
console.warn(`Failed to determine priority fee using Triton RPC:`, e);
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
fee: min,
|
|
292
|
+
methodUsed: "minimum",
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const rpcProvider = determineRpcProvider(connection.rpcEndpoint);
|
|
298
|
+
|
|
299
|
+
const { fee, methodUsed } = await calculateFee(rpcProvider);
|
|
300
|
+
|
|
301
|
+
const maxFeeInSol =
|
|
302
|
+
(fee /
|
|
303
|
+
// convert microlamports to lamports
|
|
304
|
+
1e6 /
|
|
305
|
+
// convert lamports to SOL
|
|
306
|
+
LAMPORTS_PER_SOL) *
|
|
307
|
+
// multiply by maximum compute units used
|
|
308
|
+
unitBudget;
|
|
309
|
+
|
|
310
|
+
console.table({
|
|
311
|
+
"RPC Provider": rpcProvider,
|
|
312
|
+
"Method used": methodUsed,
|
|
313
|
+
"Percentile used": percentile,
|
|
314
|
+
"Multiple used": percentileMultiple,
|
|
315
|
+
"Compute budget": unitBudget,
|
|
316
|
+
"Priority fee": fee,
|
|
317
|
+
"Max fee in SOL": maxFeeInSol,
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
instructions.push(
|
|
321
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: fee })
|
|
322
|
+
);
|
|
323
|
+
return instructions;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Checks response logs for known errors.
|
|
327
|
+
// Returns when the first error is encountered.
|
|
328
|
+
function checkKnownSimulationError(
|
|
329
|
+
response: SimulatedTransactionResponse
|
|
330
|
+
): boolean {
|
|
331
|
+
const errors = {} as any;
|
|
332
|
+
|
|
333
|
+
// This error occur when the blockhash included in a transaction is not deemed to be valid
|
|
334
|
+
// when a validator processes a transaction. We can retry the simulation to get a valid blockhash.
|
|
335
|
+
if (response.err === "BlockhashNotFound") {
|
|
336
|
+
errors["BlockhashNotFound"] =
|
|
337
|
+
"Blockhash not found during simulation. Trying again.";
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Check the response logs for any known errors
|
|
341
|
+
if (response.logs) {
|
|
342
|
+
for (const line of response.logs) {
|
|
343
|
+
// In some cases which aren't deterministic, like a slippage error, we can retry the
|
|
344
|
+
// simulation a few times to get a successful response.
|
|
345
|
+
if (line.includes("SlippageToleranceExceeded")) {
|
|
346
|
+
errors["SlippageToleranceExceeded"] =
|
|
347
|
+
"Slippage failure during simulation. Trying again.";
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// In this case a require_gte expression was violated during a Swap instruction.
|
|
351
|
+
// We can retry the simulation to get a successful response.
|
|
352
|
+
if (line.includes("RequireGteViolated")) {
|
|
353
|
+
errors["RequireGteViolated"] =
|
|
354
|
+
"Swap instruction failure during simulation. Trying again.";
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// No known simulation errors found
|
|
360
|
+
if (isEmptyObject(errors)) {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
console.table(errors);
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export async function sleep(timeout: number) {
|
|
369
|
+
return new Promise((resolve) => setTimeout(resolve, timeout));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Checks whether an object is empty.
|
|
374
|
+
*
|
|
375
|
+
* isEmptyObject(null)
|
|
376
|
+
* // => true
|
|
377
|
+
*
|
|
378
|
+
* isEmptyObject(undefined)
|
|
379
|
+
* // => true
|
|
380
|
+
*
|
|
381
|
+
* isEmptyObject({})
|
|
382
|
+
* // => true
|
|
383
|
+
*
|
|
384
|
+
* isEmptyObject({ 'a': 1 })
|
|
385
|
+
* // => false
|
|
386
|
+
*/
|
|
387
|
+
export const isEmptyObject = (value: object | null | undefined) => {
|
|
388
|
+
if (value === null || value === undefined) {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Check all property keys for any own prop
|
|
393
|
+
for (const key in value) {
|
|
394
|
+
if (value.hasOwnProperty.call(value, key)) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return true;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
function determineRpcProvider(endpoint: string): SolanaRpcProvider {
|
|
403
|
+
try {
|
|
404
|
+
const url = new URL(endpoint);
|
|
405
|
+
const hostname = url.hostname;
|
|
406
|
+
if (hostname === "rpcpool.com") {
|
|
407
|
+
return "triton";
|
|
408
|
+
} else if (hostname === "helius-rpc.com") {
|
|
409
|
+
return "helius";
|
|
410
|
+
} else if (hostname === "rpc.ankr.com") {
|
|
411
|
+
return "ankr";
|
|
412
|
+
} else {
|
|
413
|
+
return "unknown";
|
|
414
|
+
}
|
|
415
|
+
} catch (e) {
|
|
416
|
+
return "unknown";
|
|
417
|
+
}
|
|
418
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AccountAddressInput, Account } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import { AdapterWallet } from "@aptos-labs/wallet-adapter-core";
|
|
3
|
+
import { routes, AttestationReceipt } from "@wormhole-foundation/sdk/dist/cjs";
|
|
4
|
+
import { Chain, AptosAccount } from "../..";
|
|
5
|
+
|
|
6
|
+
export type WormholeRouteResponse = routes.Route<
|
|
7
|
+
"Mainnet" | "Testnet",
|
|
8
|
+
routes.Options,
|
|
9
|
+
routes.ValidatedTransferParams<routes.Options>,
|
|
10
|
+
routes.Receipt
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
export type WormholeRequest = routes.RouteTransferRequest<
|
|
14
|
+
"Mainnet" | "Testnet"
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
export type WormholeQuoteResponse = routes.Quote<
|
|
18
|
+
routes.Options,
|
|
19
|
+
routes.ValidatedTransferParams<routes.Options>,
|
|
20
|
+
any
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
export interface WormholeQuoteRequest {
|
|
24
|
+
amount: string;
|
|
25
|
+
sourceChain: Chain;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type GasStationApiKey = string;
|
|
29
|
+
|
|
30
|
+
export interface WormholeInitiateTransferRequest {
|
|
31
|
+
sourceChain: Chain;
|
|
32
|
+
wallet: AdapterWallet;
|
|
33
|
+
destinationAddress: AccountAddressInput;
|
|
34
|
+
mainSigner: Account;
|
|
35
|
+
amount?: string;
|
|
36
|
+
sponsorAccount?: Account | GasStationApiKey;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface WormholeSubmitTransferRequest {
|
|
40
|
+
sourceChain: Chain;
|
|
41
|
+
wallet: AdapterWallet;
|
|
42
|
+
destinationAddress: AccountAddressInput;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface WormholeClaimTransferRequest {
|
|
46
|
+
receipt: routes.Receipt<AttestationReceipt>;
|
|
47
|
+
mainSigner: AptosAccount;
|
|
48
|
+
sponsorAccount?: AptosAccount | GasStationApiKey;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface WormholeInitiateTransferResponse {
|
|
52
|
+
destinationChainTxnId: string;
|
|
53
|
+
originChainTxnId: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface WormholeStartTransferResponse {
|
|
57
|
+
originChainTxnId: string;
|
|
58
|
+
receipt: routes.Receipt<AttestationReceipt>;
|
|
59
|
+
}
|