11import {
2- type AnyMessage ,
32 type CCIPVersion ,
43 type ChainStatic ,
54 type EVMChain ,
65 type ExtraArgs ,
6+ type RequestMessage ,
77 CCIPArgumentInvalidError ,
88 CCIPChainFamilyUnsupportedError ,
99 CCIPTokenNotFoundError ,
@@ -13,7 +13,7 @@ import {
1313 networkInfo ,
1414 sourceToDestTokenAmounts ,
1515} from '@chainlink/ccip-sdk/src/index.ts'
16- import { type BytesLike , dataLength , formatUnits , toUtf8Bytes } from 'ethers'
16+ import { type BytesLike , formatUnits , toUtf8Bytes } from 'ethers'
1717import type { Argv } from 'yargs'
1818
1919import type { GlobalOpts } from '../index.ts'
@@ -67,7 +67,6 @@ export const builder = (yargs: Argv) =>
6767 type : 'number' ,
6868 describe :
6969 'Gas limit for receiver callback execution; defaults to default configured on ramps' ,
70- default : 0 ,
7170 } ,
7271 'estimate-gas-limit' : {
7372 type : 'number' ,
@@ -105,10 +104,11 @@ export const builder = (yargs: Argv) =>
105104 describe : "Address of the Solana tokenReceiver (if different than program's receiver)" ,
106105 } ,
107106 account : {
107+ alias : 'receiver-object-id' ,
108108 type : 'array' ,
109109 string : true ,
110110 describe :
111- 'List of accounts needed by Solana receiver program; append `=rw` to specify account as writable; can be specified multiple times' ,
111+ 'List of accounts needed by Solana receiver program, or receiverObjectIds needed by Sui; On Solana, append `=rw` to specify account as writable; can be specified multiple times' ,
112112 example : 'requiredPdaAddress=rw' ,
113113 } ,
114114 'only-get-fee' : {
@@ -159,54 +159,33 @@ async function sendMessage(
159159 const getChain = fetchChainsFromRpcs ( ctx , argv )
160160 const source = await getChain ( sourceNetwork . name )
161161
162- let data : BytesLike
162+ let data : BytesLike | undefined
163163 if ( argv . data ) {
164164 try {
165165 data = getDataBytes ( argv . data )
166166 } catch ( _ ) {
167167 data = toUtf8Bytes ( argv . data )
168168 }
169- } else {
170- data = '0x'
171169 }
172170
173171 const tokenAmounts : { token : string ; amount : bigint } [ ] = argv . transferTokens ?. length
174172 ? await parseTokenAmounts ( source , argv . transferTokens )
175173 : [ ]
176174
177175 let receiver = argv . receiver
178- let tokenReceiver
179176 let accounts ,
180177 accountIsWritableBitmap = 0n
181178 if ( destNetwork . family === ChainFamily . Solana ) {
182- if ( argv . tokenReceiver ) tokenReceiver = argv . tokenReceiver
183- else if ( ! tokenAmounts . length ) {
184- tokenReceiver = '11111111111111111111111111111111'
185- } else if ( ! dataLength ( data ) ) {
186- // sending tokens without data, i.e. not for a receiver contract
187- tokenReceiver = receiver
188- receiver = '11111111111111111111111111111111'
189- } else {
190- throw new CCIPArgumentInvalidError (
191- 'token-receiver' ,
192- 'required when sending tokens with data to Solana' ,
193- )
194- }
195-
196- if ( argv . account ) {
179+ // parse accounts with or without `=rw` suffix
180+ if ( argv . account ?. length ) {
197181 accounts = argv . account . map ( ( account , i ) => {
198182 if ( account . endsWith ( '=rw' ) ) {
199183 accountIsWritableBitmap |= 1n << BigInt ( i )
200184 account = account . substring ( 0 , account . length - 3 )
201185 }
202186 return account
203187 } )
204- } else accounts = [ ] as string [ ]
205- } else if ( argv . tokenReceiver || argv . account ?. length ) {
206- throw new CCIPArgumentInvalidError (
207- 'token-receiver/account' ,
208- 'only valid for Solana destination' ,
209- )
188+ }
210189 }
211190
212191 let walletAddress , wallet
@@ -244,7 +223,7 @@ async function sendMessage(
244223 message : {
245224 sender : walletAddress ,
246225 receiver,
247- data,
226+ data : data || '0x' ,
248227 tokenAmounts : destTokenAmounts ,
249228 } ,
250229 } )
@@ -253,17 +232,19 @@ async function sendMessage(
253232 if ( argv . onlyEstimate ) return
254233 }
255234
256- // `--allow-out-of-order-exec` forces EVMExtraArgsV2 , which shouldn't work on v1.2 lanes;
257- // otherwise, fallsback to EVMExtraArgsV1 (compatible with v1.2 & v1.5)
235+ // builds a catch-all extraArgs object , which can be massaged by
236+ // [[Chain.buildMessageForDest]] to create suitable extraArgs with defaults if needed
258237 const extraArgs = {
259- ...( argv . allowOutOfOrderExec != null || destNetwork . family !== ChainFamily . EVM
260- ? { allowOutOfOrderExecution : ! ! argv . allowOutOfOrderExec }
261- : { } ) ,
262- ...( destNetwork . family === ChainFamily . Solana
263- ? { computeUnits : BigInt ( argv . gasLimit ) }
264- : { gasLimit : BigInt ( argv . gasLimit ) } ) ,
265- ...( tokenReceiver ? { tokenReceiver } : { } ) ,
266- ...( accounts ? { accounts, accountIsWritableBitmap } : { } ) ,
238+ ...( argv . allowOutOfOrderExec != null && {
239+ allowOutOfOrderExecution : ! ! argv . allowOutOfOrderExec ,
240+ } ) ,
241+ ...( argv . gasLimit == null
242+ ? { }
243+ : destNetwork . family === ChainFamily . Solana
244+ ? { computeUnits : BigInt ( argv . gasLimit ) }
245+ : { gasLimit : BigInt ( argv . gasLimit ) } ) ,
246+ ...( ! ! argv . tokenReceiver && { tokenReceiver : argv . tokenReceiver } ) ,
247+ ...( ! ! accounts && { accounts, accountIsWritableBitmap } ) , // accounts also used as Sui receiverObjectIds
267248 }
268249
269250 let feeToken , feeTokenInfo
@@ -287,7 +268,7 @@ async function sendMessage(
287268 feeTokenInfo = await source . getTokenInfo ( nativeToken )
288269 }
289270
290- const message : AnyMessage = {
271+ const message : RequestMessage = {
291272 receiver,
292273 data,
293274 extraArgs : extraArgs as ExtraArgs ,
@@ -322,9 +303,7 @@ async function sendMessage(
322303 } )
323304 logger . info (
324305 '🚀 Sending message to' ,
325- tokenReceiver && tokenReceiver !== '11111111111111111111111111111111'
326- ? tokenReceiver
327- : receiver ,
306+ receiver ,
328307 '@' ,
329308 destNetwork . name ,
330309 ', tx =>' ,
0 commit comments