@chainlink/ccip-sdk 0.94.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 (170) 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 +86 -7
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +270 -10
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/types.d.ts +134 -13
  11. package/dist/api/types.d.ts.map +1 -1
  12. package/dist/aptos/index.d.ts +38 -17
  13. package/dist/aptos/index.d.ts.map +1 -1
  14. package/dist/aptos/index.js +91 -61
  15. package/dist/aptos/index.js.map +1 -1
  16. package/dist/aptos/logs.js +3 -3
  17. package/dist/aptos/logs.js.map +1 -1
  18. package/dist/chain.d.ts +300 -42
  19. package/dist/chain.d.ts.map +1 -1
  20. package/dist/chain.js +160 -9
  21. package/dist/chain.js.map +1 -1
  22. package/dist/errors/codes.d.ts +9 -3
  23. package/dist/errors/codes.d.ts.map +1 -1
  24. package/dist/errors/codes.js +10 -3
  25. package/dist/errors/codes.js.map +1 -1
  26. package/dist/errors/index.d.ts +8 -8
  27. package/dist/errors/index.d.ts.map +1 -1
  28. package/dist/errors/index.js +8 -8
  29. package/dist/errors/index.js.map +1 -1
  30. package/dist/errors/recovery.d.ts.map +1 -1
  31. package/dist/errors/recovery.js +10 -4
  32. package/dist/errors/recovery.js.map +1 -1
  33. package/dist/errors/specialized.d.ts +62 -21
  34. package/dist/errors/specialized.d.ts.map +1 -1
  35. package/dist/errors/specialized.js +128 -41
  36. package/dist/errors/specialized.js.map +1 -1
  37. package/dist/evm/extra-args.d.ts +25 -0
  38. package/dist/evm/extra-args.d.ts.map +1 -0
  39. package/dist/evm/extra-args.js +328 -0
  40. package/dist/evm/extra-args.js.map +1 -0
  41. package/dist/evm/gas.d.ts +14 -0
  42. package/dist/evm/gas.d.ts.map +1 -0
  43. package/dist/evm/gas.js +92 -0
  44. package/dist/evm/gas.js.map +1 -0
  45. package/dist/evm/index.d.ts +76 -32
  46. package/dist/evm/index.d.ts.map +1 -1
  47. package/dist/evm/index.js +94 -104
  48. package/dist/evm/index.js.map +1 -1
  49. package/dist/evm/offchain.d.ts.map +1 -1
  50. package/dist/evm/offchain.js +8 -8
  51. package/dist/evm/offchain.js.map +1 -1
  52. package/dist/execution.d.ts.map +1 -1
  53. package/dist/execution.js +24 -3
  54. package/dist/execution.js.map +1 -1
  55. package/dist/extra-args.d.ts +103 -4
  56. package/dist/extra-args.d.ts.map +1 -1
  57. package/dist/extra-args.js +28 -3
  58. package/dist/extra-args.js.map +1 -1
  59. package/dist/gas.d.ts +46 -19
  60. package/dist/gas.d.ts.map +1 -1
  61. package/dist/gas.js +56 -68
  62. package/dist/gas.js.map +1 -1
  63. package/dist/index.d.ts +18 -15
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +14 -13
  66. package/dist/index.js.map +1 -1
  67. package/dist/offchain.d.ts +5 -4
  68. package/dist/offchain.d.ts.map +1 -1
  69. package/dist/offchain.js +7 -6
  70. package/dist/offchain.js.map +1 -1
  71. package/dist/requests.d.ts +30 -20
  72. package/dist/requests.d.ts.map +1 -1
  73. package/dist/requests.js +86 -56
  74. package/dist/requests.js.map +1 -1
  75. package/dist/selectors.d.ts +2 -1
  76. package/dist/selectors.d.ts.map +1 -1
  77. package/dist/selectors.js +625 -278
  78. package/dist/selectors.js.map +1 -1
  79. package/dist/solana/exec.d.ts.map +1 -1
  80. package/dist/solana/exec.js +2 -1
  81. package/dist/solana/exec.js.map +1 -1
  82. package/dist/solana/index.d.ts +73 -22
  83. package/dist/solana/index.d.ts.map +1 -1
  84. package/dist/solana/index.js +91 -28
  85. package/dist/solana/index.js.map +1 -1
  86. package/dist/solana/offchain.js +2 -2
  87. package/dist/solana/offchain.js.map +1 -1
  88. package/dist/solana/send.d.ts.map +1 -1
  89. package/dist/solana/send.js +6 -9
  90. package/dist/solana/send.js.map +1 -1
  91. package/dist/solana/utils.d.ts +29 -1
  92. package/dist/solana/utils.d.ts.map +1 -1
  93. package/dist/solana/utils.js +39 -1
  94. package/dist/solana/utils.js.map +1 -1
  95. package/dist/sui/discovery.d.ts +7 -4
  96. package/dist/sui/discovery.d.ts.map +1 -1
  97. package/dist/sui/discovery.js +66 -19
  98. package/dist/sui/discovery.js.map +1 -1
  99. package/dist/sui/events.d.ts +23 -12
  100. package/dist/sui/events.d.ts.map +1 -1
  101. package/dist/sui/events.js +267 -128
  102. package/dist/sui/events.js.map +1 -1
  103. package/dist/sui/index.d.ts +57 -41
  104. package/dist/sui/index.d.ts.map +1 -1
  105. package/dist/sui/index.js +286 -159
  106. package/dist/sui/index.js.map +1 -1
  107. package/dist/sui/objects.d.ts +14 -4
  108. package/dist/sui/objects.d.ts.map +1 -1
  109. package/dist/sui/objects.js +61 -68
  110. package/dist/sui/objects.js.map +1 -1
  111. package/dist/sui/types.d.ts +33 -0
  112. package/dist/sui/types.d.ts.map +1 -1
  113. package/dist/sui/types.js.map +1 -1
  114. package/dist/ton/index.d.ts +67 -21
  115. package/dist/ton/index.d.ts.map +1 -1
  116. package/dist/ton/index.js +159 -30
  117. package/dist/ton/index.js.map +1 -1
  118. package/dist/ton/send.d.ts +52 -0
  119. package/dist/ton/send.d.ts.map +1 -0
  120. package/dist/ton/send.js +166 -0
  121. package/dist/ton/send.js.map +1 -0
  122. package/dist/ton/utils.d.ts +3 -3
  123. package/dist/ton/utils.d.ts.map +1 -1
  124. package/dist/ton/utils.js +6 -5
  125. package/dist/ton/utils.js.map +1 -1
  126. package/dist/types.d.ts +126 -9
  127. package/dist/types.d.ts.map +1 -1
  128. package/dist/types.js +19 -5
  129. package/dist/types.js.map +1 -1
  130. package/dist/utils.d.ts +67 -4
  131. package/dist/utils.d.ts.map +1 -1
  132. package/dist/utils.js +126 -17
  133. package/dist/utils.js.map +1 -1
  134. package/package.json +14 -9
  135. package/src/all-chains.ts +26 -0
  136. package/src/api/index.ts +348 -13
  137. package/src/api/types.ts +160 -13
  138. package/src/aptos/index.ts +98 -76
  139. package/src/aptos/logs.ts +3 -3
  140. package/src/chain.ts +408 -51
  141. package/src/errors/codes.ts +10 -3
  142. package/src/errors/index.ts +8 -5
  143. package/src/errors/recovery.ts +18 -5
  144. package/src/errors/specialized.ts +168 -49
  145. package/src/evm/extra-args.ts +377 -0
  146. package/src/evm/gas.ts +150 -0
  147. package/src/evm/index.ts +123 -155
  148. package/src/evm/offchain.ts +15 -9
  149. package/src/execution.ts +26 -3
  150. package/src/extra-args.ts +108 -4
  151. package/src/gas.ts +101 -115
  152. package/src/index.ts +27 -14
  153. package/src/offchain.ts +12 -6
  154. package/src/requests.ts +117 -67
  155. package/src/selectors.ts +632 -280
  156. package/src/solana/exec.ts +3 -1
  157. package/src/solana/index.ts +97 -37
  158. package/src/solana/offchain.ts +2 -2
  159. package/src/solana/send.ts +5 -23
  160. package/src/solana/utils.ts +66 -0
  161. package/src/sui/discovery.ts +92 -31
  162. package/src/sui/events.ts +346 -239
  163. package/src/sui/index.ts +365 -212
  164. package/src/sui/objects.ts +74 -98
  165. package/src/sui/types.ts +35 -0
  166. package/src/ton/index.ts +199 -35
  167. package/src/ton/send.ts +222 -0
  168. package/src/ton/utils.ts +7 -6
  169. package/src/types.ts +128 -9
  170. package/src/utils.ts +169 -21
