@chainlink/ccip-cli 0.90.2 → 0.91.1

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 (68) hide show
  1. package/README.md +40 -21
  2. package/dist/commands/index.d.ts +2 -1
  3. package/dist/commands/index.d.ts.map +1 -1
  4. package/dist/commands/index.js +1 -0
  5. package/dist/commands/index.js.map +1 -1
  6. package/dist/commands/manual-exec.d.ts +9 -0
  7. package/dist/commands/manual-exec.d.ts.map +1 -1
  8. package/dist/commands/manual-exec.js +40 -35
  9. package/dist/commands/manual-exec.js.map +1 -1
  10. package/dist/commands/parse.d.ts +9 -0
  11. package/dist/commands/parse.d.ts.map +1 -1
  12. package/dist/commands/parse.js +18 -7
  13. package/dist/commands/parse.js.map +1 -1
  14. package/dist/commands/send.d.ts +9 -0
  15. package/dist/commands/send.d.ts.map +1 -1
  16. package/dist/commands/send.js +39 -26
  17. package/dist/commands/send.js.map +1 -1
  18. package/dist/commands/show.d.ts +9 -0
  19. package/dist/commands/show.d.ts.map +1 -1
  20. package/dist/commands/show.js +46 -39
  21. package/dist/commands/show.js.map +1 -1
  22. package/dist/commands/supported-tokens.d.ts +9 -2
  23. package/dist/commands/supported-tokens.d.ts.map +1 -1
  24. package/dist/commands/supported-tokens.js +35 -30
  25. package/dist/commands/supported-tokens.js.map +1 -1
  26. package/dist/commands/types.d.ts +13 -0
  27. package/dist/commands/types.d.ts.map +1 -1
  28. package/dist/commands/types.js +1 -0
  29. package/dist/commands/types.js.map +1 -1
  30. package/dist/commands/utils.d.ts +75 -10
  31. package/dist/commands/utils.d.ts.map +1 -1
  32. package/dist/commands/utils.js +95 -19
  33. package/dist/commands/utils.js.map +1 -1
  34. package/dist/index.d.ts +2 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +24 -7
  37. package/dist/index.js.map +1 -1
  38. package/dist/providers/aptos.d.ts +35 -0
  39. package/dist/providers/aptos.d.ts.map +1 -1
  40. package/dist/providers/aptos.js +34 -9
  41. package/dist/providers/aptos.js.map +1 -1
  42. package/dist/providers/evm.d.ts +10 -1
  43. package/dist/providers/evm.d.ts.map +1 -1
  44. package/dist/providers/evm.js +11 -5
  45. package/dist/providers/evm.js.map +1 -1
  46. package/dist/providers/index.d.ts +15 -8
  47. package/dist/providers/index.d.ts.map +1 -1
  48. package/dist/providers/index.js +47 -11
  49. package/dist/providers/index.js.map +1 -1
  50. package/dist/providers/solana.d.ts +30 -0
  51. package/dist/providers/solana.d.ts.map +1 -1
  52. package/dist/providers/solana.js +30 -5
  53. package/dist/providers/solana.js.map +1 -1
  54. package/package.json +11 -8
  55. package/src/commands/index.ts +2 -1
  56. package/src/commands/manual-exec.ts +40 -33
  57. package/src/commands/parse.ts +19 -8
  58. package/src/commands/send.ts +47 -30
  59. package/src/commands/show.ts +47 -48
  60. package/src/commands/supported-tokens.ts +35 -30
  61. package/src/commands/types.ts +15 -0
  62. package/src/commands/utils.ts +112 -26
  63. package/src/index.ts +29 -7
  64. package/src/providers/aptos.ts +33 -8
  65. package/src/providers/evm.ts +22 -5
  66. package/src/providers/index.ts +67 -15
  67. package/src/providers/solana.ts +31 -6
  68. package/tsconfig.json +2 -1
