@chainlink/ccip-sdk 0.95.0 → 0.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/all-chains.d.ts +23 -0
- package/dist/all-chains.d.ts.map +1 -0
- package/dist/all-chains.js +24 -0
- package/dist/all-chains.js.map +1 -0
- package/dist/api/index.d.ts +31 -19
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +46 -25
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +24 -30
- package/dist/api/types.d.ts.map +1 -1
- package/dist/aptos/exec.d.ts +2 -2
- package/dist/aptos/exec.d.ts.map +1 -1
- package/dist/aptos/exec.js.map +1 -1
- package/dist/aptos/hasher.d.ts.map +1 -1
- package/dist/aptos/hasher.js +1 -1
- package/dist/aptos/hasher.js.map +1 -1
- package/dist/aptos/index.d.ts +43 -15
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +112 -105
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/types.d.ts +2 -19
- package/dist/aptos/types.d.ts.map +1 -1
- package/dist/aptos/types.js +0 -11
- package/dist/aptos/types.js.map +1 -1
- package/dist/chain.d.ts +734 -174
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +216 -31
- package/dist/chain.js.map +1 -1
- package/dist/commits.d.ts +4 -6
- package/dist/commits.d.ts.map +1 -1
- package/dist/commits.js +4 -4
- package/dist/commits.js.map +1 -1
- package/dist/errors/CCIPError.d.ts +33 -4
- package/dist/errors/CCIPError.d.ts.map +1 -1
- package/dist/errors/CCIPError.js +33 -4
- package/dist/errors/CCIPError.js.map +1 -1
- package/dist/errors/codes.d.ts +5 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +5 -1
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +6 -1
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +1702 -121
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +1729 -125
- package/dist/errors/specialized.js.map +1 -1
- package/dist/errors/utils.d.ts.map +1 -1
- package/dist/errors/utils.js +0 -1
- package/dist/errors/utils.js.map +1 -1
- package/dist/evm/abi/OffRamp_2_0.d.ts +764 -0
- package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OffRamp_2_0.js +744 -0
- package/dist/evm/abi/OffRamp_2_0.js.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts +925 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.js +992 -0
- package/dist/evm/abi/OnRamp_2_0.js.map +1 -0
- package/dist/evm/const.d.ts +12 -2
- package/dist/evm/const.d.ts.map +1 -1
- package/dist/evm/const.js +8 -2
- package/dist/evm/const.js.map +1 -1
- package/dist/evm/errors.d.ts.map +1 -1
- package/dist/evm/errors.js +7 -2
- package/dist/evm/errors.js.map +1 -1
- package/dist/evm/extra-args.d.ts +25 -0
- package/dist/evm/extra-args.d.ts.map +1 -0
- package/dist/evm/extra-args.js +309 -0
- package/dist/evm/extra-args.js.map +1 -0
- package/dist/evm/gas.d.ts.map +1 -1
- package/dist/evm/gas.js +7 -12
- package/dist/evm/gas.js.map +1 -1
- package/dist/evm/hasher.d.ts.map +1 -1
- package/dist/evm/hasher.js +23 -13
- package/dist/evm/hasher.js.map +1 -1
- package/dist/evm/index.d.ts +140 -35
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +306 -226
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/messages.d.ts +59 -5
- package/dist/evm/messages.d.ts.map +1 -1
- package/dist/evm/messages.js +210 -0
- package/dist/evm/messages.js.map +1 -1
- package/dist/evm/offchain.js.map +1 -1
- package/dist/evm/types.d.ts +7 -2
- package/dist/evm/types.d.ts.map +1 -1
- package/dist/evm/types.js +22 -1
- package/dist/evm/types.js.map +1 -1
- package/dist/execution.d.ts +62 -22
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +102 -51
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +113 -4
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +38 -3
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +31 -5
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +43 -9
- package/dist/gas.js.map +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/requests.d.ts +101 -22
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +115 -24
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts.map +1 -1
- package/dist/selectors.js +24 -0
- package/dist/selectors.js.map +1 -1
- package/dist/shared/bcs-codecs.d.ts +61 -0
- package/dist/shared/bcs-codecs.d.ts.map +1 -0
- package/dist/shared/bcs-codecs.js +102 -0
- package/dist/shared/bcs-codecs.js.map +1 -0
- package/dist/shared/constants.d.ts +3 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +3 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/solana/exec.d.ts +2 -2
- package/dist/solana/exec.d.ts.map +1 -1
- package/dist/solana/exec.js.map +1 -1
- package/dist/solana/index.d.ts +148 -30
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +137 -44
- package/dist/solana/index.js.map +1 -1
- package/dist/sui/hasher.d.ts.map +1 -1
- package/dist/sui/hasher.js +1 -1
- package/dist/sui/hasher.js.map +1 -1
- package/dist/sui/index.d.ts +49 -19
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +76 -43
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/manuallyExec/encoder.d.ts +2 -2
- package/dist/sui/manuallyExec/encoder.d.ts.map +1 -1
- package/dist/sui/manuallyExec/encoder.js.map +1 -1
- package/dist/sui/manuallyExec/index.d.ts +2 -2
- package/dist/sui/manuallyExec/index.d.ts.map +1 -1
- package/dist/ton/exec.d.ts +2 -2
- package/dist/ton/exec.d.ts.map +1 -1
- package/dist/ton/exec.js.map +1 -1
- package/dist/ton/index.d.ts +66 -27
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +172 -47
- package/dist/ton/index.js.map +1 -1
- package/dist/ton/send.d.ts +52 -0
- package/dist/ton/send.d.ts.map +1 -0
- package/dist/ton/send.js +166 -0
- package/dist/ton/send.js.map +1 -0
- package/dist/ton/types.d.ts +2 -2
- package/dist/ton/types.d.ts.map +1 -1
- package/dist/ton/types.js.map +1 -1
- package/dist/types.d.ts +148 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +79 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +92 -7
- package/dist/utils.js.map +1 -1
- package/package.json +16 -11
- package/src/all-chains.ts +26 -0
- package/src/api/index.ts +58 -34
- package/src/api/types.ts +24 -31
- package/src/aptos/exec.ts +2 -2
- package/src/aptos/hasher.ts +1 -1
- package/src/aptos/index.ts +127 -129
- package/src/aptos/types.ts +2 -15
- package/src/chain.ts +837 -191
- package/src/commits.ts +9 -9
- package/src/errors/CCIPError.ts +33 -4
- package/src/errors/codes.ts +5 -1
- package/src/errors/index.ts +2 -1
- package/src/errors/recovery.ts +9 -1
- package/src/errors/specialized.ts +1745 -132
- package/src/errors/utils.ts +0 -1
- package/src/evm/abi/OffRamp_2_0.ts +743 -0
- package/src/evm/abi/OnRamp_2_0.ts +991 -0
- package/src/evm/const.ts +10 -3
- package/src/evm/errors.ts +6 -2
- package/src/evm/extra-args.ts +360 -0
- package/src/evm/gas.ts +14 -13
- package/src/evm/hasher.ts +30 -18
- package/src/evm/index.ts +376 -281
- package/src/evm/messages.ts +323 -11
- package/src/evm/offchain.ts +2 -2
- package/src/evm/types.ts +20 -2
- package/src/execution.ts +126 -71
- package/src/extra-args.ts +118 -4
- package/src/gas.ts +44 -11
- package/src/index.ts +14 -11
- package/src/requests.ts +128 -24
- package/src/selectors.ts +24 -0
- package/src/shared/bcs-codecs.ts +132 -0
- package/src/shared/constants.ts +2 -0
- package/src/solana/exec.ts +4 -4
- package/src/solana/index.ts +170 -82
- package/src/sui/hasher.ts +1 -1
- package/src/sui/index.ts +88 -56
- package/src/sui/manuallyExec/encoder.ts +2 -2
- package/src/sui/manuallyExec/index.ts +2 -2
- package/src/ton/exec.ts +2 -2
- package/src/ton/index.ts +220 -58
- package/src/ton/send.ts +222 -0
- package/src/ton/types.ts +2 -2
- package/src/types.ts +173 -30
- package/src/utils.ts +91 -7
- package/dist/aptos/utils.d.ts +0 -12
- package/dist/aptos/utils.d.ts.map +0 -1
- package/dist/aptos/utils.js +0 -15
- package/dist/aptos/utils.js.map +0 -1
- package/src/aptos/utils.ts +0 -24
package/src/solana/index.ts
CHANGED
|
@@ -73,14 +73,14 @@ import SELECTORS from '../selectors.ts'
|
|
|
73
73
|
import { supportedChains } from '../supported-chains.ts'
|
|
74
74
|
import {
|
|
75
75
|
type AnyMessage,
|
|
76
|
-
type CCIPCommit,
|
|
77
76
|
type CCIPExecution,
|
|
78
77
|
type CCIPMessage,
|
|
79
78
|
type CCIPRequest,
|
|
79
|
+
type CCIPVerifications,
|
|
80
80
|
type ChainTransaction,
|
|
81
81
|
type CommitReport,
|
|
82
|
+
type ExecutionInput,
|
|
82
83
|
type ExecutionReceipt,
|
|
83
|
-
type ExecutionReport,
|
|
84
84
|
type Lane,
|
|
85
85
|
type Log_,
|
|
86
86
|
type MergeArrayElements,
|
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
createRateLimitedFetch,
|
|
97
97
|
decodeAddress,
|
|
98
98
|
decodeOnRampAddress,
|
|
99
|
+
getAddressBytes,
|
|
99
100
|
getDataBytes,
|
|
100
101
|
leToBigInt,
|
|
101
102
|
networkInfo,
|
|
@@ -126,7 +127,7 @@ import {
|
|
|
126
127
|
} from './utils.ts'
|
|
127
128
|
import { buildMessageForDest, getMessagesInBatch } from '../requests.ts'
|
|
128
129
|
import { patchBorsh } from './patchBorsh.ts'
|
|
129
|
-
import { DEFAULT_GAS_LIMIT } from '../
|
|
130
|
+
import { DEFAULT_GAS_LIMIT } from '../shared/constants.ts'
|
|
130
131
|
export type { UnsignedSolanaTx }
|
|
131
132
|
|
|
132
133
|
const routerCoder = new BorshCoder(CCIP_ROUTER_IDL)
|
|
@@ -171,6 +172,29 @@ export type SolanaTransaction = MergeArrayElements<
|
|
|
171
172
|
|
|
172
173
|
/**
|
|
173
174
|
* Solana chain implementation supporting Solana networks.
|
|
175
|
+
*
|
|
176
|
+
* Provides methods for sending CCIP cross-chain messages, querying message
|
|
177
|
+
* status, fetching fee quotes, and manually executing pending messages on
|
|
178
|
+
* Solana networks.
|
|
179
|
+
*
|
|
180
|
+
* @remarks
|
|
181
|
+
* Solana uses CCIP v1.6+ protocol only.
|
|
182
|
+
*
|
|
183
|
+
* @example Create from RPC URL
|
|
184
|
+
* ```typescript
|
|
185
|
+
* import { SolanaChain } from '@chainlink/ccip-sdk'
|
|
186
|
+
*
|
|
187
|
+
* const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
|
|
188
|
+
* console.log(`Connected to: ${chain.network.name}`)
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @example Query messages in a transaction
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const requests = await chain.getMessagesInTx('5abc123...')
|
|
194
|
+
* for (const req of requests) {
|
|
195
|
+
* console.log(`Message ID: ${req.message.messageId}`)
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
174
198
|
*/
|
|
175
199
|
export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
176
200
|
static {
|
|
@@ -252,6 +276,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
252
276
|
* @param url - RPC endpoint URL (https://, http://, wss://, or ws://).
|
|
253
277
|
* @param ctx - context containing logger.
|
|
254
278
|
* @returns Solana Connection instance.
|
|
279
|
+
* @throws {@link CCIPDataFormatUnsupportedError} if URL format is invalid
|
|
255
280
|
*/
|
|
256
281
|
static _getConnection(url: string, ctx?: WithLogger): Connection {
|
|
257
282
|
const { logger = console } = ctx ?? {}
|
|
@@ -283,9 +308,20 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
283
308
|
|
|
284
309
|
/**
|
|
285
310
|
* Creates a SolanaChain instance from an RPC URL.
|
|
286
|
-
*
|
|
287
|
-
* @param
|
|
288
|
-
* @
|
|
311
|
+
*
|
|
312
|
+
* @param url - RPC endpoint URL (https://, http://, wss://, or ws://).
|
|
313
|
+
* @param ctx - Optional context containing logger and API client configuration.
|
|
314
|
+
* @returns A new SolanaChain instance connected to the specified network.
|
|
315
|
+
* @throws {@link CCIPChainNotFoundError} if chain cannot be identified from genesis hash
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```typescript
|
|
319
|
+
* // Create from devnet URL
|
|
320
|
+
* const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
|
|
321
|
+
*
|
|
322
|
+
* // With custom logger
|
|
323
|
+
* const chain = await SolanaChain.fromUrl(url, { logger: customLogger })
|
|
324
|
+
* ```
|
|
289
325
|
*/
|
|
290
326
|
static async fromUrl(url: string, ctx?: ChainContext): Promise<SolanaChain> {
|
|
291
327
|
const connection = this._getConnection(url, ctx)
|
|
@@ -293,7 +329,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
293
329
|
}
|
|
294
330
|
|
|
295
331
|
// cached
|
|
296
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* {@inheritDoc Chain.getBlockTimestamp}
|
|
334
|
+
* @throws {@link CCIPBlockTimeNotFoundError} if block time cannot be retrieved
|
|
335
|
+
*/
|
|
297
336
|
async getBlockTimestamp(block: number | 'latest' | 'finalized'): Promise<number> {
|
|
298
337
|
if (typeof block !== 'number') {
|
|
299
338
|
const slot = await this.connection.getSlot(block === 'latest' ? 'confirmed' : block)
|
|
@@ -313,7 +352,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
313
352
|
return blockTime
|
|
314
353
|
}
|
|
315
354
|
|
|
316
|
-
/**
|
|
355
|
+
/**
|
|
356
|
+
* {@inheritDoc Chain.getTransaction}
|
|
357
|
+
* @throws {@link CCIPTransactionNotFoundError} if transaction not found
|
|
358
|
+
*/
|
|
317
359
|
async getTransaction(hash: string): Promise<SolanaTransaction> {
|
|
318
360
|
const tx = await this.connection.getTransaction(hash, {
|
|
319
361
|
commitment: 'confirmed',
|
|
@@ -389,6 +431,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
389
431
|
* - `programs`: Special option to allow querying by address of interest, but yielding matching
|
|
390
432
|
* logs from specific (string address) program or any (true)
|
|
391
433
|
* @returns AsyncIterableIterator of parsed Log_ objects.
|
|
434
|
+
* @throws {@link CCIPLogsAddressRequiredError} if address is not provided
|
|
435
|
+
* @throws {@link CCIPTopicsInvalidError} if topics contain invalid values
|
|
392
436
|
*/
|
|
393
437
|
async *getLogs(
|
|
394
438
|
opts: LogFilter & { programs?: string[] | true },
|
|
@@ -433,15 +477,15 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
433
477
|
}
|
|
434
478
|
|
|
435
479
|
/** {@inheritDoc Chain.getMessagesInBatch} */
|
|
436
|
-
async getMessagesInBatch<
|
|
480
|
+
override async getMessagesInBatch<
|
|
437
481
|
R extends PickDeep<
|
|
438
482
|
CCIPRequest,
|
|
439
483
|
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.sequenceNumber'
|
|
440
484
|
>,
|
|
441
485
|
>(
|
|
442
486
|
request: R,
|
|
443
|
-
|
|
444
|
-
opts?:
|
|
487
|
+
range: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
|
|
488
|
+
opts?: Pick<LogFilter, 'page'>,
|
|
445
489
|
): Promise<R['message'][]> {
|
|
446
490
|
const [destChainStatePda] = PublicKey.findProgramAddressSync(
|
|
447
491
|
[Buffer.from('dest_chain_state'), toLeArray(request.lane.destChainSelector, 8)],
|
|
@@ -454,7 +498,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
454
498
|
programs: [request.log.address],
|
|
455
499
|
address: destChainStatePda.toBase58(),
|
|
456
500
|
}
|
|
457
|
-
return getMessagesInBatch(this, request,
|
|
501
|
+
return getMessagesInBatch(this, request, range, opts_)
|
|
458
502
|
}
|
|
459
503
|
|
|
460
504
|
/** {@inheritDoc Chain.typeAndVersion} */
|
|
@@ -480,7 +524,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
480
524
|
return Promise.resolve(onRamp) // Solana's router is also the onRamp
|
|
481
525
|
}
|
|
482
526
|
|
|
483
|
-
/**
|
|
527
|
+
/**
|
|
528
|
+
* {@inheritDoc Chain.getRouterForOffRamp}
|
|
529
|
+
* @throws {@link CCIPSolanaRefAddressesNotFoundError} if reference addresses PDA not found
|
|
530
|
+
*/
|
|
484
531
|
async getRouterForOffRamp(offRamp: string, _sourceChainSelector: bigint): Promise<string> {
|
|
485
532
|
const offRamp_ = new PublicKey(offRamp)
|
|
486
533
|
const program = new Program(CCIP_OFFRAMP_IDL as Idl, offRamp_, {
|
|
@@ -507,7 +554,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
507
554
|
return Promise.resolve(NATIVE_MINT.toBase58())
|
|
508
555
|
}
|
|
509
556
|
|
|
510
|
-
/**
|
|
557
|
+
/**
|
|
558
|
+
* {@inheritDoc Chain.getOffRampsForRouter}
|
|
559
|
+
* @throws {@link CCIPSolanaOffRampEventsNotFoundError} if no OffRamp events found
|
|
560
|
+
*/
|
|
511
561
|
async getOffRampsForRouter(router: string, sourceChainSelector: bigint): Promise<string[]> {
|
|
512
562
|
// feeQuoter is present in router's config, and has a DestChainState account which is updated by
|
|
513
563
|
// the offramps, so we can use it to narrow the search for the offramp
|
|
@@ -533,8 +583,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
533
583
|
return Promise.resolve(router) // solana's Router is also the OnRamp
|
|
534
584
|
}
|
|
535
585
|
|
|
536
|
-
/** {@inheritDoc Chain.
|
|
537
|
-
async
|
|
586
|
+
/** {@inheritDoc Chain.getOnRampsForOffRamp} */
|
|
587
|
+
async getOnRampsForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string[]> {
|
|
538
588
|
const program = new Program(CCIP_OFFRAMP_IDL, new PublicKey(offRamp), {
|
|
539
589
|
connection: this.connection,
|
|
540
590
|
})
|
|
@@ -548,18 +598,18 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
548
598
|
const {
|
|
549
599
|
config: { onRamp },
|
|
550
600
|
} = await program.account.sourceChain.fetch(statePda)
|
|
551
|
-
return
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
/** {@inheritDoc Chain.getCommitStoreForOffRamp} */
|
|
558
|
-
getCommitStoreForOffRamp(offRamp: string): Promise<string> {
|
|
559
|
-
return Promise.resolve(offRamp) // Solana supports only CCIP>=1.6, for which OffRamp and CommitStore are the same
|
|
601
|
+
return [
|
|
602
|
+
decodeAddress(
|
|
603
|
+
getAddressBytes(onRamp.bytes).subarray(0, onRamp.len),
|
|
604
|
+
networkInfo(sourceChainSelector).family,
|
|
605
|
+
),
|
|
606
|
+
]
|
|
560
607
|
}
|
|
561
608
|
|
|
562
|
-
/**
|
|
609
|
+
/**
|
|
610
|
+
* {@inheritDoc Chain.getTokenForTokenPool}
|
|
611
|
+
* @throws {@link CCIPTokenPoolInfoNotFoundError} if token pool info not found
|
|
612
|
+
*/
|
|
563
613
|
async getTokenForTokenPool(tokenPool: string): Promise<string> {
|
|
564
614
|
const tokenPoolInfo = await this.connection.getAccountInfo(new PublicKey(tokenPool))
|
|
565
615
|
if (!tokenPoolInfo) throw new CCIPTokenPoolInfoNotFoundError(tokenPool)
|
|
@@ -570,7 +620,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
570
620
|
return config.mint.toString()
|
|
571
621
|
}
|
|
572
622
|
|
|
573
|
-
/**
|
|
623
|
+
/**
|
|
624
|
+
* {@inheritDoc Chain.getTokenInfo}
|
|
625
|
+
* @throws {@link CCIPSplTokenInvalidError} if token is not a valid SPL token
|
|
626
|
+
* @throws {@link CCIPTokenDataParseError} if token data cannot be parsed
|
|
627
|
+
*/
|
|
574
628
|
async getTokenInfo(token: string): Promise<TokenInfo> {
|
|
575
629
|
const mint = new PublicKey(token)
|
|
576
630
|
const mintInfo = await this.connection.getParsedAccountInfo(mint)
|
|
@@ -619,7 +673,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
619
673
|
}
|
|
620
674
|
}
|
|
621
675
|
|
|
622
|
-
/**
|
|
676
|
+
/**
|
|
677
|
+
* {@inheritDoc Chain.getBalance}
|
|
678
|
+
* @throws {@link CCIPTokenAccountNotFoundError} if token account not found
|
|
679
|
+
*/
|
|
623
680
|
async getBalance(opts: GetBalanceOpts): Promise<bigint> {
|
|
624
681
|
const { holder, token } = opts
|
|
625
682
|
const holderPubkey = new PublicKey(holder)
|
|
@@ -712,6 +769,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
712
769
|
* Decodes a CCIP message from a Solana log event.
|
|
713
770
|
* @param log - Log with data field.
|
|
714
771
|
* @returns Decoded CCIPMessage or undefined if not valid.
|
|
772
|
+
* @throws {@link CCIPExtraArgsInvalidError} if extra args cannot be decoded
|
|
715
773
|
*/
|
|
716
774
|
static decodeMessage({ data }: { data: unknown }): CCIPMessage | undefined {
|
|
717
775
|
if (!data || typeof data !== 'string') return undefined
|
|
@@ -789,6 +847,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
789
847
|
* Decodes extra arguments from Solana CCIP messages.
|
|
790
848
|
* @param extraArgs - Encoded extra arguments bytes.
|
|
791
849
|
* @returns Decoded EVMExtraArgsV2 or undefined if unknown format.
|
|
850
|
+
* @throws {@link CCIPExtraArgsLengthInvalidError} if extra args length is invalid
|
|
792
851
|
*/
|
|
793
852
|
static decodeExtraArgs(
|
|
794
853
|
extraArgs: BytesLike,
|
|
@@ -816,6 +875,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
816
875
|
* Encodes extra arguments for Solana CCIP messages.
|
|
817
876
|
* @param args - Extra arguments to encode.
|
|
818
877
|
* @returns Encoded extra arguments as hex string.
|
|
878
|
+
* @throws {@link CCIPSolanaExtraArgsEncodingError} if SVMExtraArgsV1 encoding is attempted
|
|
819
879
|
*/
|
|
820
880
|
static encodeExtraArgs(args: ExtraArgs): string {
|
|
821
881
|
if ('computeUnits' in args) throw new CCIPSolanaExtraArgsEncodingError()
|
|
@@ -832,6 +892,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
832
892
|
* @param log - Log with data field.
|
|
833
893
|
* @param lane - Lane info for filtering.
|
|
834
894
|
* @returns Array of CommitReport or undefined if not valid.
|
|
895
|
+
* @throws {@link CCIPLogDataMissingError} if log data is missing
|
|
835
896
|
*/
|
|
836
897
|
static decodeCommits(
|
|
837
898
|
log: Pick<Log_, 'data'>,
|
|
@@ -886,6 +947,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
886
947
|
* Decodes an execution receipt from a Solana log event.
|
|
887
948
|
* @param log - Log with data, tx, and index fields.
|
|
888
949
|
* @returns ExecutionReceipt or undefined if not valid.
|
|
950
|
+
* @throws {@link CCIPLogDataMissingError} if log data is missing
|
|
951
|
+
* @throws {@link CCIPExecutionStateInvalidError} if execution state is invalid
|
|
889
952
|
*/
|
|
890
953
|
static decodeReceipt(log: Pick<Log_, 'data' | 'tx' | 'index'>): ExecutionReceipt | undefined {
|
|
891
954
|
// Check if this is a ExecutionStateChanged event by looking at the discriminant
|
|
@@ -984,7 +1047,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
984
1047
|
return getV16SolanaLeafHasher(lane, ctx)
|
|
985
1048
|
}
|
|
986
1049
|
|
|
987
|
-
/**
|
|
1050
|
+
/**
|
|
1051
|
+
* {@inheritDoc Chain.getTokenAdminRegistryFor}
|
|
1052
|
+
* @throws {@link CCIPContractNotRouterError} if address is not a Router
|
|
1053
|
+
*/
|
|
988
1054
|
async getTokenAdminRegistryFor(address: string): Promise<string> {
|
|
989
1055
|
const [type] = await this.typeAndVersion(address)
|
|
990
1056
|
if (!type.includes('Router')) throw new CCIPContractNotRouterError(address, type)
|
|
@@ -1026,7 +1092,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1026
1092
|
)
|
|
1027
1093
|
}
|
|
1028
1094
|
|
|
1029
|
-
/**
|
|
1095
|
+
/**
|
|
1096
|
+
* {@inheritDoc Chain.sendMessage}
|
|
1097
|
+
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
|
|
1098
|
+
*/
|
|
1030
1099
|
async sendMessage(opts: Parameters<Chain['sendMessage']>[0]): Promise<CCIPRequest> {
|
|
1031
1100
|
if (!isWallet(opts.wallet)) throw new CCIPWalletInvalidError(util.inspect(opts.wallet))
|
|
1032
1101
|
const unsigned = await this.generateUnsignedSendMessage({
|
|
@@ -1044,22 +1113,22 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1044
1113
|
}
|
|
1045
1114
|
|
|
1046
1115
|
/**
|
|
1047
|
-
* {@inheritDoc Chain.
|
|
1116
|
+
* {@inheritDoc Chain.generateUnsignedExecute}
|
|
1048
1117
|
* @returns instructions - array of instructions to execute the report
|
|
1049
1118
|
* lookupTables - array of lookup tables for `manuallyExecute` call
|
|
1050
1119
|
* mainIndex - index of the `manuallyExecute` instruction in the array; last unless
|
|
1051
1120
|
* forceLookupTable is set, in which case last is ALT deactivation tx, and manuallyExecute is
|
|
1052
1121
|
* second to last
|
|
1122
|
+
* @throws {@link CCIPExecutionReportChainMismatchError} if message is not a Solana message
|
|
1053
1123
|
*/
|
|
1054
|
-
async
|
|
1124
|
+
async generateUnsignedExecute({
|
|
1055
1125
|
payer,
|
|
1056
|
-
offRamp,
|
|
1057
|
-
execReport,
|
|
1058
1126
|
...opts
|
|
1059
|
-
}: Parameters<Chain['
|
|
1060
|
-
if (!('computeUnits' in
|
|
1127
|
+
}: Parameters<Chain['generateUnsignedExecute']>[0]): Promise<UnsignedSolanaTx> {
|
|
1128
|
+
if (!('input' in opts) || !('message' in opts.input) || !('computeUnits' in opts.input.message))
|
|
1061
1129
|
throw new CCIPExecutionReportChainMismatchError('Solana')
|
|
1062
|
-
const
|
|
1130
|
+
const { offRamp, input } = opts
|
|
1131
|
+
const execReport_ = input as ExecutionInput<CCIPMessage_V1_6_Solana>
|
|
1063
1132
|
return generateUnsignedExecuteReport(
|
|
1064
1133
|
this,
|
|
1065
1134
|
new PublicKey(payer),
|
|
@@ -1069,9 +1138,12 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1069
1138
|
)
|
|
1070
1139
|
}
|
|
1071
1140
|
|
|
1072
|
-
/**
|
|
1073
|
-
|
|
1074
|
-
|
|
1141
|
+
/**
|
|
1142
|
+
* {@inheritDoc Chain.execute}
|
|
1143
|
+
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
|
|
1144
|
+
*/
|
|
1145
|
+
async execute(
|
|
1146
|
+
opts: Parameters<Chain['execute']>[0] & {
|
|
1075
1147
|
// when cleaning leftover LookUp Tables, wait deactivation grace period (~513 slots) then close ALT
|
|
1076
1148
|
waitDeactivation?: boolean
|
|
1077
1149
|
},
|
|
@@ -1082,7 +1154,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1082
1154
|
let hash
|
|
1083
1155
|
do {
|
|
1084
1156
|
try {
|
|
1085
|
-
const unsigned = await this.
|
|
1157
|
+
const unsigned = await this.generateUnsignedExecute({
|
|
1086
1158
|
...opts,
|
|
1087
1159
|
payer: wallet.publicKey.toBase58(),
|
|
1088
1160
|
})
|
|
@@ -1118,6 +1190,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1118
1190
|
* - waitDeactivation - Whether to wait for lookup table deactivation cool down period
|
|
1119
1191
|
* (513 slots) to pass before closing; by default, we deactivate (if needed) and move on, to
|
|
1120
1192
|
* close other ready ALTs
|
|
1193
|
+
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
|
|
1121
1194
|
*/
|
|
1122
1195
|
async cleanUpBuffers(opts: { wallet: unknown; waitDeactivation?: boolean }): Promise<void> {
|
|
1123
1196
|
const wallet = opts.wallet
|
|
@@ -1157,39 +1230,36 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1157
1230
|
/**
|
|
1158
1231
|
* Solana specialization: use getProgramAccounts to fetch commit reports from PDAs
|
|
1159
1232
|
*/
|
|
1160
|
-
override async
|
|
1161
|
-
opts: Parameters<Chain['
|
|
1162
|
-
): Promise<
|
|
1163
|
-
const {
|
|
1164
|
-
const commitsAroundSeqNum = await this.connection.getProgramAccounts(
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
{
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
offset: 0,
|
|
1172
|
-
bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
|
|
1173
|
-
},
|
|
1233
|
+
override async getVerifications(
|
|
1234
|
+
opts: Parameters<Chain['getVerifications']>[0],
|
|
1235
|
+
): Promise<CCIPVerifications> {
|
|
1236
|
+
const { offRamp, request } = opts
|
|
1237
|
+
const commitsAroundSeqNum = await this.connection.getProgramAccounts(new PublicKey(offRamp), {
|
|
1238
|
+
filters: [
|
|
1239
|
+
{
|
|
1240
|
+
// commit report account discriminator filter
|
|
1241
|
+
memcmp: {
|
|
1242
|
+
offset: 0,
|
|
1243
|
+
bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
|
|
1174
1244
|
},
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
// sourceChainSelector filter
|
|
1248
|
+
memcmp: {
|
|
1249
|
+
offset: 8 + 1,
|
|
1250
|
+
bytes: encodeBase58(toLeArray(request.lane.sourceChainSelector, 8)),
|
|
1181
1251
|
},
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1252
|
+
},
|
|
1253
|
+
// memcmp report.min with msg.sequenceNumber's without least-significant byte;
|
|
1254
|
+
// this should be ~256 around seqNum, i.e. big chance of a match; requires PDAs not to have been closed
|
|
1255
|
+
{
|
|
1256
|
+
memcmp: {
|
|
1257
|
+
offset: 8 + 1 + 8 + 32 + 8 + /*skip byte*/ 1,
|
|
1258
|
+
bytes: encodeBase58(toLeArray(request.message.sequenceNumber, 8).slice(1)),
|
|
1189
1259
|
},
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
)
|
|
1260
|
+
},
|
|
1261
|
+
],
|
|
1262
|
+
})
|
|
1193
1263
|
for (const acc of commitsAroundSeqNum) {
|
|
1194
1264
|
// const merkleRoot = acc.account.data.subarray(8 + 1 + 8, 8 + 1 + 8 + 32)
|
|
1195
1265
|
const minSeqNr = acc.account.data.readBigUInt64LE(8 + 1 + 8 + 32 + 8)
|
|
@@ -1199,7 +1269,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1199
1269
|
// we have all the commit report info, but we also need log details (txHash, etc)
|
|
1200
1270
|
for await (const log of this.getLogs({
|
|
1201
1271
|
startTime: 1, // just to force getting the oldest log first
|
|
1202
|
-
programs: [
|
|
1272
|
+
programs: [offRamp],
|
|
1203
1273
|
address: acc.pubkey.toBase58(),
|
|
1204
1274
|
topics: ['CommitReportAccepted'],
|
|
1205
1275
|
})) {
|
|
@@ -1212,23 +1282,23 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1212
1282
|
}
|
|
1213
1283
|
}
|
|
1214
1284
|
// in case we can't find it, fallback to generic iterating txs
|
|
1215
|
-
return super.
|
|
1285
|
+
return super.getVerifications(opts)
|
|
1216
1286
|
}
|
|
1217
1287
|
|
|
1218
1288
|
/** {@inheritDoc Chain.getExecutionReceipts} */
|
|
1219
1289
|
override async *getExecutionReceipts(
|
|
1220
1290
|
opts: Parameters<Chain['getExecutionReceipts']>[0],
|
|
1221
1291
|
): AsyncIterableIterator<CCIPExecution> {
|
|
1222
|
-
const { offRamp, sourceChainSelector,
|
|
1292
|
+
const { offRamp, sourceChainSelector, verifications } = opts
|
|
1223
1293
|
let opts_: Parameters<Chain['getExecutionReceipts']>[0] &
|
|
1224
1294
|
Parameters<SolanaChain['getLogs']>[0] = opts
|
|
1225
|
-
if (
|
|
1295
|
+
if (sourceChainSelector && verifications && 'report' in verifications) {
|
|
1226
1296
|
// if we know of commit, use `commit_report` PDA as more specialized address
|
|
1227
1297
|
const [commitReportPda] = PublicKey.findProgramAddressSync(
|
|
1228
1298
|
[
|
|
1229
1299
|
Buffer.from('commit_report'),
|
|
1230
1300
|
toLeArray(sourceChainSelector, 8),
|
|
1231
|
-
bytesToBuffer(
|
|
1301
|
+
bytesToBuffer(verifications.report.merkleRoot),
|
|
1232
1302
|
],
|
|
1233
1303
|
new PublicKey(offRamp),
|
|
1234
1304
|
)
|
|
@@ -1241,7 +1311,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1241
1311
|
yield* super.getExecutionReceipts(opts_)
|
|
1242
1312
|
}
|
|
1243
1313
|
|
|
1244
|
-
/**
|
|
1314
|
+
/**
|
|
1315
|
+
* {@inheritDoc Chain.getRegistryTokenConfig}
|
|
1316
|
+
* @throws {@link CCIPTokenNotConfiguredError} if token is not configured in registry
|
|
1317
|
+
*/
|
|
1245
1318
|
async getRegistryTokenConfig(
|
|
1246
1319
|
registry: string,
|
|
1247
1320
|
token: string,
|
|
@@ -1295,8 +1368,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1295
1368
|
return config
|
|
1296
1369
|
}
|
|
1297
1370
|
|
|
1298
|
-
/**
|
|
1299
|
-
|
|
1371
|
+
/**
|
|
1372
|
+
* {@inheritDoc Chain.getTokenPoolConfig}
|
|
1373
|
+
* @throws {@link CCIPTokenPoolStateNotFoundError} if token pool state not found
|
|
1374
|
+
*/
|
|
1375
|
+
async getTokenPoolConfig(tokenPool: string): Promise<{
|
|
1300
1376
|
token: string
|
|
1301
1377
|
router: string
|
|
1302
1378
|
tokenPoolProgram: string
|
|
@@ -1328,7 +1404,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1328
1404
|
}
|
|
1329
1405
|
}
|
|
1330
1406
|
|
|
1331
|
-
/**
|
|
1407
|
+
/**
|
|
1408
|
+
* {@inheritDoc Chain.getTokenPoolRemotes}
|
|
1409
|
+
* @throws {@link CCIPTokenPoolStateNotFoundError} if token pool state not found
|
|
1410
|
+
* @throws {@link CCIPTokenPoolChainConfigNotFoundError} if chain config not found for specified selector
|
|
1411
|
+
*/
|
|
1332
1412
|
async getTokenPoolRemotes(
|
|
1333
1413
|
tokenPool: string,
|
|
1334
1414
|
remoteChainSelector?: bigint,
|
|
@@ -1506,7 +1586,14 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1506
1586
|
return program.account.config.fetch(configPda)
|
|
1507
1587
|
}
|
|
1508
1588
|
|
|
1509
|
-
/**
|
|
1589
|
+
/**
|
|
1590
|
+
* Returns a copy of a message, populating missing fields like `extraArgs` with defaults.
|
|
1591
|
+
* It's expected to return a message suitable at least for basic token transfers.
|
|
1592
|
+
*
|
|
1593
|
+
* @param message - AnyMessage (from source), containing at least `receiver`
|
|
1594
|
+
* @returns A message suitable for `sendMessage` to this destination chain family
|
|
1595
|
+
* @throws {@link CCIPArgumentInvalidError} if tokenReceiver missing when sending tokens with data
|
|
1596
|
+
*/
|
|
1510
1597
|
static override buildMessageForDest(
|
|
1511
1598
|
message: Parameters<ChainStatic['buildMessageForDest']>[0],
|
|
1512
1599
|
): AnyMessage & { extraArgs: SVMExtraArgsV1 } {
|
|
@@ -1544,7 +1631,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1544
1631
|
const tokenReceiver =
|
|
1545
1632
|
message.extraArgs &&
|
|
1546
1633
|
'tokenReceiver' in message.extraArgs &&
|
|
1547
|
-
message.extraArgs.tokenReceiver != null
|
|
1634
|
+
message.extraArgs.tokenReceiver != null &&
|
|
1635
|
+
typeof message.extraArgs.tokenReceiver === 'string'
|
|
1548
1636
|
? message.extraArgs.tokenReceiver
|
|
1549
1637
|
: message.tokenAmounts?.length
|
|
1550
1638
|
? this.getAddress(message.receiver)
|
package/src/sui/hasher.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { concat, id, keccak256, zeroPadValue } from 'ethers'
|
|
2
2
|
|
|
3
|
-
import { encodeNumber, encodeRawBytes } from '../aptos/utils.ts'
|
|
4
3
|
import { CCIPExtraArgsInvalidError, CCIPSuiHasherVersionUnsupportedError } from '../errors/index.ts'
|
|
5
4
|
import { decodeExtraArgs } from '../extra-args.ts'
|
|
6
5
|
import { type LeafHasher, LEAF_DOMAIN_SEPARATOR } from '../hasher/common.ts'
|
|
7
6
|
import { type CCIPMessage, type CCIPMessage_V1_6, CCIPVersion } from '../types.ts'
|
|
8
7
|
import type { CCIPMessage_V1_6_Sui } from './types.ts'
|
|
8
|
+
import { encodeNumber, encodeRawBytes } from '../shared/bcs-codecs.ts'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Creates a leaf hasher for Sui CCIP messages.
|