@chainlink/ccip-sdk 0.95.0 → 0.96.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +2 -2
  2. package/dist/all-chains.d.ts +23 -0
  3. package/dist/all-chains.d.ts.map +1 -0
  4. package/dist/all-chains.js +24 -0
  5. package/dist/all-chains.js.map +1 -0
  6. package/dist/api/index.d.ts +15 -12
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +20 -16
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/types.d.ts +25 -29
  11. package/dist/api/types.d.ts.map +1 -1
  12. package/dist/aptos/index.d.ts +33 -8
  13. package/dist/aptos/index.d.ts.map +1 -1
  14. package/dist/aptos/index.js +74 -41
  15. package/dist/aptos/index.js.map +1 -1
  16. package/dist/chain.d.ts +220 -41
  17. package/dist/chain.d.ts.map +1 -1
  18. package/dist/chain.js +105 -15
  19. package/dist/chain.js.map +1 -1
  20. package/dist/errors/codes.d.ts +2 -0
  21. package/dist/errors/codes.d.ts.map +1 -1
  22. package/dist/errors/codes.js +2 -0
  23. package/dist/errors/codes.js.map +1 -1
  24. package/dist/errors/index.d.ts +1 -1
  25. package/dist/errors/index.d.ts.map +1 -1
  26. package/dist/errors/index.js +1 -1
  27. package/dist/errors/index.js.map +1 -1
  28. package/dist/errors/recovery.d.ts.map +1 -1
  29. package/dist/errors/recovery.js +2 -0
  30. package/dist/errors/recovery.js.map +1 -1
  31. package/dist/errors/specialized.d.ts +12 -6
  32. package/dist/errors/specialized.d.ts.map +1 -1
  33. package/dist/errors/specialized.js +19 -7
  34. package/dist/errors/specialized.js.map +1 -1
  35. package/dist/evm/extra-args.d.ts +25 -0
  36. package/dist/evm/extra-args.d.ts.map +1 -0
  37. package/dist/evm/extra-args.js +328 -0
  38. package/dist/evm/extra-args.js.map +1 -0
  39. package/dist/evm/gas.d.ts.map +1 -1
  40. package/dist/evm/gas.js +7 -12
  41. package/dist/evm/gas.js.map +1 -1
  42. package/dist/evm/index.d.ts +70 -24
  43. package/dist/evm/index.d.ts.map +1 -1
  44. package/dist/evm/index.js +72 -91
  45. package/dist/evm/index.js.map +1 -1
  46. package/dist/execution.d.ts.map +1 -1
  47. package/dist/execution.js +16 -2
  48. package/dist/execution.js.map +1 -1
  49. package/dist/extra-args.d.ts +103 -4
  50. package/dist/extra-args.d.ts.map +1 -1
  51. package/dist/extra-args.js +28 -3
  52. package/dist/extra-args.js.map +1 -1
  53. package/dist/gas.d.ts +6 -3
  54. package/dist/gas.d.ts.map +1 -1
  55. package/dist/gas.js +14 -6
  56. package/dist/gas.js.map +1 -1
  57. package/dist/index.d.ts +10 -9
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +8 -8
  60. package/dist/index.js.map +1 -1
  61. package/dist/requests.d.ts +17 -9
  62. package/dist/requests.d.ts.map +1 -1
  63. package/dist/requests.js +17 -9
  64. package/dist/requests.js.map +1 -1
  65. package/dist/selectors.d.ts.map +1 -1
  66. package/dist/selectors.js +12 -0
  67. package/dist/selectors.js.map +1 -1
  68. package/dist/solana/index.d.ts +70 -15
  69. package/dist/solana/index.d.ts.map +1 -1
  70. package/dist/solana/index.js +72 -16
  71. package/dist/solana/index.js.map +1 -1
  72. package/dist/sui/index.d.ts +37 -9
  73. package/dist/sui/index.d.ts.map +1 -1
  74. package/dist/sui/index.js +40 -11
  75. package/dist/sui/index.js.map +1 -1
  76. package/dist/ton/index.d.ts +65 -19
  77. package/dist/ton/index.d.ts.map +1 -1
  78. package/dist/ton/index.js +155 -25
  79. package/dist/ton/index.js.map +1 -1
  80. package/dist/ton/send.d.ts +52 -0
  81. package/dist/ton/send.d.ts.map +1 -0
  82. package/dist/ton/send.js +166 -0
  83. package/dist/ton/send.js.map +1 -0
  84. package/dist/types.d.ts +102 -1
  85. package/dist/types.d.ts.map +1 -1
  86. package/dist/types.js.map +1 -1
  87. package/dist/utils.d.ts +15 -3
  88. package/dist/utils.d.ts.map +1 -1
  89. package/dist/utils.js +19 -6
  90. package/dist/utils.js.map +1 -1
  91. package/package.json +12 -7
  92. package/src/all-chains.ts +26 -0
  93. package/src/api/index.ts +26 -25
  94. package/src/api/types.ts +25 -30
  95. package/src/aptos/index.ts +79 -43
  96. package/src/chain.ts +274 -46
  97. package/src/errors/codes.ts +2 -0
  98. package/src/errors/index.ts +1 -1
  99. package/src/errors/recovery.ts +2 -0
  100. package/src/errors/specialized.ts +24 -7
  101. package/src/evm/extra-args.ts +377 -0
  102. package/src/evm/gas.ts +14 -13
  103. package/src/evm/index.ts +76 -125
  104. package/src/execution.ts +18 -2
  105. package/src/extra-args.ts +108 -4
  106. package/src/gas.ts +16 -9
  107. package/src/index.ts +12 -9
  108. package/src/requests.ts +17 -9
  109. package/src/selectors.ts +12 -0
  110. package/src/solana/index.ts +72 -16
  111. package/src/sui/index.ts +40 -11
  112. package/src/ton/index.ts +192 -27
  113. package/src/ton/send.ts +222 -0
  114. package/src/types.ts +103 -1
  115. package/src/utils.ts +19 -6