@@ -7,7 +7,6 @@ import {
7
7
  ChainFamily,
8
8
  bigIntReplacer,
9
9
  estimateExecGasForRequest,
10
- fetchCCIPRequestsInTx,
11
10
  getDataBytes,
12
11
  networkInfo,
13
12
  sourceToDestTokenAmounts,
@@ -16,13 +15,24 @@ import { type BytesLike, dataLength, formatUnits, toUtf8Bytes } from 'ethers'
16
15
  import type { Argv } from 'yargs'
17
16
 
18
17
  import type { GlobalOpts } from '../index.ts'
19
- import { Format } from './types.ts'
20
- import { logParsedError, parseTokenAmounts, prettyRequest, withDateTimestamp } from './utils.ts'
21
- import { fetchChainsFromRpcs } from '../providers/index.ts'
18
+ import { type Ctx, Format } from './types.ts'
19
+ import {
20
+ getCtx,
21
+ logParsedError,
22
+ parseTokenAmounts,
23
+ prettyRequest,
24
+ withDateTimestamp,
25
+ } from './utils.ts'
26
+ import { fetchChainsFromRpcs, loadChainWallet } from '../providers/index.ts'
22
27
 
23
28
  export const command = 'send <source> <router> <dest>'
24
29
  export const describe = 'Send a CCIP message from router on source to dest'
25
30
 
31
+ /**
32
+ * Yargs builder for the send command.
33
+ * @param yargs - Yargs instance.
34
+ * @returns Configured yargs instance with command options.
35
+ */
26
36
  export const builder = (yargs: Argv) =>
27
37
  yargs
28
38
  .positional('source', {
@@ -123,26 +133,28 @@ export const builder = (yargs: Argv) =>
123
133
  !transferTokens || transferTokens.every((t) => /^[^=]+=\d+(\.\d+)?$/.test(t)),
124
134
  )
125
135
 
136
+ /**
137
+ * Handler for the send command.
138
+ * @param argv - Command line arguments.
139
+ */
126
140
  export async function handler(argv: Awaited<ReturnType<typeof builder>['argv']> & GlobalOpts) {
127
- let destroy
128
- const destroy$ = new Promise((resolve) => {
129
- destroy = resolve
130
- })
131
- return sendMessage(argv, destroy$)
141
+ const [controller, ctx] = getCtx(argv)
142
+ return sendMessage(ctx, argv)
132
143
  .catch((err) => {
133
144
  process.exitCode = 1
134
- if (!logParsedError(err)) console.error(err)
145
+ if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
135
146
  })
136
- .finally(destroy)
147
+ .finally(() => controller.abort('Exited'))
137
148
  }
138
149
 
139
150
  async function sendMessage(
151
+ ctx: Ctx,
140
152
  argv: Awaited<ReturnType<typeof builder>['argv']> & GlobalOpts,
141
- destroy: Promise<unknown>,
142
153
  ) {
154
+ const { logger } = ctx
143
155
  const sourceNetwork = networkInfo(argv.source)
144
156
  const destNetwork = networkInfo(argv.dest)
145
- const getChain = fetchChainsFromRpcs(argv, undefined, destroy)
157
+ const getChain = fetchChainsFromRpcs(ctx, argv)
146
158
  const source = await getChain(sourceNetwork.name)
147
159
 
148
160
  let data: BytesLike
@@ -189,10 +201,12 @@ async function sendMessage(
189
201
  throw new Error('--token-receiver and --account intended only for Solana dest')
190
202
  }
191
203
 
204
+ let walletAddress, wallet
192
205
  if (!receiver) {
193
206
  if (sourceNetwork.family !== destNetwork.family)
194
207
  throw new Error('--receiver is required when sending to a different chain family')
195
- receiver = await source.getWalletAddress(argv) // send to self if same family
208
+ ;[walletAddress, wallet] = await loadChainWallet(source, argv)
209
+ receiver = walletAddress // send to self if same family
196
210
  }
197
211
 
198
212
  if (argv.estimateGasLimit != null || argv.onlyEstimate) {
@@ -214,16 +228,17 @@ async function sendMessage(
214
228
  tokenAmounts,
215
229
  )
216
230
 
231
+ if (!walletAddress) [walletAddress, wallet] = await loadChainWallet(source, argv)
217
232
  const estimated = await estimateExecGasForRequest(source, dest, {
218
233
  lane,
219
234
  message: {
220
- sender: await source.getWalletAddress(argv),
235
+ sender: walletAddress,
221
236
  receiver,
222
237
  data,
223
238
  tokenAmounts: destTokenAmounts,
224
239
  },
225
240
  })
226
- console.log('Estimated gasLimit:', estimated)
241
+ logger.log('Estimated gasLimit:', estimated)
227
242
  argv.gasLimit = Math.ceil(estimated * (1 + (argv.estimateGasLimit ?? 0) / 100))
228
243
  if (argv.onlyEstimate) return
229
244
  }
@@ -247,8 +262,8 @@ async function sendMessage(
247
262
  feeToken = (source.constructor as ChainStatic).getAddress(argv.feeToken)
248
263
  feeTokenInfo = await source.getTokenInfo(feeToken)
249
264
  } catch (_) {
250
- const feeTokens = await source.listFeeTokens(argv.router)
251
- console.debug('supported feeTokens:', feeTokens)
265
+ const feeTokens = await source.getFeeTokens(argv.router)
266
+ logger.debug('supported feeTokens:', feeTokens)
252
267
  for (const [token, info] of Object.entries(feeTokens)) {
253
268
  if (info.symbol === 'UNKNOWN' || info.symbol !== argv.feeToken) continue
254
269
  feeToken = token
@@ -273,7 +288,7 @@ async function sendMessage(
273
288
  // calculate fee
274
289
  const fee = await source.getFee(argv.router, destNetwork.chainSelector, message)
275
290
 
276
- console.info(
291
+ logger.info(
277
292
  'Fee:',
278
293
  fee,
279
294
  '=',
@@ -284,33 +299,35 @@ async function sendMessage(
284
299
  )
285
300
  if (argv.onlyGetFee) return
286
301
 
287
- const tx = await source.sendMessage(
302
+ if (!walletAddress) [walletAddress, wallet] = await loadChainWallet(source, argv)
303
+ const request = await source.sendMessage(
288
304
  argv.router,
289
305
  destNetwork.chainSelector,
290
306
  { ...message, fee },
291
- argv,
307
+ { ...argv, wallet },
292
308
  )
293
- console.log(
309
+ logger.info(
294
310
  '🚀 Sending message to',
295
- tokenReceiver || receiver,
311
+ tokenReceiver && tokenReceiver !== '11111111111111111111111111111111'
312
+ ? tokenReceiver
313
+ : receiver,
296
314
  '@',
297
315
  destNetwork.name,
298
316
  ', tx =>',
299
- tx.hash,
317
+ request.tx.hash,
318
+ ', messageId =>',
319
+ request.message.header.messageId,
300
320
  )
301
321
 
302
- // print CCIPRequest from tx receipt
303
- const request = (await fetchCCIPRequestsInTx(tx))[0]
304
-
305
322
  switch (argv.format) {
306
323
  case Format.log:
307
- console.log(`message ${request.log.index} =`, withDateTimestamp(request))
324
+ logger.log(`message ${request.log.index} =`, withDateTimestamp(request))
308
325
  break
309
326
  case Format.pretty:
310
- await prettyRequest(source, request)
327
+ await prettyRequest.call(ctx, source, request)
311
328
  break
312
329
  case Format.json:
313
- console.info(JSON.stringify(request, bigIntReplacer, 2))
330
+ logger.info(JSON.stringify(request, bigIntReplacer, 2))
314
331
  break
315
332
  }
316
333
  }
@@ -2,18 +2,17 @@ import util from 'util'
2
2
 
3
3
  import {
4
4
  type CCIPRequest,
5
- ChainFamily,
5
+ type ChainTransaction,
6
6
  bigIntReplacer,
7
7
  discoverOffRamp,
8
- fetchCCIPMessageById,
9
- fetchCCIPRequestsInTx,
10
8
  networkInfo,
11
9
  } from '@chainlink/ccip-sdk/src/index.ts'
12
10
  import type { Argv } from 'yargs'
13
11
 
14
12
  import type { GlobalOpts } from '../index.ts'
15
- import { Format } from './types.ts'
13
+ import { type Ctx, Format } from './types.ts'
16
14
  import {
15
+ getCtx,
17
16
  logParsedError,
18
17
  prettyCommit,
19
18
  prettyReceipt,
@@ -26,6 +25,11 @@ import { fetchChainsFromRpcs } from '../providers/index.ts'
26
25
  export const command = ['show <tx-hash>', '* <tx-hash>']
27
26
  export const describe = 'Show details of a CCIP request'
28
27
 
28
+ /**
29
+ * Yargs builder for the show command.
30
+ * @param yargs - Yargs instance.
31
+ * @returns Configured yargs instance with command options.
32
+ */
29
33
  export const builder = (yargs: Argv) =>
30
34
  yargs
31
35
  .positional('tx-hash', {
@@ -41,50 +45,52 @@ export const builder = (yargs: Argv) =>
41
45
  },
42
46
  'id-from-source': {
43
47
  type: 'string',
44
- describe: 'Search by messageId instead of txHash; requires specifying source network',
48
+ describe:
49
+ 'Search by messageId instead of txHash; requires `[onRamp@]sourceNetwork` (onRamp address may be required in some chains)',
45
50
  },
46
51
  })
47
52
 
53
+ /**
54
+ * Handler for the show command.
55
+ * @param argv - Command line arguments.
56
+ */
48
57
  export async function handler(argv: Awaited<ReturnType<typeof builder>['argv']> & GlobalOpts) {
49
- let destroy
50
- const destroy$ = new Promise((resolve) => {
51
- destroy = resolve
52
- })
53
- return showRequests(argv, destroy$)
58
+ const [controller, ctx] = getCtx(argv)
59
+ return showRequests(ctx, argv)
54
60
  .catch((err) => {
55
61
  process.exitCode = 1
56
- if (!logParsedError(err)) console.error(err)
62
+ if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
57
63
  })
58
- .finally(destroy)
64
+ .finally(() => controller.abort('Exited'))
59
65
  }
60
66
 
61
- async function showRequests(argv: Parameters<typeof handler>[0], destroy: Promise<unknown>) {
62
- let source, getChain, tx, request: CCIPRequest
67
+ async function showRequests(ctx: Ctx, argv: Parameters<typeof handler>[0]) {
68
+ const { logger } = ctx
69
+ let source, getChain, tx: ChainTransaction, request: CCIPRequest
63
70
  // messageId not yet implemented for Solana
64
71
  if (argv.idFromSource) {
65
- getChain = fetchChainsFromRpcs(argv, undefined, destroy)
66
- const sourceNetwork = networkInfo(argv.idFromSource)
67
- if (sourceNetwork.family === ChainFamily.Solana) {
68
- throw new Error(
69
- `Message ID search is not yet supported for Solana networks.\n` +
70
- `Please use show with Solana transaction signature instead`,
71
- )
72
- }
72
+ getChain = fetchChainsFromRpcs(ctx, argv)
73
+ let idFromSource, onRamp
74
+ if (argv.idFromSource.includes('@')) {
75
+ ;[onRamp, idFromSource] = argv.idFromSource.split('@')
76
+ } else idFromSource = argv.idFromSource
77
+ const sourceNetwork = networkInfo(idFromSource)
73
78
  source = await getChain(sourceNetwork.chainId)
74
- request = await fetchCCIPMessageById(source, argv.txHash, argv)
79
+ if (!source.fetchRequestById)
80
+ throw new Error(`fetchRequestById not implemented for ${source.constructor.name}`)
81
+ request = await source.fetchRequestById(argv.txHash, onRamp, argv)
75
82
  } else {
76
- const [getChain_, tx$] = fetchChainsFromRpcs(argv, argv.txHash, destroy)
83
+ const [getChain_, tx$] = fetchChainsFromRpcs(ctx, argv, argv.txHash)
77
84
  getChain = getChain_
78
- tx = await tx$
79
- source = tx.chain
80
- request = await selectRequest(await fetchCCIPRequestsInTx(tx), 'to know more', argv)
85
+ ;[source, tx] = await tx$
86
+ request = await selectRequest(await source.fetchRequestsInTx(tx), 'to know more', argv)
81
87
  }
82
88
 
83
89
  const offchainTokenData = await source.fetchOffchainTokenData(request)
84
90
 
85
91
  switch (argv.format) {
86
92
  case Format.log: {
87
- console.log(
93
+ logger.log(
88
94
  `message ${request.log.index} =`,
89
95
  withDateTimestamp(request),
90
96
  '\nattestations =',
@@ -93,48 +99,41 @@ async function showRequests(argv: Parameters<typeof handler>[0], destroy: Promis
93
99
  break
94
100
  }
95
101
  case Format.pretty:
96
- await prettyRequest(source, request, offchainTokenData)
102
+ await prettyRequest.call(ctx, source, request, offchainTokenData)
97
103
  break
98
104
  case Format.json:
99
- console.info(JSON.stringify({ ...request, offchainTokenData }, bigIntReplacer, 2))
105
+ logger.info(JSON.stringify({ ...request, offchainTokenData }, bigIntReplacer, 2))
100
106
  break
101
107
  }
102
108
  if (request.tx.error) throw new Error(`Request tx reverted: ${util.inspect(request.tx.error)}`)
103
109
 
104
110
  const dest = await getChain(request.lane.destChainSelector)
105
- const offRamp = await discoverOffRamp(source, dest, request.lane.onRamp)
111
+ const offRamp = await discoverOffRamp(source, dest, request.lane.onRamp, source)
106
112
  const commitStore = await dest.getCommitStoreForOffRamp(offRamp)
107
113
 
108
114
  const commit = await dest.fetchCommitReport(commitStore, request, argv)
109
115
  switch (argv.format) {
110
116
  case Format.log:
111
- console.log('commit =', commit)
117
+ logger.log('commit =', commit)
112
118
  break
113
119
  case Format.pretty:
114
- await prettyCommit(dest, commit, request)
120
+ await prettyCommit.call(ctx, dest, commit, request)
115
121
  break
116
122
  case Format.json:
117
- console.info(JSON.stringify(commit, bigIntReplacer, 2))
123
+ logger.info(JSON.stringify(commit, bigIntReplacer, 2))
118
124
  break
119
125
  }
120
126
 
121
127
  let found = false
122
- for await (const receipt of dest.fetchExecutionReceipts(
123
- offRamp,
124
- new Set([request.message.header.messageId]),
125
- {
126
- startBlock: commit.log.blockNumber,
127
- page: argv.page,
128
- commit: commit.report,
129
- },
130
- )) {
128
+ for await (const receipt of dest.fetchExecutionReceipts(offRamp, request, commit, argv)) {
131
129
  switch (argv.format) {
132
130
  case Format.log:
133
- console.log('receipt =', withDateTimestamp(receipt))
131
+ logger.log('receipt =', withDateTimestamp(receipt))
134
132
  break
135
133
  case Format.pretty:
136
- if (!found) console.info('Receipts (dest):')
137
- prettyReceipt(
134
+ if (!found) logger.info('Receipts (dest):')
135
+ prettyReceipt.call(
136
+ ctx,
138
137
  receipt,
139
138
  request,
140
139
  receipt.log.tx?.from ??
@@ -142,10 +141,10 @@ async function showRequests(argv: Parameters<typeof handler>[0], destroy: Promis
142
141
  )
143
142
  break
144
143
  case Format.json:
145
- console.info(JSON.stringify(receipt, bigIntReplacer, 2))
144
+ logger.info(JSON.stringify(receipt, bigIntReplacer, 2))
146
145
  break
147
146
  }
148
147
  found = true
149
148
  }
150
- if (!found) console.warn(`No execution receipt found for request`)
149
+ if (!found) logger.warn(`No execution receipt found for request`)
151
150
  }
@@ -19,8 +19,6 @@
19
19
  * - Individual token failures don't halt the process
20
20
  * - Errors are collected and reported comprehensively
21
21
  * - Detailed error reporting for debugging
22
- *
23
- * @module supported-tokens
24
22
  */
25
23
 
26
24
  import {
@@ -33,8 +31,8 @@ import { search } from '@inquirer/prompts'
33
31
  import { formatUnits } from 'ethers'
34
32
  import type { Argv } from 'yargs'
35
33
 
36
- import { Format } from './types.ts'
37
- import { formatDuration, logParsedError, prettyTable } from './utils.ts'
34
+ import { type Ctx, Format } from './types.ts'
35
+ import { formatDuration, getCtx, logParsedError, prettyTable } from './utils.ts'
38
36
  import type { GlobalOpts } from '../index.ts'
39
37
  import { fetchChainsFromRpcs } from '../providers/index.ts'
40
38
 
@@ -42,6 +40,11 @@ export const command = ['getSupportedTokens <source> <address> [token]']
42
40
  export const describe =
43
41
  'List supported tokens in a given Router/OnRamp/TokenAdminRegistry, and/or show info about token/pool'
44
42
 
43
+ /**
44
+ * Yargs builder for the supported-tokens command.
45
+ * @param yargs - Yargs instance.
46
+ * @returns Configured yargs instance with command options.
47
+ */
45
48
  export const builder = (yargs: Argv) =>
46
49
  yargs
47
50
  .positional('source', {
@@ -62,22 +65,24 @@ export const builder = (yargs: Argv) =>
62
65
  'If address is router/onramp/tokenAdminRegistry, token may be used to pre-select a token from the supported list',
63
66
  })
64
67
 
68
+ /**
69
+ * Handler for the supported-tokens command.
70
+ * @param argv - Command line arguments.
71
+ */
65
72
  export async function handler(argv: Awaited<ReturnType<typeof builder>['argv']> & GlobalOpts) {
66
- let destroy
67
- const destroy$ = new Promise((resolve) => {
68
- destroy = resolve
69
- })
70
- return getSupportedTokens(argv, destroy$)
73
+ const [controller, ctx] = getCtx(argv)
74
+ return getSupportedTokens(ctx, argv)
71
75
  .catch((err) => {
72
76
  process.exitCode = 1
73
- if (!logParsedError(err)) console.error(err)
77
+ if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
74
78
  })
75
- .finally(destroy)
79
+ .finally(() => controller.abort('Exited'))
76
80
  }
77
81
 
78
- async function getSupportedTokens(argv: Parameters<typeof handler>[0], destroy: Promise<unknown>) {
82
+ async function getSupportedTokens(ctx: Ctx, argv: Parameters<typeof handler>[0]) {
83
+ const { logger } = ctx
79
84
  const sourceNetwork = networkInfo(argv.source)
80
- const getChain = fetchChainsFromRpcs(argv, undefined, destroy)
85
+ const getChain = fetchChainsFromRpcs(ctx, argv)
81
86
  const source = await getChain(sourceNetwork.name)
82
87
  let registry
83
88
  try {
@@ -88,21 +93,21 @@ async function getSupportedTokens(argv: Parameters<typeof handler>[0], destroy:
88
93
 
89
94
  let info, tokenPool, poolConfigs, registryConfig
90
95
  if (registry && !argv.token) {
91
- const feeTokens = await source.listFeeTokens(argv.address)
96
+ const feeTokens = await source.getFeeTokens(argv.address)
92
97
  switch (argv.format) {
93
98
  case Format.pretty:
94
- console.info('Fee Tokens:')
95
- console.table(feeTokens)
99
+ logger.info('Fee Tokens:')
100
+ logger.table(feeTokens)
96
101
  break
97
102
  case Format.json:
98
- console.log(JSON.stringify(feeTokens, null, 2))
103
+ logger.log(JSON.stringify(feeTokens, null, 2))
99
104
  break
100
105
  default:
101
- console.log('feeTokens:', feeTokens)
106
+ logger.log('feeTokens:', feeTokens)
102
107
  }
103
108
 
104
109
  // router + interactive list
105
- info = await listTokens(source, registry, argv)
110
+ info = await listTokens(ctx, source, registry, argv)
106
111
  if (!info) return // format != pretty
107
112
  registryConfig = await source.getRegistryTokenConfig(registry, info.token)
108
113
  tokenPool = registryConfig.tokenPool
@@ -134,18 +139,18 @@ async function getSupportedTokens(argv: Parameters<typeof handler>[0], destroy:
134
139
  }
135
140
 
136
141
  if (argv.format === Format.json) {
137
- console.log(JSON.stringify({ ...info, tokenPool, ...poolConfigs }, bigIntReplacer, 2))
142
+ logger.log(JSON.stringify({ ...info, tokenPool, ...poolConfigs }, bigIntReplacer, 2))
138
143
  return
139
144
  } else if (argv.format === Format.log) {
140
- console.log('Token:', poolConfigs.token, info)
141
- console.log('Token Pool:', tokenPool)
142
- console.log('Pool Configs:', poolConfigs)
145
+ logger.log('Token:', poolConfigs.token, info)
146
+ logger.log('Token Pool:', tokenPool)
147
+ logger.log('Pool Configs:', poolConfigs)
143
148
  return
144
149
  }
145
150
  }
146
151
  const remotes = await source.getTokenPoolRemotes(tokenPool)
147
152
 
148
- prettyTable({
153
+ prettyTable.call(ctx, {
149
154
  network: `${source.network.name} [${source.network.chainSelector}]`,
150
155
  token: poolConfigs.token,
151
156
  symbol: info.symbol,
@@ -161,9 +166,9 @@ async function getSupportedTokens(argv: Parameters<typeof handler>[0], destroy:
161
166
  }),
162
167
  })
163
168
  const remotesLen = Object.keys(remotes).length
164
- if (remotesLen > 0) console.info('Remotes [', remotesLen, ']:')
169
+ if (remotesLen > 0) logger.info('Remotes [', remotesLen, ']:')
165
170
  for (const [network, remote] of Object.entries(remotes))
166
- prettyTable({
171
+ prettyTable.call(ctx, {
167
172
  remoteNetwork: `${network} [${networkInfo(network).chainSelector}]`,
168
173
  remoteToken: remote.remoteToken,
169
174
  remotePool: remote.remotePools,
@@ -172,7 +177,7 @@ async function getSupportedTokens(argv: Parameters<typeof handler>[0], destroy:
172
177
  })
173
178
  }
174
179
 
175
- async function listTokens(source: Chain, registry: string, argv: GlobalOpts) {
180
+ async function listTokens({ logger }: Ctx, source: Chain, registry: string, argv: GlobalOpts) {
176
181
  const tokens = await source.getSupportedTokens(registry)
177
182
  const infos: { token: string; symbol: string; decimals: number; name?: string }[] = []
178
183
  const batch = 500
@@ -185,12 +190,12 @@ async function listTokens(source: Chain, registry: string, argv: GlobalOpts) {
185
190
  const res = { token, ...info }
186
191
  if (argv.format === Format.log) {
187
192
  // Format.log prints out-of-order, as it fetches data, concurrently
188
- console.info(token, '=', info)
193
+ logger.info(token, '=', info)
189
194
  }
190
195
  return res
191
196
  },
192
197
  (err) => {
193
- console.debug(`getTokenInfo errored`, token, err)
198
+ logger.debug(`getTokenInfo errored`, token, err)
194
199
  },
195
200
  ),
196
201
  ),
@@ -199,7 +204,7 @@ async function listTokens(source: Chain, registry: string, argv: GlobalOpts) {
199
204
  if (argv.format === Format.json) {
200
205
  // Format.json keeps order, prints newline-separated objects
201
206
  for (const info of infos_) {
202
- console.log(JSON.stringify(info))
207
+ logger.log(JSON.stringify(info))
203
208
  }
204
209
  }
205
210
  infos.push(...infos_)
@@ -1,6 +1,21 @@
1
+ import type { Logger } from '@chainlink/ccip-sdk/src/types.js'
2
+
3
+ /** Output format options for CLI commands. */
1
4
  export const Format = {
2
5
  log: 'log',
3
6
  pretty: 'pretty',
4
7
  json: 'json',
5
8
  } as const
9
+ /** Type for output format selection. */
6
10
  export type Format = (typeof Format)[keyof typeof Format]
11
+
12
+ /**
13
+ * Command context
14
+ */
15
+ export type Ctx = {
16
+ destroy$: AbortSignal
17
+ logger: Logger & {
18
+ table: (tabularData: unknown, properties?: readonly string[]) => void
19
+ log: (...args: unknown[]) => void
20
+ }
21
+ }