@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.
- package/README.md +40 -21
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/manual-exec.d.ts +9 -0
- package/dist/commands/manual-exec.d.ts.map +1 -1
- package/dist/commands/manual-exec.js +40 -35
- package/dist/commands/manual-exec.js.map +1 -1
- package/dist/commands/parse.d.ts +9 -0
- package/dist/commands/parse.d.ts.map +1 -1
- package/dist/commands/parse.js +18 -7
- package/dist/commands/parse.js.map +1 -1
- package/dist/commands/send.d.ts +9 -0
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/send.js +39 -26
- package/dist/commands/send.js.map +1 -1
- package/dist/commands/show.d.ts +9 -0
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +46 -39
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/supported-tokens.d.ts +9 -2
- package/dist/commands/supported-tokens.d.ts.map +1 -1
- package/dist/commands/supported-tokens.js +35 -30
- package/dist/commands/supported-tokens.js.map +1 -1
- package/dist/commands/types.d.ts +13 -0
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js +1 -0
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/utils.d.ts +75 -10
- package/dist/commands/utils.d.ts.map +1 -1
- package/dist/commands/utils.js +95 -19
- package/dist/commands/utils.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -7
- package/dist/index.js.map +1 -1
- package/dist/providers/aptos.d.ts +35 -0
- package/dist/providers/aptos.d.ts.map +1 -1
- package/dist/providers/aptos.js +34 -9
- package/dist/providers/aptos.js.map +1 -1
- package/dist/providers/evm.d.ts +10 -1
- package/dist/providers/evm.d.ts.map +1 -1
- package/dist/providers/evm.js +11 -5
- package/dist/providers/evm.js.map +1 -1
- package/dist/providers/index.d.ts +15 -8
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +47 -11
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/solana.d.ts +30 -0
- package/dist/providers/solana.d.ts.map +1 -1
- package/dist/providers/solana.js +30 -5
- package/dist/providers/solana.js.map +1 -1
- package/package.json +11 -8
- package/src/commands/index.ts +2 -1
- package/src/commands/manual-exec.ts +40 -33
- package/src/commands/parse.ts +19 -8
- package/src/commands/send.ts +47 -30
- package/src/commands/show.ts +47 -48
- package/src/commands/supported-tokens.ts +35 -30
- package/src/commands/types.ts +15 -0
- package/src/commands/utils.ts +112 -26
- package/src/index.ts +29 -7
- package/src/providers/aptos.ts +33 -8
- package/src/providers/evm.ts +22 -5
- package/src/providers/index.ts +67 -15
- package/src/providers/solana.ts +31 -6
- package/tsconfig.json +2 -1
package/src/commands/send.ts
CHANGED
|
@@ -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 {
|
|
21
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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))
|
|
145
|
+
if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
|
|
135
146
|
})
|
|
136
|
-
.finally(
|
|
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(
|
|
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
|
-
|
|
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:
|
|
235
|
+
sender: walletAddress,
|
|
221
236
|
receiver,
|
|
222
237
|
data,
|
|
223
238
|
tokenAmounts: destTokenAmounts,
|
|
224
239
|
},
|
|
225
240
|
})
|
|
226
|
-
|
|
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.
|
|
251
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
309
|
+
logger.info(
|
|
294
310
|
'🚀 Sending message to',
|
|
295
|
-
tokenReceiver
|
|
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
|
-
|
|
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
|
-
|
|
330
|
+
logger.info(JSON.stringify(request, bigIntReplacer, 2))
|
|
314
331
|
break
|
|
315
332
|
}
|
|
316
333
|
}
|
package/src/commands/show.ts
CHANGED
|
@@ -2,18 +2,17 @@ import util from 'util'
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
type CCIPRequest,
|
|
5
|
-
|
|
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:
|
|
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
|
-
|
|
50
|
-
|
|
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))
|
|
62
|
+
if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
|
|
57
63
|
})
|
|
58
|
-
.finally(
|
|
64
|
+
.finally(() => controller.abort('Exited'))
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
async function showRequests(argv: Parameters<typeof handler>[0]
|
|
62
|
-
|
|
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(
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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
|
|
83
|
+
const [getChain_, tx$] = fetchChainsFromRpcs(ctx, argv, argv.txHash)
|
|
77
84
|
getChain = getChain_
|
|
78
|
-
tx = await tx$
|
|
79
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
+
logger.log('receipt =', withDateTimestamp(receipt))
|
|
134
132
|
break
|
|
135
133
|
case Format.pretty:
|
|
136
|
-
if (!found)
|
|
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
|
-
|
|
144
|
+
logger.info(JSON.stringify(receipt, bigIntReplacer, 2))
|
|
146
145
|
break
|
|
147
146
|
}
|
|
148
147
|
found = true
|
|
149
148
|
}
|
|
150
|
-
if (!found)
|
|
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
|
-
|
|
67
|
-
|
|
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))
|
|
77
|
+
if (!logParsedError.call(ctx, err)) ctx.logger.error(err)
|
|
74
78
|
})
|
|
75
|
-
.finally(
|
|
79
|
+
.finally(() => controller.abort('Exited'))
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
async function getSupportedTokens(argv: Parameters<typeof handler>[0]
|
|
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(
|
|
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.
|
|
96
|
+
const feeTokens = await source.getFeeTokens(argv.address)
|
|
92
97
|
switch (argv.format) {
|
|
93
98
|
case Format.pretty:
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
logger.info('Fee Tokens:')
|
|
100
|
+
logger.table(feeTokens)
|
|
96
101
|
break
|
|
97
102
|
case Format.json:
|
|
98
|
-
|
|
103
|
+
logger.log(JSON.stringify(feeTokens, null, 2))
|
|
99
104
|
break
|
|
100
105
|
default:
|
|
101
|
-
|
|
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
|
-
|
|
142
|
+
logger.log(JSON.stringify({ ...info, tokenPool, ...poolConfigs }, bigIntReplacer, 2))
|
|
138
143
|
return
|
|
139
144
|
} else if (argv.format === Format.log) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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)
|
|
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
|
-
|
|
193
|
+
logger.info(token, '=', info)
|
|
189
194
|
}
|
|
190
195
|
return res
|
|
191
196
|
},
|
|
192
197
|
(err) => {
|
|
193
|
-
|
|
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
|
-
|
|
207
|
+
logger.log(JSON.stringify(info))
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
210
|
infos.push(...infos_)
|
package/src/commands/types.ts
CHANGED
|
@@ -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
|
+
}
|