package/src/extra-args.ts CHANGED
@@ -8,6 +8,8 @@ import { ChainFamily } from './types.ts'
8
8
  export const EVMExtraArgsV1Tag = id('CCIP EVMExtraArgsV1').substring(0, 10) as '0x97a657c9'
9
9
  /** Tag identifier for EVMExtraArgsV2 encoding. */
10
10
  export const EVMExtraArgsV2Tag = id('CCIP EVMExtraArgsV2').substring(0, 10) as '0x181dcf10'
11
+ /** Tag identifier for GenericExtraArgsV3 encoding (tightly packed binary format). */
12
+ export const GenericExtraArgsV3Tag = '0x302326cb' as const
11
13
  /** Tag identifier for SVMExtraArgsV1 encoding. */
12
14
  export const SVMExtraArgsV1Tag = id('CCIP SVMExtraArgsV1').substring(0, 10) as '0x1f3b3aba'
13
15
  /** Tag identifier for SuiExtraArgsV1 encoding. */
@@ -15,6 +17,13 @@ export const SuiExtraArgsV1Tag = id('CCIP SuiExtraArgsV1').substring(0, 10) as '
15
17
 
16
18
  /**
17
19
  * EVM extra arguments version 1 with gas limit only.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const args: EVMExtraArgsV1 = {
24
+ * gasLimit: 200_000n,
25
+ * }
26
+ * ```
18
27
  */