package/src/requests.ts CHANGED
@@ -126,9 +126,12 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
126
126
  }
127
127
 
128
128
  /**
129
- * Decodes hex strings, bytearrays, JSON strings and raw objects as CCIPMessages
130
- * Does minimal validation, but converts objects in the format expected by ccip-tools-ts
131
- **/
129
+ * Decodes hex strings, bytearrays, JSON strings and raw objects as CCIPMessages.
130
+ * Does minimal validation, but converts objects in the format expected by ccip-tools-ts.
131
+ * @param data - Data to decode (hex string, Uint8Array, JSON string, or object)
132
+ * @returns Decoded CCIPMessage
133
+ * @throws {@link CCIPMessageDecodeError} if data cannot be decoded as a valid message
134
+ */
132
135
  export function decodeMessage(data: string | Uint8Array | Record<string, unknown>): CCIPMessage {
133
136
  if (
134
137
  (typeof data === 'string' && data.startsWith('{')) ||
@@ -151,10 +154,11 @@ export function decodeMessage(data: string | Uint8Array | Record<string, unknown
151
154
  }
152
155
 
153
156
  /**
154
- * Populates missing required fields (e.g. `extraArgs`) from AnyMessage
155
- * @param message - partial AnyMessage
156
- * @returns original message or shallow copy with defaults for required fields
157
- **/
157
+ * Populates missing required fields (e.g. `extraArgs`) from AnyMessage.
158
+ * @param message - Partial AnyMessage with at least receiver
159
+ * @param dest - Destination chain family to build message for
160
+ * @returns Original message or shallow copy with defaults for required fields
161
+ */
158
162
  export function buildMessageForDest(message: MessageInput, dest: ChainFamily): AnyMessage {
159
163
  const chain = supportedChains[dest] ?? Chain
160
164
  return chain.buildMessageForDest(message)
@@ -162,10 +166,12 @@ export function buildMessageForDest(message: MessageInput, dest: ChainFamily): A
162
166
 
163
167
  /**
164
168
  * Fetch all CCIP messages in a transaction.
165
- * @param source - Chain
169
+ * @param source - Source chain instance
166
170
  * @param tx - ChainTransaction to search in
167
171
  * @returns CCIP requests (messages) in the transaction (at least one)
168
- **/
172
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported for legacy messages
173
+ * @throws {@link CCIPMessageNotFoundInTxError} if no CCIP messages found in transaction
174
+ */
169
175
  export async function getMessagesInTx(source: Chain, tx: ChainTransaction): Promise<CCIPRequest[]> {
170
176
  // RPC fallback
171
177
  const requests: CCIPRequest[] = []
@@ -332,6 +338,7 @@ export async function getMessagesInBatch<
332
338
  * @param sender - Sender address.
333
339
  * @param filter - Log filter options.
334
340
  * @returns Async generator of CCIP requests.
341
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported for legacy messages
335
342
  */
336
343
  export async function* getMessagesForSender(
337
344
  source: Chain,
@@ -375,6 +382,7 @@ export async function* getMessagesForSender(
375
382
  * @param onRamp - Contract address.
376
383
  * @param sourceTokenAmount - tokenAmount object, usually containing `token` and `amount` properties.
377
384
  * @returns tokenAmount object with `sourcePoolAddress`, `sourceTokenAddress`, `destTokenAddress`, and remaining properties.
385
+ * @throws {@link CCIPTokenNotInRegistryError} if token not found in registry
378
386
  */
379
387
  export async function sourceToDestTokenAddresses<S extends { token: string }>(
380
388
  source: Chain,
package/src/selectors.ts CHANGED
@@ -721,6 +721,12 @@ const selectors: Selectors = {
721
721
  network_type: 'TESTNET',
722
722
  family: 'EVM',
723
723
  },
724
+ '3343': {
725
+ selector: 6325494908023253251n,
726
+ name: 'edge-mainnet',
727
+ network_type: 'MAINNET',
728
+ family: 'EVM',
729
+ },
724
730
  '3636': {
725
731
  selector: 1467223411771711614n,
726
732
  name: 'bitcoin-testnet-botanix',
@@ -1003,6 +1009,12 @@ const selectors: Selectors = {
1003
1009
  network_type: 'MAINNET',
1004
1010
  family: 'EVM',
1005
1011
  },
1012
+ '33431': {
1013
+ selector: 13222148116102326311n,
1014
+ name: 'edge-testnet',
1015
+ network_type: 'TESTNET',
1016
+ family: 'EVM',
1017
+ },
1006
1018
  '34443': {
1007
1019
  selector: 7264351850409363825n,
1008
1020
  name: 'ethereum-mainnet-mode-1',
@@ -252,6 +252,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
252
252
  * @param url - RPC endpoint URL (https://, http://, wss://, or ws://).
253
253
  * @param ctx - context containing logger.
254
254
  * @returns Solana Connection instance.
255
+ * @throws {@link CCIPDataFormatUnsupportedError} if URL format is invalid
255
256
  */
256
257
  static _getConnection(url: string, ctx?: WithLogger): Connection {
257
258
  const { logger = console } = ctx ?? {}
@@ -293,7 +294,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
293
294
  }
294
295
 
295
296
  // cached
296
- /** {@inheritDoc Chain.getBlockTimestamp} */
297
+ /**
298
+ * {@inheritDoc Chain.getBlockTimestamp}
299
+ * @throws {@link CCIPBlockTimeNotFoundError} if block time cannot be retrieved
300
+ */
297
301
  async getBlockTimestamp(block: number | 'latest' | 'finalized'): Promise<number> {
298
302
  if (typeof block !== 'number') {
299
303
  const slot = await this.connection.getSlot(block === 'latest' ? 'confirmed' : block)
@@ -313,7 +317,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
313
317
  return blockTime
314
318
  }
315
319
 
316
- /** {@inheritDoc Chain.getTransaction} */
320
+ /**
321
+ * {@inheritDoc Chain.getTransaction}
322
+ * @throws {@link CCIPTransactionNotFoundError} if transaction not found
323
+ */
317
324
  async getTransaction(hash: string): Promise<SolanaTransaction> {
318
325
  const tx = await this.connection.getTransaction(hash, {
319
326
  commitment: 'confirmed',
@@ -389,6 +396,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
389
396
  * - `programs`: Special option to allow querying by address of interest, but yielding matching
390
397
  * logs from specific (string address) program or any (true)
391
398
  * @returns AsyncIterableIterator of parsed Log_ objects.
399
+ * @throws {@link CCIPLogsAddressRequiredError} if address is not provided
400
+ * @throws {@link CCIPTopicsInvalidError} if topics contain invalid values
392
401
  */
393
402
  async *getLogs(
394
403
  opts: LogFilter & { programs?: string[] | true },
@@ -480,7 +489,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
480
489
  return Promise.resolve(onRamp) // Solana's router is also the onRamp
481
490
  }
482
491
 
483
- /** {@inheritDoc Chain.getRouterForOffRamp} */
492
+ /**
493
+ * {@inheritDoc Chain.getRouterForOffRamp}
494
+ * @throws {@link CCIPSolanaRefAddressesNotFoundError} if reference addresses PDA not found
495
+ */
484
496
  async getRouterForOffRamp(offRamp: string, _sourceChainSelector: bigint): Promise<string> {
485
497
  const offRamp_ = new PublicKey(offRamp)
486
498
  const program = new Program(CCIP_OFFRAMP_IDL as Idl, offRamp_, {
@@ -507,7 +519,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
507
519
  return Promise.resolve(NATIVE_MINT.toBase58())
508
520
  }
509
521
 
510
- /** {@inheritDoc Chain.getOffRampsForRouter} */
522
+ /**
523
+ * {@inheritDoc Chain.getOffRampsForRouter}
524
+ * @throws {@link CCIPSolanaOffRampEventsNotFoundError} if no OffRamp events found
525
+ */
511
526
  async getOffRampsForRouter(router: string, sourceChainSelector: bigint): Promise<string[]> {
512
527
  // feeQuoter is present in router's config, and has a DestChainState account which is updated by
513
528
  // the offramps, so we can use it to narrow the search for the offramp
@@ -559,7 +574,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
559
574
  return Promise.resolve(offRamp) // Solana supports only CCIP>=1.6, for which OffRamp and CommitStore are the same
560
575
  }
561
576
 
562
- /** {@inheritDoc Chain.getTokenForTokenPool} */
577
+ /**
578
+ * {@inheritDoc Chain.getTokenForTokenPool}
579
+ * @throws {@link CCIPTokenPoolInfoNotFoundError} if token pool info not found
580
+ */
563
581
  async getTokenForTokenPool(tokenPool: string): Promise<string> {
564
582
  const tokenPoolInfo = await this.connection.getAccountInfo(new PublicKey(tokenPool))
565
583
  if (!tokenPoolInfo) throw new CCIPTokenPoolInfoNotFoundError(tokenPool)
@@ -570,7 +588,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
570
588
  return config.mint.toString()
571
589
  }
572
590
 
573
- /** {@inheritDoc Chain.getTokenInfo} */
591
+ /**
592
+ * {@inheritDoc Chain.getTokenInfo}
593
+ * @throws {@link CCIPSplTokenInvalidError} if token is not a valid SPL token
594
+ * @throws {@link CCIPTokenDataParseError} if token data cannot be parsed
595
+ */
574
596
  async getTokenInfo(token: string): Promise<TokenInfo> {
575
597
  const mint = new PublicKey(token)
576
598
  const mintInfo = await this.connection.getParsedAccountInfo(mint)
@@ -619,7 +641,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
619
641
  }
620
642
  }
621
643
 
622
- /** {@inheritDoc Chain.getBalance} */
644
+ /**
645
+ * {@inheritDoc Chain.getBalance}
646
+ * @throws {@link CCIPTokenAccountNotFoundError} if token account not found
647
+ */
623
648
  async getBalance(opts: GetBalanceOpts): Promise<bigint> {
624
649
  const { holder, token } = opts
625
650
  const holderPubkey = new PublicKey(holder)
@@ -712,6 +737,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
712
737
  * Decodes a CCIP message from a Solana log event.
713
738
  * @param log - Log with data field.
714
739
  * @returns Decoded CCIPMessage or undefined if not valid.
740
+ * @throws {@link CCIPExtraArgsInvalidError} if extra args cannot be decoded
715
741
  */
716
742
  static decodeMessage({ data }: { data: unknown }): CCIPMessage | undefined {
717
743
  if (!data || typeof data !== 'string') return undefined
@@ -789,6 +815,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
789
815
  * Decodes extra arguments from Solana CCIP messages.
790
816
  * @param extraArgs - Encoded extra arguments bytes.
791
817
  * @returns Decoded EVMExtraArgsV2 or undefined if unknown format.
818
+ * @throws {@link CCIPExtraArgsLengthInvalidError} if extra args length is invalid
792
819
  */
793
820
  static decodeExtraArgs(
794
821
  extraArgs: BytesLike,
@@ -816,6 +843,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
816
843
  * Encodes extra arguments for Solana CCIP messages.
817
844
  * @param args - Extra arguments to encode.
818
845
  * @returns Encoded extra arguments as hex string.
846
+ * @throws {@link CCIPSolanaExtraArgsEncodingError} if SVMExtraArgsV1 encoding is attempted
819
847
  */
820
848
  static encodeExtraArgs(args: ExtraArgs): string {
821
849
  if ('computeUnits' in args) throw new CCIPSolanaExtraArgsEncodingError()
@@ -832,6 +860,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
832
860
  * @param log - Log with data field.
833
861
  * @param lane - Lane info for filtering.
834
862
  * @returns Array of CommitReport or undefined if not valid.
863
+ * @throws {@link CCIPLogDataMissingError} if log data is missing
835
864
  */
836
865
  static decodeCommits(
837
866
  log: Pick<Log_, 'data'>,
@@ -886,6 +915,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
886
915
  * Decodes an execution receipt from a Solana log event.
887
916
  * @param log - Log with data, tx, and index fields.
888
917
  * @returns ExecutionReceipt or undefined if not valid.
918
+ * @throws {@link CCIPLogDataMissingError} if log data is missing
919
+ * @throws {@link CCIPExecutionStateInvalidError} if execution state is invalid
889
920
  */
890
921
  static decodeReceipt(log: Pick<Log_, 'data' | 'tx' | 'index'>): ExecutionReceipt | undefined {
891
922
  // Check if this is a ExecutionStateChanged event by looking at the discriminant
@@ -984,7 +1015,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
984
1015
  return getV16SolanaLeafHasher(lane, ctx)
985
1016
  }
986
1017
 
987
- /** {@inheritDoc Chain.getTokenAdminRegistryFor} */
1018
+ /**
1019
+ * {@inheritDoc Chain.getTokenAdminRegistryFor}
1020
+ * @throws {@link CCIPContractNotRouterError} if address is not a Router
1021
+ */
988
1022
  async getTokenAdminRegistryFor(address: string): Promise<string> {
989
1023
  const [type] = await this.typeAndVersion(address)
990
1024
  if (!type.includes('Router')) throw new CCIPContractNotRouterError(address, type)
@@ -1026,7 +1060,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1026
1060
  )
1027
1061
  }
1028
1062
 
1029
- /** {@inheritDoc Chain.sendMessage} */
1063
+ /**
1064
+ * {@inheritDoc Chain.sendMessage}
1065
+ * @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
1066
+ */
1030
1067
  async sendMessage(opts: Parameters<Chain['sendMessage']>[0]): Promise<CCIPRequest> {
1031
1068
  if (!isWallet(opts.wallet)) throw new CCIPWalletInvalidError(util.inspect(opts.wallet))
1032
1069
  const unsigned = await this.generateUnsignedSendMessage({
@@ -1050,6 +1087,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1050
1087
  * mainIndex - index of the `manuallyExecute` instruction in the array; last unless
1051
1088
  * forceLookupTable is set, in which case last is ALT deactivation tx, and manuallyExecute is
1052
1089
  * second to last
1090
+ * @throws {@link CCIPExecutionReportChainMismatchError} if message is not a Solana message
1053
1091
  */
1054
1092
  async generateUnsignedExecuteReport({
1055
1093
  payer,
@@ -1069,7 +1107,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1069
1107
  )
1070
1108
  }
1071
1109
 
1072
- /** {@inheritDoc Chain.executeReport} */
1110
+ /**
1111
+ * {@inheritDoc Chain.executeReport}
1112
+ * @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
1113
+ */
1073
1114
  async executeReport(
1074
1115
  opts: Parameters<Chain['executeReport']>[0] & {
1075
1116
  // when cleaning leftover LookUp Tables, wait deactivation grace period (~513 slots) then close ALT
@@ -1118,6 +1159,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1118
1159
  * - waitDeactivation - Whether to wait for lookup table deactivation cool down period
1119
1160
  * (513 slots) to pass before closing; by default, we deactivate (if needed) and move on, to
1120
1161
  * close other ready ALTs
1162
+ * @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
1121
1163
  */
1122
1164
  async cleanUpBuffers(opts: { wallet: unknown; waitDeactivation?: boolean }): Promise<void> {
1123
1165
  const wallet = opts.wallet
@@ -1241,7 +1283,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1241
1283
  yield* super.getExecutionReceipts(opts_)
1242
1284
  }
1243
1285
 
1244
- /** {@inheritDoc Chain.getRegistryTokenConfig} */
1286
+ /**
1287
+ * {@inheritDoc Chain.getRegistryTokenConfig}
1288
+ * @throws {@link CCIPTokenNotConfiguredError} if token is not configured in registry
1289
+ */
1245
1290
  async getRegistryTokenConfig(
1246
1291
  registry: string,
1247
1292
  token: string,
@@ -1295,8 +1340,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1295
1340
  return config
1296
1341
  }
1297
1342
 
1298
- /** {@inheritDoc Chain.getTokenPoolConfigs} */
1299
- async getTokenPoolConfigs(tokenPool: string): Promise<{
1343
+ /**
1344
+ * {@inheritDoc Chain.getTokenPoolConfig}
1345
+ * @throws {@link CCIPTokenPoolStateNotFoundError} if token pool state not found
1346
+ */
1347
+ async getTokenPoolConfig(tokenPool: string): Promise<{
1300
1348
  token: string
1301
1349
  router: string
1302
1350
  tokenPoolProgram: string
@@ -1328,7 +1376,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1328
1376
  }
1329
1377
  }
1330
1378
 
1331
- /** {@inheritDoc Chain.getTokenPoolRemotes} */
1379
+ /**
1380
+ * {@inheritDoc Chain.getTokenPoolRemotes}
1381
+ * @throws {@link CCIPTokenPoolStateNotFoundError} if token pool state not found
1382
+ * @throws {@link CCIPTokenPoolChainConfigNotFoundError} if chain config not found for specified selector
1383
+ */
1332
1384
  async getTokenPoolRemotes(
1333
1385
  tokenPool: string,
1334
1386
  remoteChainSelector?: bigint,
@@ -1506,7 +1558,10 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1506
1558
  return program.account.config.fetch(configPda)
1507
1559
  }
1508
1560
 
1509
- /** {@inheritDoc ChainStatic.buildMessageForDest} */
1561
+ /**
1562
+ * {@inheritDoc ChainStatic.buildMessageForDest}
1563
+ * @throws {@link CCIPArgumentInvalidError} if tokenReceiver missing when sending tokens with data
1564
+ */
1510
1565
  static override buildMessageForDest(
1511
1566
  message: Parameters<ChainStatic['buildMessageForDest']>[0],
1512
1567
  ): AnyMessage & { extraArgs: SVMExtraArgsV1 } {
@@ -1544,7 +1599,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1544
1599
  const tokenReceiver =
1545
1600
  message.extraArgs &&
1546
1601
  'tokenReceiver' in message.extraArgs &&
1547
- message.extraArgs.tokenReceiver != null
1602
+ message.extraArgs.tokenReceiver != null &&
1603
+ typeof message.extraArgs.tokenReceiver === 'string'
1548
1604
  ? message.extraArgs.tokenReceiver
1549
1605
  : message.tokenAmounts?.length
1550
1606
  ? this.getAddress(message.receiver)
package/src/sui/index.ts CHANGED
@@ -125,6 +125,8 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
125
125
  * Creates a SuiChain instance from an RPC URL.
126
126
  * @param url - HTTP or WebSocket endpoint URL for the Sui network.
127
127
  * @returns A new SuiChain instance.
128
+ * @throws {@link CCIPDataFormatUnsupportedError} if unable to fetch chain identifier
129
+ * @throws {@link CCIPError} if chain identifier is not supported
128
130
  */
129
131
  static async fromUrl(url: string, ctx?: ChainContext): Promise<SuiChain> {
130
132
  const client = new SuiClient({ url })
@@ -208,7 +210,11 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
208
210
  }
209
211
  }
210
212
 
211
- /** {@inheritDoc Chain.getLogs} */
213
+ /**
214
+ * {@inheritDoc Chain.getLogs}
215
+ * @throws {@link CCIPLogsAddressRequiredError} if address is not provided
216
+ * @throws {@link CCIPTopicsInvalidError} if topics format is invalid
217
+ */
212
218
  async *getLogs(opts: LogFilter & { versionAsHash?: boolean }) {
213
219
  if (!opts.address) throw new CCIPLogsAddressRequiredError()
214
220
 
@@ -246,7 +252,10 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
246
252
  return getMessagesInBatch(this, request, commit, opts)
247
253
  }
248
254
 
249
- /** {@inheritDoc Chain.typeAndVersion} */
255
+ /**
256
+ * {@inheritDoc Chain.typeAndVersion}
257
+ * @throws {@link CCIPDataFormatUnsupportedError} if view call fails
258
+ */
250
259
  async typeAndVersion(address: string) {
251
260
  // requires address to have `::<module>` suffix
252
261
  address = await getLatestPackageId(address, this.client)
@@ -280,7 +289,10 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
280
289
  return Promise.resolve(onRamp)
281
290
  }
282
291
 
283
- /** {@inheritDoc Chain.getRouterForOffRamp} */
292
+ /**
293
+ * {@inheritDoc Chain.getRouterForOffRamp}
294
+ * @throws {@link CCIPContractNotRouterError} always (Sui architecture doesn't have separate router)
295
+ */
284
296
  getRouterForOffRamp(offRamp: string, _sourceChainSelector: bigint): Promise<string> {
285
297
  throw new CCIPContractNotRouterError(offRamp, 'unknown')
286
298
  }
@@ -305,7 +317,10 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
305
317
  return Promise.resolve(router)
306
318
  }
307
319
 
308
- /** {@inheritDoc Chain.getOnRampForOffRamp} */
320
+ /**
321
+ * {@inheritDoc Chain.getOnRampForOffRamp}
322
+ * @throws {@link CCIPDataFormatUnsupportedError} if view call fails
323
+ */
309
324
  async getOnRampForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string> {
310
325
  offRamp = await getLatestPackageId(offRamp, this.client)
311
326
  const functionName = 'get_source_chain_config'
@@ -383,7 +398,11 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
383
398
  return Promise.resolve(offRamp)
384
399
  }
385
400
 
386
- /** {@inheritDoc Chain.getTokenForTokenPool} */
401
+ /**
402
+ * {@inheritDoc Chain.getTokenForTokenPool}
403
+ * @throws {@link CCIPError} if token pool type is invalid or state not found
404
+ * @throws {@link CCIPDataFormatUnsupportedError} if view call fails
405
+ */
387
406
  async getTokenForTokenPool(tokenPool: string): Promise<string> {
388
407
  const normalizedTokenPool = normalizeSuiAddress(tokenPool)
389
408
 
@@ -481,7 +500,10 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
481
500
  return coinMetadataAddress
482
501
  }
483
502
 
484
- /** {@inheritDoc Chain.getTokenInfo} */
503
+ /**
504
+ * {@inheritDoc Chain.getTokenInfo}
505
+ * @throws {@link CCIPError} if token address is invalid or metadata cannot be loaded
506
+ */
485
507
  async getTokenInfo(token: string): Promise<{ symbol: string; decimals: number }> {
486
508
  const normalizedTokenAddress = normalizeSuiAddress(token)
487
509
  if (!isValidSuiAddress(normalizedTokenAddress)) {
@@ -558,6 +580,7 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
558
580
  * Decodes a CCIP message from a Sui log event.
559
581
  * @param log - Log event data.
560
582
  * @returns Decoded CCIPMessage or undefined if not valid.
583
+ * @throws {@link CCIPSuiLogInvalidError} if log data format is invalid
561
584
  */
562
585
  static decodeMessage(log: Log_): CCIPMessage | undefined {
563
586
  const { data } = log
@@ -592,6 +615,7 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
592
615
  * Encodes extra arguments for CCIP messages.
593
616
  * @param _extraArgs - Extra arguments to encode.
594
617
  * @returns Encoded extra arguments as a hex string.
618
+ * @throws {@link CCIPNotImplementedError} always (not yet implemented)
595
619
  */
596
620
  static encodeExtraArgs(_extraArgs: ExtraArgs): string {
597
621
  throw new CCIPNotImplementedError()
@@ -723,7 +747,11 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
723
747
  return Promise.reject(new CCIPNotImplementedError('SuiChain.generateUnsignedExecuteReport'))
724
748
  }
725
749
 
726
- /** {@inheritDoc Chain.executeReport} */
750
+ /**
751
+ * {@inheritDoc Chain.executeReport}
752
+ * @throws {@link CCIPError} if transaction submission fails
753
+ * @throws {@link CCIPExecTxRevertedError} if transaction reverts
754
+ */
727
755
  async executeReport(
728
756
  opts: Parameters<Chain['executeReport']>[0] & {
729
757
  receiverObjectIds?: string[]
@@ -838,9 +866,9 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
838
866
  return Promise.reject(new CCIPNotImplementedError('SuiChain.getRegistryTokenConfig'))
839
867
  }
840
868
 
841
- /** {@inheritDoc Chain.getTokenPoolConfigs} */
842
- async getTokenPoolConfigs(_tokenPool: string): Promise<never> {
843
- return Promise.reject(new CCIPNotImplementedError('SuiChain.getTokenPoolConfigs'))
869
+ /** {@inheritDoc Chain.getTokenPoolConfig} */
870
+ async getTokenPoolConfig(_tokenPool: string): Promise<never> {
871
+ return Promise.reject(new CCIPNotImplementedError('SuiChain.getTokenPoolConfig'))
844
872
  }
845
873
 
846
874
  /** {@inheritDoc Chain.getTokenPoolRemotes} */
@@ -872,7 +900,8 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
872
900
  const tokenReceiver =
873
901
  message.extraArgs &&
874
902
  'tokenReceiver' in message.extraArgs &&
875
- message.extraArgs.tokenReceiver != null
903
+ message.extraArgs.tokenReceiver != null &&
904
+ typeof message.extraArgs.tokenReceiver === 'string'
876
905
  ? message.extraArgs.tokenReceiver
877
906
  : message.tokenAmounts?.length
878
907
  ? this.getAddress(message.receiver)