@chainlink/ccip-sdk 0.96.0 → 1.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.
- package/README.md +12 -9
- package/dist/api/index.d.ts +21 -8
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +42 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +0 -2
- 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 +17 -16
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +42 -73
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/logs.d.ts +2 -2
- package/dist/aptos/logs.d.ts.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 +538 -158
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +132 -19
- 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 +3 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +3 -1
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +4 -4
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +4 -1
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +1695 -120
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +1715 -123
- 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.map +1 -1
- package/dist/evm/extra-args.js +5 -24
- package/dist/evm/extra-args.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 +73 -16
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +241 -146
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/logs.d.ts +1 -1
- package/dist/evm/logs.js +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.d.ts +1 -14
- package/dist/evm/offchain.d.ts.map +1 -1
- package/dist/evm/offchain.js +1 -133
- 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 +98 -61
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +13 -3
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +13 -3
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +25 -2
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +30 -4
- package/dist/gas.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/offchain.d.ts +23 -6
- package/dist/offchain.d.ts.map +1 -1
- package/dist/offchain.js +92 -17
- package/dist/offchain.js.map +1 -1
- package/dist/requests.d.ts +85 -14
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +99 -17
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts.map +1 -1
- package/dist/selectors.js +12 -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/idl/1.6.0/BASE_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.js +1 -1
- package/dist/solana/index.d.ts +85 -24
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +69 -37
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/offchain.d.ts +1 -13
- package/dist/solana/offchain.d.ts.map +1 -1
- package/dist/solana/offchain.js +1 -66
- package/dist/solana/offchain.js.map +1 -1
- package/dist/solana/utils.d.ts +4 -4
- package/dist/solana/utils.d.ts.map +1 -1
- package/dist/solana/utils.js +1 -1
- package/dist/solana/utils.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 +18 -18
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +38 -39
- 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 +3 -3
- package/dist/ton/exec.d.ts.map +1 -1
- package/dist/ton/exec.js +1 -1
- package/dist/ton/exec.js.map +1 -1
- package/dist/ton/index.d.ts +14 -22
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +26 -35
- package/dist/ton/index.js.map +1 -1
- package/dist/ton/types.d.ts +3 -5
- package/dist/ton/types.d.ts.map +1 -1
- package/dist/ton/types.js.map +1 -1
- package/dist/types.d.ts +55 -20
- 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 +65 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +74 -2
- package/dist/utils.js.map +1 -1
- package/package.json +14 -10
- package/src/api/index.ts +53 -17
- package/src/api/types.ts +0 -2
- package/src/aptos/exec.ts +2 -2
- package/src/aptos/hasher.ts +1 -1
- package/src/aptos/index.ts +55 -100
- package/src/aptos/logs.ts +2 -2
- package/src/aptos/types.ts +2 -15
- package/src/chain.ts +594 -171
- package/src/commits.ts +9 -9
- package/src/errors/CCIPError.ts +33 -4
- package/src/errors/codes.ts +3 -1
- package/src/errors/index.ts +4 -0
- package/src/errors/recovery.ts +7 -1
- package/src/errors/specialized.ts +1726 -130
- 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 +4 -21
- package/src/evm/hasher.ts +30 -18
- package/src/evm/index.ts +314 -176
- package/src/evm/logs.ts +1 -1
- package/src/evm/messages.ts +323 -11
- package/src/evm/offchain.ts +2 -191
- package/src/evm/types.ts +20 -2
- package/src/execution.ts +125 -86
- package/src/extra-args.ts +13 -3
- package/src/gas.ts +29 -3
- package/src/index.ts +10 -3
- package/src/offchain.ts +125 -28
- package/src/requests.ts +114 -19
- package/src/selectors.ts +12 -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/idl/1.6.0/BASE_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_COMMON.ts +32 -2
- package/src/solana/idl/1.6.0/CCIP_OFFRAMP.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_ROUTER.ts +2 -2
- package/src/solana/index.ts +110 -85
- package/src/solana/offchain.ts +3 -100
- package/src/solana/utils.ts +8 -5
- package/src/sui/hasher.ts +1 -1
- package/src/sui/index.ts +55 -59
- package/src/sui/manuallyExec/encoder.ts +2 -2
- package/src/sui/manuallyExec/index.ts +2 -2
- package/src/ton/exec.ts +4 -7
- package/src/ton/index.ts +45 -53
- package/src/ton/types.ts +4 -7
- package/src/types.ts +81 -37
- package/src/utils.ts +73 -2
- 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,19 +73,18 @@ 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
|
+
type ChainLog,
|
|
80
81
|
type ChainTransaction,
|
|
81
82
|
type CommitReport,
|
|
83
|
+
type ExecutionInput,
|
|
82
84
|
type ExecutionReceipt,
|
|
83
|
-
type ExecutionReport,
|
|
84
85
|
type Lane,
|
|
85
|
-
type Log_,
|
|
86
86
|
type MergeArrayElements,
|
|
87
87
|
type NetworkInfo,
|
|
88
|
-
type OffchainTokenData,
|
|
89
88
|
type WithLogger,
|
|
90
89
|
CCIPVersion,
|
|
91
90
|
ChainFamily,
|
|
@@ -96,6 +95,7 @@ import {
|
|
|
96
95
|
createRateLimitedFetch,
|
|
97
96
|
decodeAddress,
|
|
98
97
|
decodeOnRampAddress,
|
|
98
|
+
getAddressBytes,
|
|
99
99
|
getDataBytes,
|
|
100
100
|
leToBigInt,
|
|
101
101
|
networkInfo,
|
|
@@ -112,7 +112,6 @@ import { IDL as CCIP_CCTP_TOKEN_POOL } from './idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts
|
|
|
112
112
|
import { IDL as CCIP_OFFRAMP_IDL } from './idl/1.6.0/CCIP_OFFRAMP.ts'
|
|
113
113
|
import { IDL as CCIP_ROUTER_IDL } from './idl/1.6.0/CCIP_ROUTER.ts'
|
|
114
114
|
import { getTransactionsForAddress } from './logs.ts'
|
|
115
|
-
import { fetchSolanaOffchainTokenData } from './offchain.ts'
|
|
116
115
|
import { generateUnsignedCcipSend, getFee } from './send.ts'
|
|
117
116
|
import { type CCIPMessage_V1_6_Solana, type UnsignedSolanaTx, isWallet } from './types.ts'
|
|
118
117
|
import {
|
|
@@ -126,7 +125,7 @@ import {
|
|
|
126
125
|
} from './utils.ts'
|
|
127
126
|
import { buildMessageForDest, getMessagesInBatch } from '../requests.ts'
|
|
128
127
|
import { patchBorsh } from './patchBorsh.ts'
|
|
129
|
-
import { DEFAULT_GAS_LIMIT } from '../
|
|
128
|
+
import { DEFAULT_GAS_LIMIT } from '../shared/constants.ts'
|
|
130
129
|
export type { UnsignedSolanaTx }
|
|
131
130
|
|
|
132
131
|
const routerCoder = new BorshCoder(CCIP_ROUTER_IDL)
|
|
@@ -159,7 +158,7 @@ const unknownTokens: { [mint: string]: string } = {
|
|
|
159
158
|
}
|
|
160
159
|
|
|
161
160
|
/** Solana-specific log structure with transaction reference and log level. */
|
|
162
|
-
export type SolanaLog =
|
|
161
|
+
export type SolanaLog = ChainLog & { tx: SolanaTransaction; data: string; level: number }
|
|
163
162
|
/** Solana-specific transaction structure with versioned transaction response. */
|
|
164
163
|
export type SolanaTransaction = MergeArrayElements<
|
|
165
164
|
ChainTransaction,
|
|
@@ -171,6 +170,29 @@ export type SolanaTransaction = MergeArrayElements<
|
|
|
171
170
|
|
|
172
171
|
/**
|
|
173
172
|
* Solana chain implementation supporting Solana networks.
|
|
173
|
+
*
|
|
174
|
+
* Provides methods for sending CCIP cross-chain messages, querying message
|
|
175
|
+
* status, fetching fee quotes, and manually executing pending messages on
|
|
176
|
+
* Solana networks.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* Solana uses CCIP v1.6+ protocol only.
|
|
180
|
+
*
|
|
181
|
+
* @example Create from RPC URL
|
|
182
|
+
* ```typescript
|
|
183
|
+
* import { SolanaChain } from '@chainlink/ccip-sdk'
|
|
184
|
+
*
|
|
185
|
+
* const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
|
|
186
|
+
* console.log(`Connected to: ${chain.network.name}`)
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @example Query messages in a transaction
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const requests = await chain.getMessagesInTx('5abc123...')
|
|
192
|
+
* for (const req of requests) {
|
|
193
|
+
* console.log(`Message ID: ${req.message.messageId}`)
|
|
194
|
+
* }
|
|
195
|
+
* ```
|
|
174
196
|
*/
|
|
175
197
|
export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
176
198
|
static {
|
|
@@ -284,9 +306,20 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
284
306
|
|
|
285
307
|
/**
|
|
286
308
|
* Creates a SolanaChain instance from an RPC URL.
|
|
287
|
-
*
|
|
288
|
-
* @param
|
|
289
|
-
* @
|
|
309
|
+
*
|
|
310
|
+
* @param url - RPC endpoint URL (https://, http://, wss://, or ws://).
|
|
311
|
+
* @param ctx - Optional context containing logger and API client configuration.
|
|
312
|
+
* @returns A new SolanaChain instance connected to the specified network.
|
|
313
|
+
* @throws {@link CCIPChainNotFoundError} if chain cannot be identified from genesis hash
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```typescript
|
|
317
|
+
* // Create from devnet URL
|
|
318
|
+
* const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
|
|
319
|
+
*
|
|
320
|
+
* // With custom logger
|
|
321
|
+
* const chain = await SolanaChain.fromUrl(url, { logger: customLogger })
|
|
322
|
+
* ```
|
|
290
323
|
*/
|
|
291
324
|
static async fromUrl(url: string, ctx?: ChainContext): Promise<SolanaChain> {
|
|
292
325
|
const connection = this._getConnection(url, ctx)
|
|
@@ -395,13 +428,13 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
395
428
|
* - `watch`: Watch for new logs
|
|
396
429
|
* - `programs`: Special option to allow querying by address of interest, but yielding matching
|
|
397
430
|
* logs from specific (string address) program or any (true)
|
|
398
|
-
* @returns AsyncIterableIterator of parsed
|
|
431
|
+
* @returns AsyncIterableIterator of parsed ChainLog objects.
|
|
399
432
|
* @throws {@link CCIPLogsAddressRequiredError} if address is not provided
|
|
400
433
|
* @throws {@link CCIPTopicsInvalidError} if topics contain invalid values
|
|
401
434
|
*/
|
|
402
435
|
async *getLogs(
|
|
403
436
|
opts: LogFilter & { programs?: string[] | true },
|
|
404
|
-
): AsyncGenerator<
|
|
437
|
+
): AsyncGenerator<ChainLog & { tx: SolanaTransaction }> {
|
|
405
438
|
let programs: true | string[]
|
|
406
439
|
if (!opts.address) {
|
|
407
440
|
throw new CCIPLogsAddressRequiredError()
|
|
@@ -442,15 +475,15 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
442
475
|
}
|
|
443
476
|
|
|
444
477
|
/** {@inheritDoc Chain.getMessagesInBatch} */
|
|
445
|
-
async getMessagesInBatch<
|
|
478
|
+
override async getMessagesInBatch<
|
|
446
479
|
R extends PickDeep<
|
|
447
480
|
CCIPRequest,
|
|
448
481
|
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.sequenceNumber'
|
|
449
482
|
>,
|
|
450
483
|
>(
|
|
451
484
|
request: R,
|
|
452
|
-
|
|
453
|
-
opts?:
|
|
485
|
+
range: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
|
|
486
|
+
opts?: Pick<LogFilter, 'page'>,
|
|
454
487
|
): Promise<R['message'][]> {
|
|
455
488
|
const [destChainStatePda] = PublicKey.findProgramAddressSync(
|
|
456
489
|
[Buffer.from('dest_chain_state'), toLeArray(request.lane.destChainSelector, 8)],
|
|
@@ -463,7 +496,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
463
496
|
programs: [request.log.address],
|
|
464
497
|
address: destChainStatePda.toBase58(),
|
|
465
498
|
}
|
|
466
|
-
return getMessagesInBatch(this, request,
|
|
499
|
+
return getMessagesInBatch(this, request, range, opts_)
|
|
467
500
|
}
|
|
468
501
|
|
|
469
502
|
/** {@inheritDoc Chain.typeAndVersion} */
|
|
@@ -548,8 +581,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
548
581
|
return Promise.resolve(router) // solana's Router is also the OnRamp
|
|
549
582
|
}
|
|
550
583
|
|
|
551
|
-
/** {@inheritDoc Chain.
|
|
552
|
-
async
|
|
584
|
+
/** {@inheritDoc Chain.getOnRampsForOffRamp} */
|
|
585
|
+
async getOnRampsForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string[]> {
|
|
553
586
|
const program = new Program(CCIP_OFFRAMP_IDL, new PublicKey(offRamp), {
|
|
554
587
|
connection: this.connection,
|
|
555
588
|
})
|
|
@@ -563,15 +596,12 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
563
596
|
const {
|
|
564
597
|
config: { onRamp },
|
|
565
598
|
} = await program.account.sourceChain.fetch(statePda)
|
|
566
|
-
return
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
/** {@inheritDoc Chain.getCommitStoreForOffRamp} */
|
|
573
|
-
getCommitStoreForOffRamp(offRamp: string): Promise<string> {
|
|
574
|
-
return Promise.resolve(offRamp) // Solana supports only CCIP>=1.6, for which OffRamp and CommitStore are the same
|
|
599
|
+
return [
|
|
600
|
+
decodeAddress(
|
|
601
|
+
getAddressBytes(onRamp.bytes).subarray(0, onRamp.len),
|
|
602
|
+
networkInfo(sourceChainSelector).family,
|
|
603
|
+
),
|
|
604
|
+
]
|
|
575
605
|
}
|
|
576
606
|
|
|
577
607
|
/**
|
|
@@ -863,7 +893,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
863
893
|
* @throws {@link CCIPLogDataMissingError} if log data is missing
|
|
864
894
|
*/
|
|
865
895
|
static decodeCommits(
|
|
866
|
-
log: Pick<
|
|
896
|
+
log: Pick<ChainLog, 'data'>,
|
|
867
897
|
lane?: Omit<Lane, 'destChainSelector'>,
|
|
868
898
|
): CommitReport[] | undefined {
|
|
869
899
|
// Check if this is a CommitReportAccepted event by looking at the discriminant
|
|
@@ -918,7 +948,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
918
948
|
* @throws {@link CCIPLogDataMissingError} if log data is missing
|
|
919
949
|
* @throws {@link CCIPExecutionStateInvalidError} if execution state is invalid
|
|
920
950
|
*/
|
|
921
|
-
static decodeReceipt(log: Pick<
|
|
951
|
+
static decodeReceipt(log: Pick<ChainLog, 'data' | 'tx' | 'index'>): ExecutionReceipt | undefined {
|
|
922
952
|
// Check if this is a ExecutionStateChanged event by looking at the discriminant
|
|
923
953
|
if (!log.data || typeof log.data !== 'string') {
|
|
924
954
|
throw new CCIPLogDataMissingError()
|
|
@@ -951,7 +981,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
951
981
|
} else throw new CCIPExecutionStateInvalidError(util.inspect(decoded.data.state))
|
|
952
982
|
|
|
953
983
|
let returnData
|
|
954
|
-
if (log.tx) {
|
|
984
|
+
if (log.tx?.logs) {
|
|
955
985
|
// use only last receipt per tx+message (i.e. skip intermediary InProgress=1 states for Solana)
|
|
956
986
|
const laterReceiptLog = log.tx.logs
|
|
957
987
|
.filter((l) => l.index > log.index)
|
|
@@ -1075,13 +1105,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1075
1105
|
return (await this.getMessagesInTx(await this.getTransaction(hash)))[0]!
|
|
1076
1106
|
}
|
|
1077
1107
|
|
|
1078
|
-
/** {@inheritDoc Chain.getOffchainTokenData} */
|
|
1079
|
-
async getOffchainTokenData(request: CCIPRequest): Promise<OffchainTokenData[]> {
|
|
1080
|
-
return fetchSolanaOffchainTokenData(request, this)
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
1108
|
/**
|
|
1084
|
-
* {@inheritDoc Chain.
|
|
1109
|
+
* {@inheritDoc Chain.generateUnsignedExecute}
|
|
1085
1110
|
* @returns instructions - array of instructions to execute the report
|
|
1086
1111
|
* lookupTables - array of lookup tables for `manuallyExecute` call
|
|
1087
1112
|
* mainIndex - index of the `manuallyExecute` instruction in the array; last unless
|
|
@@ -1089,15 +1114,14 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1089
1114
|
* second to last
|
|
1090
1115
|
* @throws {@link CCIPExecutionReportChainMismatchError} if message is not a Solana message
|
|
1091
1116
|
*/
|
|
1092
|
-
async
|
|
1117
|
+
async generateUnsignedExecute({
|
|
1093
1118
|
payer,
|
|
1094
|
-
offRamp,
|
|
1095
|
-
execReport,
|
|
1096
1119
|
...opts
|
|
1097
|
-
}: Parameters<Chain['
|
|
1098
|
-
if (!('computeUnits' in
|
|
1120
|
+
}: Parameters<Chain['generateUnsignedExecute']>[0]): Promise<UnsignedSolanaTx> {
|
|
1121
|
+
if (!('input' in opts) || !('message' in opts.input) || !('computeUnits' in opts.input.message))
|
|
1099
1122
|
throw new CCIPExecutionReportChainMismatchError('Solana')
|
|
1100
|
-
const
|
|
1123
|
+
const { offRamp, input } = opts
|
|
1124
|
+
const execReport_ = input as ExecutionInput<CCIPMessage_V1_6_Solana>
|
|
1101
1125
|
return generateUnsignedExecuteReport(
|
|
1102
1126
|
this,
|
|
1103
1127
|
new PublicKey(payer),
|
|
@@ -1108,11 +1132,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1108
1132
|
}
|
|
1109
1133
|
|
|
1110
1134
|
/**
|
|
1111
|
-
* {@inheritDoc Chain.
|
|
1135
|
+
* {@inheritDoc Chain.execute}
|
|
1112
1136
|
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
|
|
1113
1137
|
*/
|
|
1114
|
-
async
|
|
1115
|
-
opts: Parameters<Chain['
|
|
1138
|
+
async execute(
|
|
1139
|
+
opts: Parameters<Chain['execute']>[0] & {
|
|
1116
1140
|
// when cleaning leftover LookUp Tables, wait deactivation grace period (~513 slots) then close ALT
|
|
1117
1141
|
waitDeactivation?: boolean
|
|
1118
1142
|
},
|
|
@@ -1123,7 +1147,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1123
1147
|
let hash
|
|
1124
1148
|
do {
|
|
1125
1149
|
try {
|
|
1126
|
-
const unsigned = await this.
|
|
1150
|
+
const unsigned = await this.generateUnsignedExecute({
|
|
1127
1151
|
...opts,
|
|
1128
1152
|
payer: wallet.publicKey.toBase58(),
|
|
1129
1153
|
})
|
|
@@ -1178,13 +1202,13 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1178
1202
|
if (Array.isArray(data)) {
|
|
1179
1203
|
if (data.every((e) => typeof e === 'string')) return getErrorFromLogs(data)
|
|
1180
1204
|
else if (data.every((e) => typeof e === 'object' && 'data' in e && 'address' in e))
|
|
1181
|
-
return getErrorFromLogs(data as
|
|
1205
|
+
return getErrorFromLogs(data as ChainLog[])
|
|
1182
1206
|
} else if (typeof data === 'object') {
|
|
1183
1207
|
if ('transactionLogs' in data && 'transactionMessage' in data) {
|
|
1184
|
-
const parsed = getErrorFromLogs(data.transactionLogs as
|
|
1208
|
+
const parsed = getErrorFromLogs(data.transactionLogs as ChainLog[] | string[])
|
|
1185
1209
|
if (parsed) return { message: data.transactionMessage, ...parsed }
|
|
1186
1210
|
}
|
|
1187
|
-
if ('logs' in data) return getErrorFromLogs(data.logs as
|
|
1211
|
+
if ('logs' in data) return getErrorFromLogs(data.logs as ChainLog[] | string[])
|
|
1188
1212
|
} else if (typeof data === 'string') {
|
|
1189
1213
|
const parsedExtraArgs = this.decodeExtraArgs(getDataBytes(data))
|
|
1190
1214
|
if (parsedExtraArgs) return parsedExtraArgs
|
|
@@ -1199,39 +1223,36 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1199
1223
|
/**
|
|
1200
1224
|
* Solana specialization: use getProgramAccounts to fetch commit reports from PDAs
|
|
1201
1225
|
*/
|
|
1202
|
-
override async
|
|
1203
|
-
opts: Parameters<Chain['
|
|
1204
|
-
): Promise<
|
|
1205
|
-
const {
|
|
1206
|
-
const commitsAroundSeqNum = await this.connection.getProgramAccounts(
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
{
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
offset: 0,
|
|
1214
|
-
bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
|
|
1215
|
-
},
|
|
1226
|
+
override async getVerifications(
|
|
1227
|
+
opts: Parameters<Chain['getVerifications']>[0],
|
|
1228
|
+
): Promise<CCIPVerifications> {
|
|
1229
|
+
const { offRamp, request } = opts
|
|
1230
|
+
const commitsAroundSeqNum = await this.connection.getProgramAccounts(new PublicKey(offRamp), {
|
|
1231
|
+
filters: [
|
|
1232
|
+
{
|
|
1233
|
+
// commit report account discriminator filter
|
|
1234
|
+
memcmp: {
|
|
1235
|
+
offset: 0,
|
|
1236
|
+
bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
|
|
1216
1237
|
},
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
// sourceChainSelector filter
|
|
1241
|
+
memcmp: {
|
|
1242
|
+
offset: 8 + 1,
|
|
1243
|
+
bytes: encodeBase58(toLeArray(request.lane.sourceChainSelector, 8)),
|
|
1223
1244
|
},
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1245
|
+
},
|
|
1246
|
+
// memcmp report.min with msg.sequenceNumber's without least-significant byte;
|
|
1247
|
+
// this should be ~256 around seqNum, i.e. big chance of a match; requires PDAs not to have been closed
|
|
1248
|
+
{
|
|
1249
|
+
memcmp: {
|
|
1250
|
+
offset: 8 + 1 + 8 + 32 + 8 + /*skip byte*/ 1,
|
|
1251
|
+
bytes: encodeBase58(toLeArray(request.message.sequenceNumber, 8).slice(1)),
|
|
1231
1252
|
},
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
)
|
|
1253
|
+
},
|
|
1254
|
+
],
|
|
1255
|
+
})
|
|
1235
1256
|
for (const acc of commitsAroundSeqNum) {
|
|
1236
1257
|
// const merkleRoot = acc.account.data.subarray(8 + 1 + 8, 8 + 1 + 8 + 32)
|
|
1237
1258
|
const minSeqNr = acc.account.data.readBigUInt64LE(8 + 1 + 8 + 32 + 8)
|
|
@@ -1241,7 +1262,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1241
1262
|
// we have all the commit report info, but we also need log details (txHash, etc)
|
|
1242
1263
|
for await (const log of this.getLogs({
|
|
1243
1264
|
startTime: 1, // just to force getting the oldest log first
|
|
1244
|
-
programs: [
|
|
1265
|
+
programs: [offRamp],
|
|
1245
1266
|
address: acc.pubkey.toBase58(),
|
|
1246
1267
|
topics: ['CommitReportAccepted'],
|
|
1247
1268
|
})) {
|
|
@@ -1254,23 +1275,23 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1254
1275
|
}
|
|
1255
1276
|
}
|
|
1256
1277
|
// in case we can't find it, fallback to generic iterating txs
|
|
1257
|
-
return super.
|
|
1278
|
+
return super.getVerifications(opts)
|
|
1258
1279
|
}
|
|
1259
1280
|
|
|
1260
1281
|
/** {@inheritDoc Chain.getExecutionReceipts} */
|
|
1261
1282
|
override async *getExecutionReceipts(
|
|
1262
1283
|
opts: Parameters<Chain['getExecutionReceipts']>[0],
|
|
1263
1284
|
): AsyncIterableIterator<CCIPExecution> {
|
|
1264
|
-
const { offRamp, sourceChainSelector,
|
|
1285
|
+
const { offRamp, sourceChainSelector, verifications } = opts
|
|
1265
1286
|
let opts_: Parameters<Chain['getExecutionReceipts']>[0] &
|
|
1266
1287
|
Parameters<SolanaChain['getLogs']>[0] = opts
|
|
1267
|
-
if (
|
|
1288
|
+
if (sourceChainSelector && verifications && 'report' in verifications) {
|
|
1268
1289
|
// if we know of commit, use `commit_report` PDA as more specialized address
|
|
1269
1290
|
const [commitReportPda] = PublicKey.findProgramAddressSync(
|
|
1270
1291
|
[
|
|
1271
1292
|
Buffer.from('commit_report'),
|
|
1272
1293
|
toLeArray(sourceChainSelector, 8),
|
|
1273
|
-
bytesToBuffer(
|
|
1294
|
+
bytesToBuffer(verifications.report.merkleRoot),
|
|
1274
1295
|
],
|
|
1275
1296
|
new PublicKey(offRamp),
|
|
1276
1297
|
)
|
|
@@ -1559,7 +1580,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
|
|
|
1559
1580
|
}
|
|
1560
1581
|
|
|
1561
1582
|
/**
|
|
1562
|
-
*
|
|
1583
|
+
* Returns a copy of a message, populating missing fields like `extraArgs` with defaults.
|
|
1584
|
+
* It's expected to return a message suitable at least for basic token transfers.
|
|
1585
|
+
*
|
|
1586
|
+
* @param message - AnyMessage (from source), containing at least `receiver`
|
|
1587
|
+
* @returns A message suitable for `sendMessage` to this destination chain family
|
|
1563
1588
|
* @throws {@link CCIPArgumentInvalidError} if tokenReceiver missing when sending tokens with data
|
|
1564
1589
|
*/
|
|
1565
1590
|
static override buildMessageForDest(
|
package/src/solana/offchain.ts
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { PublicKey } from '@solana/web3.js'
|
|
1
|
+
import { BorshCoder } from '@coral-xyz/anchor'
|
|
3
2
|
import { hexlify } from 'ethers'
|
|
4
3
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
CCIPCctpMultipleEventsError,
|
|
8
|
-
CCIPDataFormatUnsupportedError,
|
|
9
|
-
} from '../errors/index.ts'
|
|
10
|
-
import { getUsdcAttestation } from '../offchain.ts'
|
|
11
|
-
import type { CCIPMessage, CCIPRequest, OffchainTokenData, WithLogger } from '../types.ts'
|
|
12
|
-
import { bytesToBuffer, networkInfo, util } from '../utils.ts'
|
|
4
|
+
import type { OffchainTokenData } from '../types.ts'
|
|
5
|
+
import { bytesToBuffer } from '../utils.ts'
|
|
13
6
|
import { IDL as BASE_TOKEN_POOL } from './idl/1.6.0/BASE_TOKEN_POOL.ts'
|
|
14
7
|
import { IDL as CCTP_TOKEN_POOL } from './idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts'
|
|
15
|
-
import type { SolanaLog, SolanaTransaction } from './index.ts'
|
|
16
|
-
import { hexDiscriminator } from './utils.ts'
|
|
17
|
-
|
|
18
|
-
interface CcipCctpMessageSentEvent {
|
|
19
|
-
originalSender: PublicKey
|
|
20
|
-
remoteChainSelector: BN
|
|
21
|
-
msgTotalNonce: BN
|
|
22
|
-
eventAddress: PublicKey
|
|
23
|
-
sourceDomain: number
|
|
24
|
-
cctpNonce: BN
|
|
25
|
-
messageSentBytes: Uint8Array
|
|
26
|
-
}
|
|
27
8
|
|
|
28
9
|
interface CcipCctpMessageAndAttestation {
|
|
29
10
|
message: {
|
|
@@ -38,84 +19,6 @@ const cctpTokenPoolCoder = new BorshCoder({
|
|
|
38
19
|
errors: [...BASE_TOKEN_POOL.errors, ...CCTP_TOKEN_POOL.errors],
|
|
39
20
|
})
|
|
40
21
|
|
|
41
|
-
/**
|
|
42
|
-
* Analyzes a Solana transaction to extract CcipCctpMessageSentEvent, fetch Circle attestation,
|
|
43
|
-
* and encode the data in the format required by the destination chain.
|
|
44
|
-
* @param request - CCIP request containing transaction data and chain routing info.
|
|
45
|
-
* @param logger - Logger instance for logging messages.
|
|
46
|
-
* @returns Array of encoded offchain token data (only one supported for Solana right now).
|
|
47
|
-
* @throws Error if transaction hash is missing or CcipCctpMessageSentEvent parsing fails.
|
|
48
|
-
*/
|
|
49
|
-
export async function fetchSolanaOffchainTokenData(
|
|
50
|
-
request: Pick<CCIPRequest, 'tx' | 'lane'> & {
|
|
51
|
-
message: CCIPMessage
|
|
52
|
-
log: Pick<CCIPRequest['log'], 'topics' | 'index' | 'transactionHash' | 'address'>
|
|
53
|
-
},
|
|
54
|
-
{ logger = console }: WithLogger = {},
|
|
55
|
-
): Promise<OffchainTokenData[]> {
|
|
56
|
-
if (!request.message.tokenAmounts.length) {
|
|
57
|
-
return []
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (request.message.tokenAmounts.length > 1) {
|
|
61
|
-
throw new CCIPDataFormatUnsupportedError(
|
|
62
|
-
`Expected at most 1 token transfer, found ${request.message.tokenAmounts.length}`,
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const { networkType } = networkInfo(request.lane.sourceChainSelector)
|
|
67
|
-
const txSignature = request.log.transactionHash
|
|
68
|
-
|
|
69
|
-
// Parse Solana transaction to find CCTP event
|
|
70
|
-
const tx = request.tx as SolanaTransaction
|
|
71
|
-
const log = request.log as SolanaLog
|
|
72
|
-
const logMessages = tx.tx.meta!.logMessages!
|
|
73
|
-
// there may have multiple ccipSend calls in same tx;
|
|
74
|
-
// use `invoke [level]` to filter only logs inside this call
|
|
75
|
-
const requestInvokeIdx = logMessages.findLastIndex(
|
|
76
|
-
(l, i) => i < log.index && l === `Program ${request.log.address} invoke [${log.level}]`,
|
|
77
|
-
)
|
|
78
|
-
const cctpEvents = []
|
|
79
|
-
for (const l of tx.logs) {
|
|
80
|
-
if (requestInvokeIdx >= l.index || l.index >= log.index) continue
|
|
81
|
-
if (l.topics[0] !== hexDiscriminator('CcipCctpMessageSentEvent')) continue
|
|
82
|
-
const decoded = cctpTokenPoolCoder.events.decode(l.data)
|
|
83
|
-
if (!decoded) throw new CCIPCctpDecodeError(util.inspect(l))
|
|
84
|
-
cctpEvents.push(decoded.data as unknown as CcipCctpMessageSentEvent)
|
|
85
|
-
}
|
|
86
|
-
const offchainTokenData: OffchainTokenData[] = request.message.tokenAmounts.map(() => undefined)
|
|
87
|
-
|
|
88
|
-
// If no CcipCctpMessageSentEvent found, return defaults so we don't block execution
|
|
89
|
-
if (cctpEvents.length === 0) {
|
|
90
|
-
logger.debug('No USDC/CCTP events found')
|
|
91
|
-
return offchainTokenData
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Currently, we only support ONE token per transfer
|
|
95
|
-
if (cctpEvents.length > 1) {
|
|
96
|
-
throw new CCIPCctpMultipleEventsError(cctpEvents.length, txSignature)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// NOTE: assuming USDC token is the first (and only) token in the CCIP message, we will process the CCTP event.
|
|
100
|
-
// If later multi-token transfers support is added, we need to add more info in order to match each token with it's event and offchainTokenData.
|
|
101
|
-
const cctpEvent = cctpEvents[0]
|
|
102
|
-
if (cctpEvent) {
|
|
103
|
-
const message = hexlify(cctpEvent.messageSentBytes)
|
|
104
|
-
try {
|
|
105
|
-
// Extract message bytes to fetch circle's attestation and then encode offchainTokenData.
|
|
106
|
-
const attestation = await getUsdcAttestation(message, networkType)
|
|
107
|
-
|
|
108
|
-
offchainTokenData[0] = { _tag: 'usdc', message, attestation }
|
|
109
|
-
} catch (error) {
|
|
110
|
-
logger.warn(`❌ Solana CCTP: Failed to fetch attestation for ${txSignature}:`, message, error)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
logger.debug('Got Solana offchain token data', offchainTokenData)
|
|
115
|
-
|
|
116
|
-
return offchainTokenData
|
|
117
|
-
}
|
|
118
|
-
|
|
119
22
|
/**
|
|
120
23
|
* Encodes CCTP message and attestation
|
|
121
24
|
*
|
package/src/solana/utils.ts
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
CCIPTokenMintNotFoundError,
|
|
27
27
|
CCIPTransactionNotFinalizedError,
|
|
28
28
|
} from '../errors/index.ts'
|
|
29
|
-
import type {
|
|
29
|
+
import type { ChainLog, WithLogger } from '../types.ts'
|
|
30
30
|
import { getDataBytes, sleep } from '../utils.ts'
|
|
31
31
|
import type { IDL as BASE_TOKEN_POOL_IDL } from './idl/1.6.0/BASE_TOKEN_POOL.ts'
|
|
32
32
|
import type { UnsignedSolanaTx, Wallet } from './types.ts'
|
|
@@ -143,7 +143,7 @@ export function camelToSnakeCase(str: string): string {
|
|
|
143
143
|
.replace(/^_/, '')
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
type ParsedLog = Pick<
|
|
146
|
+
type ParsedLog = Pick<ChainLog, 'topics' | 'index' | 'address' | 'data'> & {
|
|
147
147
|
data: string
|
|
148
148
|
level: number
|
|
149
149
|
}
|
|
@@ -160,7 +160,7 @@ type ParsedLog = Pick<Log_, 'topics' | 'index' | 'address' | 'data'> & {
|
|
|
160
160
|
* This function:
|
|
161
161
|
* 1. Tracks the program call stack to determine which program emitted each log
|
|
162
162
|
* 2. Extracts the first 8 bytes from base64 "Program data:" logs as topics (event discriminants)
|
|
163
|
-
* 3. Converts logs to EVM-compatible
|
|
163
|
+
* 3. Converts logs to EVM-compatible ChainLog format for CCIP compatibility
|
|
164
164
|
* 4. Returns ALL logs from the transaction - filtering should be done by the caller
|
|
165
165
|
*
|
|
166
166
|
* @param logs - Array of logMessages from Solana transaction
|
|
@@ -215,7 +215,10 @@ export function parseSolanaLogs(logs: readonly string[]): ParsedLog[] {
|
|
|
215
215
|
* @returns Parsed error info with program and error details.
|
|
216
216
|
*/
|
|
217
217
|
export function getErrorFromLogs(
|
|
218
|
-
logs_:
|
|
218
|
+
logs_:
|
|
219
|
+
| readonly string[]
|
|
220
|
+
| readonly Pick<ChainLog, 'address' | 'index' | 'data' | 'topics'>[]
|
|
221
|
+
| null,
|
|
219
222
|
): { program: string; [k: string]: string } | undefined {
|
|
220
223
|
if (!logs_?.length) return
|
|
221
224
|
let logs
|
|
@@ -229,7 +232,7 @@ export function getErrorFromLogs(
|
|
|
229
232
|
(acc, l) =>
|
|
230
233
|
// if acc is empty (i.e. on last log), or it is emitted by the same program and not a Program data:
|
|
231
234
|
!acc.length || (l.address === acc[0]!.address && !l.topics.length) ? [l, ...acc] : acc,
|
|
232
|
-
[] as Pick<
|
|
235
|
+
[] as Pick<ChainLog, 'address' | 'index' | 'data'>[],
|
|
233
236
|
)
|
|
234
237
|
.map(({ data }) => data as string)
|
|
235
238
|
.reduceRight(
|
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.
|