19
28
  export type EVMExtraArgsV1 = {
20
29
  /** Gas limit for execution on the destination chain. */
@@ -24,14 +33,70 @@ export type EVMExtraArgsV1 = {
24
33
  /**
25
34
  * EVM extra arguments version 2 with out-of-order execution support.
26
35
  * Also known as GenericExtraArgsV2.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const args: EVMExtraArgsV2 = {
40
+ * gasLimit: 200_000n,
41
+ * allowOutOfOrderExecution: true,
42
+ * }
43
+ * ```
27
44
  */
28
45
  export type EVMExtraArgsV2 = EVMExtraArgsV1 & {
29
46
  /** Whether to allow out-of-order message execution. */
30
47
  allowOutOfOrderExecution: boolean
31
48
  }
32
49
 
50
+ /**
51
+ * Generic extra arguments version 3 with cross-chain verifiers and executor support.
52
+ * Uses tightly packed binary encoding (NOT ABI-encoded).
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const args: GenericExtraArgsV3 = {
57
+ * gasLimit: 200_000n,
58
+ * blockConfirmations: 5,
59
+ * ccvs: ['0x1234...'],
60
+ * ccvArgs: ['0x010203'],
61
+ * executor: '0x5678...',
62
+ * executorArgs: '0x',
63
+ * tokenReceiver: '0xReceiverAddress...',
64
+ * tokenArgs: '0x',
65
+ * }
66
+ * ```
67
+ */
68
+ export type GenericExtraArgsV3 = {
69
+ /** Gas limit for execution on the destination chain (uint32). */
70
+ gasLimit: bigint
71
+ /** Number of block confirmations required. */
72
+ blockConfirmations: number
73
+ /** Cross-chain verifier addresses (EVM addresses). */
74
+ ccvs: string[]
75
+ /** Per-CCV arguments (BytesLike). */
76
+ ccvArgs: BytesLike[]
77
+ /** Executor address (EVM address or empty string for none). */
78
+ executor: string
79
+ /** Executor-specific arguments (BytesLike). */
80
+ executorArgs: BytesLike
81
+ /** Token receiver address (checksummed EVM address or hex string). */
82
+ tokenReceiver: string
83
+ /** Token pool-specific arguments (BytesLike). */
84
+ tokenArgs: BytesLike
85
+ }
86
+
33
87
  /**
34
88
  * Solana (SVM) extra arguments version 1.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const args: SVMExtraArgsV1 = {
93
+ * computeUnits: 200_000n,
94
+ * accountIsWritableBitmap: 0n,
95
+ * allowOutOfOrderExecution: true,
96
+ * tokenReceiver: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
97
+ * accounts: [],
98
+ * }
99
+ * ```
35
100
  */
36
101
  export type SVMExtraArgsV1 = {
37
102
  /** Compute units for Solana execution. */
@@ -48,6 +113,16 @@ export type SVMExtraArgsV1 = {
48
113
 
49
114
  /**
50
115
  * Sui extra arguments version 1.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const args: SuiExtraArgsV1 = {
120
+ * gasLimit: 200_000n,
121
+ * allowOutOfOrderExecution: true,
122
+ * tokenReceiver: '0x1234...abcd',
123
+ * receiverObjectIds: ['0xobject1...', '0xobject2...'],
124
+ * }
125
+ * ```
51
126
  */
52
127
  export type SuiExtraArgsV1 = EVMExtraArgsV2 & {
53
128
  /** Token receiver address on Sui. */
@@ -59,13 +134,31 @@ export type SuiExtraArgsV1 = EVMExtraArgsV2 & {
59
134
  /**
60
135
  * Union type of all supported extra arguments formats.
61
136
  */
62
- export type ExtraArgs = EVMExtraArgsV1 | EVMExtraArgsV2 | SVMExtraArgsV1 | SuiExtraArgsV1
137
+ export type ExtraArgs =
138
+ | EVMExtraArgsV1
139
+ | EVMExtraArgsV2
140
+ | GenericExtraArgsV3
141
+ | SVMExtraArgsV1
142
+ | SuiExtraArgsV1
63
143
 
64
144
  /**
65
145
  * Encodes extra arguments for CCIP messages.
66
- * The args are *to* a dest network, but are encoded as a message *from* this source chain
67
- * e.g. Solana uses Borsh to encode extraArgs in its produced requests, even those targetting EVM
68
- **/
146
+ * The args are *to* a dest network, but are encoded as a message *from* this source chain.
147
+ * E.g. Solana uses Borsh to encode extraArgs in its produced requests, even those targeting EVM.
148
+ * @param args - Extra arguments to encode
149
+ * @param from - Source chain family for encoding format (defaults to EVM)
150
+ * @returns Encoded extra arguments as hex string
151
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const encoded = encodeExtraArgs({
156
+ * gasLimit: 200_000n,
157
+ * allowOutOfOrderExecution: true,
158
+ * })
159
+ * // Returns: '0x181dcf10...'
160
+ * ```
161
+ */
69
162
  export function encodeExtraArgs(args: ExtraArgs, from: ChainFamily = ChainFamily.EVM): string {
70
163
  const chain = supportedChains[from]
71
164
  if (!chain) throw new CCIPChainFamilyUnsupportedError(from)
@@ -77,6 +170,16 @@ export function encodeExtraArgs(args: ExtraArgs, from: ChainFamily = ChainFamily
77
170
  * @param data - Extra arguments bytearray data.
78
171
  * @param from - Optional chain family to narrow decoding attempts.
79
172
  * @returns Extra arguments object if found, undefined otherwise.
173
+ * @throws {@link CCIPChainFamilyUnsupportedError} if specified chain family not supported
174
+ * @throws {@link CCIPExtraArgsParseError} if data cannot be parsed as valid extra args
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const decoded = decodeExtraArgs('0x181dcf10...')
179
+ * if (decoded?._tag === 'EVMExtraArgsV2') {
180
+ * console.log(decoded.gasLimit, decoded.allowOutOfOrderExecution)
181
+ * }
182
+ * ```
80
183
  */
81
184
  export function decodeExtraArgs(
82
185
  data: BytesLike,
@@ -84,6 +187,7 @@ export function decodeExtraArgs(
84
187
  ):
85
188
  | (EVMExtraArgsV1 & { _tag: 'EVMExtraArgsV1' })
86
189
  | (EVMExtraArgsV2 & { _tag: 'EVMExtraArgsV2' })
190
+ | (GenericExtraArgsV3 & { _tag: 'GenericExtraArgsV3' })
87
191
  | (SVMExtraArgsV1 & { _tag: 'SVMExtraArgsV1' })
88
192
  | (SuiExtraArgsV1 & { _tag: 'SuiExtraArgsV1' })
89
193
  | undefined {
package/src/gas.ts CHANGED
@@ -1,140 +1,126 @@
1
- import {
2
- type BytesLike,
3
- Contract,
4
- FunctionFragment,
5
- concat,
6
- formatUnits,
7
- getNumber,
8
- hexlify,
9
- randomBytes,
10
- solidityPackedKeccak256,
11
- toBeHex,
12
- zeroPadValue,
13
- } from 'ethers'
14
- import type { TypedContract } from 'ethers-abitype'
1
+ import { type BytesLike, formatUnits, hexlify, randomBytes } from 'ethers'
15
2
 
16
3
  import type { Chain } from './chain.ts'
17
4
  import {
18
- CCIPLegacyTokenPoolsUnsupportedError,
5
+ CCIPContractTypeInvalidError,
6
+ CCIPMethodUnsupportedError,
19
7
  CCIPTokenDecimalsInsufficientError,
20
8
  } from './errors/index.ts'
21
- import TokenABI from './evm/abi/BurnMintERC677Token.ts'
22
- import RouterABI from './evm/abi/Router.ts'
23
- import { defaultAbiCoder } from './evm/const.ts'
24
- import type { EVMChain } from './evm/index.ts'
25
9
  import { discoverOffRamp } from './execution.ts'
26
- import type { Lane } from './types.ts'
10
+ import { sourceToDestTokenAddresses } from './requests.ts'
27
11
 
28
- const BALANCES_SLOT = 0
29
- const ccipReceive = FunctionFragment.from({
30
- type: 'function',
31
- name: 'ccipReceive',
32
- stateMutability: 'nonpayable',
33
- inputs: RouterABI.find((v) => v.type === 'function' && v.name === 'routeMessage')!.inputs.slice(
34
- 0,
35
- 1,
36
- ),
37
- outputs: [],
38
- })
39
- type Any2EVMMessage = Parameters<TypedContract<typeof RouterABI>['routeMessage']>[0]
12
+ /**
13
+ * A subset of {@link MessageInput} for estimating receive execution gas.
14
+ */
15
+ export type EstimateMessageInput = {
16
+ /** receiver contract address */
17
+ receiver: string
18
+ /** optional messageId; random hash will be passed if omitted */
19
+ messageId?: string
20
+ /** optional sender: zero address will be used if omitted */
21
+ sender?: string
22
+ /** optional data: zero bytes will be used if omitted */
23
+ data?: BytesLike
24
+ /**
25
+ * optional tokenAmounts; `amount` with either source `token` (as in MessageInput) or
26
+ * `{ sourceTokenAddress?, sourcePoolAddress, destTokenAddress }` (as in v1.5..v1.7 tokenAmounts)
27
+ * can be provided
28
+ */
29
+ tokenAmounts?: readonly ({
30
+ amount: bigint
31
+ } & (
32
+ | { token: string }
33
+ | { sourceTokenAddress?: string; sourcePoolAddress: string; destTokenAddress: string }
34
+ ))[]
35
+ }
36
+
37
+ /**
38
+ * Options for {@link estimateReceiveExecution} function.
39
+ */
40
+ export type EstimateReceiveExecutionOpts = {
41
+ /** Source chain instance (for token data retrieval) */
42
+ source: Chain
43
+ /** Dest chain instance (for token and execution simulation) */
44
+ dest: Chain
45
+ /** source router or onRamp, or dest offRamp contract address */
46
+ routerOrRamp: string
47
+ /** message to be simulated */
48
+ message: EstimateMessageInput
49
+ }
40
50
 
41
51
  /**
42
52
  * Estimate CCIP gasLimit needed to execute a request on a contract receiver.
43
- * @param source - Provider for the source chain.
44
- * @param dest - Provider for the destination chain.
45
- * @param request - CCIP request info containing `lane` and `message` details.
46
- * @returns Estimated gasLimit as bigint.
53
+ * @param opts - Options for estimation: source and dest chains, router or ramp address, and message
54
+ * @returns Estimated gasLimit.
55
+ * @throws {@link CCIPMethodUnsupportedError} if dest chain doesn't support estimation
56
+ * @throws {@link CCIPContractTypeInvalidError} if routerOrRamp is not a valid contract type
57
+ * @throws {@link CCIPTokenDecimalsInsufficientError} if dest token has insufficient decimals
47
58
  */
48
- export async function estimateExecGasForRequest(
49
- source: Chain,
50
- dest: EVMChain,
51
- request: {
52
- lane: Lane
53
- message: {
54
- sender: string
55
- receiver: string
56
- data: BytesLike
57
- tokenAmounts: readonly {
58
- sourcePoolAddress: string
59
- destTokenAddress: string
60
- amount: bigint
61
- }[]
59
+ export async function estimateReceiveExecution({
60
+ source,
61
+ dest,
62
+ routerOrRamp,
63
+ message,
64
+ }: EstimateReceiveExecutionOpts) {
65
+ if (!dest.estimateReceiveExecution)
66
+ throw new CCIPMethodUnsupportedError(dest.constructor.name, 'estimateReceiveExecution')
67
+
68
+ let onRamp, offRamp: string
69
+ try {
70
+ const tnv = await source.typeAndVersion(routerOrRamp)
71
+ if (!tnv[0].includes('OnRamp'))
72
+ onRamp = await source.getOnRampForRouter(routerOrRamp, dest.network.chainSelector)
73
+ else onRamp = routerOrRamp
74
+ offRamp = await discoverOffRamp(source, dest, onRamp, source)
75
+ } catch (sourceErr) {
76
+ try {
77
+ const tnv = await dest.typeAndVersion(routerOrRamp)
78
+ if (!tnv[0].includes('OffRamp'))
79
+ throw new CCIPContractTypeInvalidError(routerOrRamp, tnv[2], ['OffRamp'])
80
+ offRamp = routerOrRamp
81
+ onRamp = await dest.getOnRampForOffRamp(offRamp, source.network.chainSelector)
82
+ } catch {
83
+ throw sourceErr // re-throw original error
62
84
  }
63
- },
64
- ) {
65
- const offRamp = await discoverOffRamp(source, dest, request.lane.onRamp, source)
66
- const destRouter = await dest.getRouterForOffRamp(offRamp, request.lane.sourceChainSelector)
85
+ }
67
86
 
68
87
  const destTokenAmounts = await Promise.all(
69
- request.message.tokenAmounts.map(async (ta) => {
70
- if (!('destTokenAddress' in ta)) throw new CCIPLegacyTokenPoolsUnsupportedError()
88
+ (message.tokenAmounts ?? []).map(async (ta) => {
89
+ const tokenAmount =
90
+ 'destTokenAddress' in ta
91
+ ? ta
92
+ : await sourceToDestTokenAddresses(source, dest.network.chainSelector, onRamp, ta)
93
+ const sourceTokenAddress =
94
+ 'token' in ta
95
+ ? ta.token
96
+ : ta.sourceTokenAddress
97
+ ? ta.sourceTokenAddress
98
+ : await source.getTokenForTokenPool(tokenAmount.sourcePoolAddress)
71
99
  const [{ decimals: sourceDecimals }, { decimals: destDecimals }] = await Promise.all([
72
- source
73
- .getTokenForTokenPool(ta.sourcePoolAddress)
74
- .then((token) => source.getTokenInfo(token)),
75
- dest.getTokenInfo(ta.destTokenAddress),
100
+ source.getTokenInfo(sourceTokenAddress),
101
+ dest.getTokenInfo(tokenAmount.destTokenAddress),
76
102
  ])
77
103
  const destAmount =
78
- (ta.amount * 10n ** BigInt(destDecimals - sourceDecimals + 36)) / 10n ** 36n
104
+ (tokenAmount.amount * 10n ** BigInt(destDecimals)) / 10n ** BigInt(sourceDecimals)
79
105
  if (destAmount === 0n)
80
106
  throw new CCIPTokenDecimalsInsufficientError(
81
- ta.destTokenAddress,
107
+ tokenAmount.destTokenAddress,
82
108
  destDecimals,
83
109
  dest.network.name,
84
- formatUnits(ta.amount, sourceDecimals),
110
+ formatUnits(tokenAmount.amount, sourceDecimals),
85
111
  )
86
- return { token: ta.destTokenAddress, amount: destAmount }
112
+ return { token: tokenAmount.destTokenAddress, amount: destAmount }
87
113
  }),
88
114
  )
89
-
90
- const message: Any2EVMMessage = {
91
- messageId: hexlify(randomBytes(32)),
92
- sender: zeroPadValue(request.message.sender, 32),
93
- data: hexlify(request.message.data),
94
- sourceChainSelector: request.lane.sourceChainSelector,
95
- destTokenAmounts,
96
- }
97
-
98
- // we need to override the state, increasing receiver's balance for each token, to simulate the
99
- // state after tokens were transferred by the offRamp just before calling `ccipReceive`
100
- const destAmounts: Record<string, bigint> = {}
101
- const stateOverrides: Record<string, { stateDiff: Record<string, string> }> = {}
102
- for (const { token, amount } of destTokenAmounts) {
103
- if (!(token in destAmounts)) {
104
- const tokenContract = new Contract(token, TokenABI, dest) as unknown as TypedContract<
105
- typeof TokenABI
106
- >
107
- const currentBalance = await tokenContract.balanceOf(request.message.receiver)
108
- destAmounts[token] = currentBalance
109
- }
110
- destAmounts[token]! += amount
111
- stateOverrides[token] = {
112
- stateDiff: {
113
- [solidityPackedKeccak256(
114
- ['uint256', 'uint256'],
115
- [request.message.receiver, BALANCES_SLOT],
116
- )]: toBeHex(destAmounts[token]!, 32),
117
- },
118
- }
119
- }
120
-
121
- const calldata = concat([
122
- ccipReceive.selector,
123
- defaultAbiCoder.encode(ccipReceive.inputs, [message]),
124
- ])
125
-
126
- return (
127
- getNumber(
128
- (await dest.provider.send('eth_estimateGas', [
129
- {
130
- from: destRouter,
131
- to: request.message.receiver,
132
- data: calldata,
133
- },
134
- 'latest',
135
- ...(Object.keys(stateOverrides).length ? [stateOverrides] : []),
136
- ])) as string,
137
- ) -
138
- (21_000 - 700) // 21k is the base gas cost for a transaction, 700 is the gas cost of the call
139
- )
115
+ return dest.estimateReceiveExecution({
116
+ receiver: message.receiver,
117
+ offRamp,
118
+ message: {
119
+ messageId: message.messageId ?? hexlify(randomBytes(32)),
120
+ sender: message.sender,
121
+ data: message.data,
122
+ sourceChainSelector: source.network.chainSelector,
123
+ destTokenAmounts,
124
+ },
125
+ })
140
126
  }
package/src/index.ts CHANGED
@@ -1,16 +1,35 @@
1
- export type { APIErrorResponse, CCIPAPIClientContext, LaneLatencyResponse } from './api/index.ts'
1
+ /**
2
+ * \@chainlink/ccip-sdk - SDK for interacting with Chainlink CCIP (Cross-Chain Interoperability Protocol).
3
+ *
4
+ * This package provides tools for sending cross-chain messages, tracking message status,
5
+ * and executing manual message delivery across supported blockchain networks.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ export type {
11
+ APICCIPRequestMetadata,
12
+ APIErrorResponse,
13
+ CCIPAPIClientContext,
14
+ LaneLatencyResponse,
15
+ } from './api/index.ts'
2
16
  export { CCIPAPIClient, DEFAULT_API_BASE_URL } from './api/index.ts'
3
17
 
4
18
  export type {
19
+ ApiRetryConfig,
5
20
  Chain,
6
21
  ChainContext,
7
22
  ChainGetter,
8
23
  ChainStatic,
24
+ GetBalanceOpts,
9
25
  LogFilter,
10
26
  RateLimiterState,
27
+ RegistryTokenConfig,
11
28
  TokenInfo,
29
+ TokenPoolConfig,
12
30
  TokenPoolRemote,
13
31
  } from './chain.ts'
32
+ export { DEFAULT_API_RETRY_CONFIG } from './chain.ts'
14
33
  export { calculateManualExecProof, discoverOffRamp } from './execution.ts'
15
34
  export {
16
35
  type EVMExtraArgsV1,
@@ -21,8 +40,8 @@ export {
21
40
  decodeExtraArgs,
22
41
  encodeExtraArgs,
23
42
  } from './extra-args.ts'
24
- export { estimateExecGasForRequest } from './gas.ts'
25
- export { decodeMessage, getMessagesForSender, sourceToDestTokenAmounts } from './requests.ts'
43
+ export { estimateReceiveExecution } from './gas.ts'
44
+ export { decodeMessage, getMessagesForSender, sourceToDestTokenAddresses } from './requests.ts'
26
45
  export {
27
46
  type CCIPCommit,
28
47
  type CCIPExecution,
@@ -34,15 +53,16 @@ export {
34
53
  type ExecutionReport,
35
54
  type Lane,
36
55
  type Logger,
56
+ type MessageInput,
37
57
  type NetworkInfo,
38
58
  type OffchainTokenData,
39
- type MessageInput,
40
59
  type WithLogger,
41
60
  CCIPVersion,
42
61
  ExecutionState,
43
62
  IntentStatus,
44
63
  MessageStatus,
45
64
  } from './types.ts'
65
+ export type { WithRetryConfig } from './utils.ts'
46
66
  export {
47
67
  bigIntReplacer,
48
68
  bigIntReviver,
@@ -51,6 +71,7 @@ export {
51
71
  getDataBytes,
52
72
  isSupportedTxHash,
53
73
  networkInfo,
74
+ withRetry,
54
75
  } from './utils.ts'
55
76
  export {
56
77
  type CCIPExplorerLinks,
@@ -73,15 +94,7 @@ export type { UnsignedSolanaTx } from './solana/index.ts'
73
94
  import { SuiChain } from './sui/index.ts'
74
95
  import { TONChain } from './ton/index.ts'
75
96
  export type { UnsignedTONTx } from './ton/index.ts'
76
- import { ChainFamily } from './types.ts'
77
- export { AptosChain, ChainFamily, EVMChain, SolanaChain, SuiChain, TONChain }
97
+ import { ChainFamily, NetworkType } from './types.ts'
98
+ export { AptosChain, ChainFamily, EVMChain, NetworkType, SolanaChain, SuiChain, TONChain }
78
99
  // use `supportedChains` to override/register derived classes, if needed
79
100
  export { supportedChains } from './supported-chains.ts'
80
- // import `allSupportedChains` to get them all registered, in tree-shaken environments
81
- export const allSupportedChains = {
82
- [ChainFamily.EVM]: EVMChain,
83
- [ChainFamily.Solana]: SolanaChain,
84
- [ChainFamily.Aptos]: AptosChain,
85
- [ChainFamily.Sui]: SuiChain,
86
- [ChainFamily.TON]: TONChain,
87
- }
package/src/offchain.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  CCIPLbtcAttestationNotFoundError,
6
6
  CCIPUsdcAttestationError,
7
7
  } from './errors/index.ts'
8
+ import { NetworkType } from './types.ts'
8
9
 
9
10
  const CIRCLE_API_URL = {
10
11
  mainnet: 'https://iris-api.circle.com/v1',
@@ -31,13 +32,17 @@ type LombardAttestationsResponse = { attestations: Array<LombardAttestation> }
31
32
  * https://developers.circle.com/stablecoins/reference/getattestation
32
33
  *
33
34
  * @param message - payload of USDC MessageSent(bytes message) event
34
- * @param isTestnet - true if this was from a testnet
35
+ * @param networkType - network type (mainnet or testnet)
35
36
  * @returns USDC/CCTP attestation bytes
36
37
  */
37
- export async function getUsdcAttestation(message: string, isTestnet: boolean): Promise<string> {
38
+ export async function getUsdcAttestation(
39
+ message: string,
40
+ networkType: NetworkType,
41
+ ): Promise<string> {
38
42
  const msgHash = keccak256(message)
39
43
 
40
- const circleApiBaseUrl = isTestnet ? CIRCLE_API_URL.testnet : CIRCLE_API_URL.mainnet
44
+ const circleApiBaseUrl =
45
+ networkType === NetworkType.Mainnet ? CIRCLE_API_URL.mainnet : CIRCLE_API_URL.testnet
41
46
  const res = await fetch(`${circleApiBaseUrl}/attestations/${msgHash}`)
42
47
  const json = (await res.json()) as CctpAttestationResponse
43
48
  if (!('status' in json) || json.status !== 'complete' || !json.attestation) {
@@ -50,16 +55,17 @@ export async function getUsdcAttestation(message: string, isTestnet: boolean): P
50
55
  * Returns the LBTC attestation for a given payload hash
51
56
  *
52
57
  * @param payloadHash - hash of the payload of the LBTC transfer
53
- * @param isTestnet - true if this was from a testnet
58
+ * @param networkType - network type (mainnet or testnet)
54
59
  * @returns LBTC attestation bytes
55
60
  */
56
61
  export async function getLbtcAttestation(
57
62
  payloadHash: string,
58
- isTestnet: boolean,
63
+ networkType: NetworkType,
59
64
  ): Promise<{
60
65
  attestation: string
61
66
  }> {
62
- const lbtcApiBaseUrl = isTestnet ? LOMBARD_API_URL.testnet : LOMBARD_API_URL.mainnet
67
+ const lbtcApiBaseUrl =
68
+ networkType === NetworkType.Mainnet ? LOMBARD_API_URL.mainnet : LOMBARD_API_URL.testnet
63
69
  const res = await fetch(`${lbtcApiBaseUrl}/api/bridge/v1/deposits/getByHash`, {
64
70
  method: 'POST',
65
71
  body: JSON.stringify({ messageHash: [payloadHash] }),