@twin.org/nft-cli 0.0.2-next.8 → 0.0.3-next.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.
@@ -1,427 +0,0 @@
1
- import path from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
- import { CLIParam, CLIDisplay, CLIOptions, CLIUtils, CLIBase } from '@twin.org/cli-core';
4
- import { buildCommandMnemonic, buildCommandAddress } from '@twin.org/crypto-cli';
5
- import { setupWalletConnector, WalletConnectorTypes, buildCommandFaucet } from '@twin.org/wallet-cli';
6
- import { I18n, Is, Converter, StringHelper } from '@twin.org/core';
7
- import { IotaNftConnector, IotaNftUtils } from '@twin.org/nft-connector-iota';
8
- import { VaultConnectorFactory } from '@twin.org/vault-models';
9
- import { WalletConnectorFactory } from '@twin.org/wallet-models';
10
- import { Command } from 'commander';
11
- import { MemoryEntityStorageConnector } from '@twin.org/entity-storage-connector-memory';
12
- import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
13
- import { initSchema, EntityStorageVaultConnector } from '@twin.org/vault-connector-entity-storage';
14
-
15
- // Copyright 2024 IOTA Stiftung.
16
- // SPDX-License-Identifier: Apache-2.0.
17
- /**
18
- * Setup the vault for use in the CLI commands.
19
- */
20
- function setupVault() {
21
- initSchema();
22
- EntityStorageConnectorFactory.register("vault-key", () => new MemoryEntityStorageConnector({
23
- entitySchema: "VaultKey"
24
- }));
25
- EntityStorageConnectorFactory.register("vault-secret", () => new MemoryEntityStorageConnector({
26
- entitySchema: "VaultSecret"
27
- }));
28
- const vaultConnector = new EntityStorageVaultConnector();
29
- VaultConnectorFactory.register("vault", () => vaultConnector);
30
- }
31
- /**
32
- * Setup the NFT connector for use in the CLI commands.
33
- * @param options The options for the NFT connector.
34
- * @param options.nodeEndpoint The node endpoint.
35
- * @param options.network The network.
36
- * @param options.vaultSeedId The vault seed ID.
37
- * @param options.walletAddressIndex The wallet address index.
38
- * @returns The NFT connector.
39
- */
40
- function setupNftConnector(options) {
41
- return new IotaNftConnector({
42
- config: {
43
- clientOptions: {
44
- url: options.nodeEndpoint
45
- },
46
- network: options.network ?? "",
47
- vaultSeedId: options.vaultSeedId,
48
- walletAddressIndex: options.walletAddressIndex ?? 0
49
- }
50
- });
51
- }
52
-
53
- // Copyright 2024 IOTA Stiftung.
54
- // SPDX-License-Identifier: Apache-2.0.
55
- /**
56
- * Build the nft burn command for the CLI.
57
- * @returns The command.
58
- */
59
- function buildCommandNftBurn() {
60
- const command = new Command();
61
- command
62
- .name("nft-burn")
63
- .summary(I18n.formatMessage("commands.nft-burn.summary"))
64
- .description(I18n.formatMessage("commands.nft-burn.description"))
65
- .requiredOption(I18n.formatMessage("commands.nft-burn.options.seed.param"), I18n.formatMessage("commands.nft-burn.options.seed.description"))
66
- .requiredOption(I18n.formatMessage("commands.nft-burn.options.id.param"), I18n.formatMessage("commands.nft-burn.options.id.description"));
67
- command
68
- .option(I18n.formatMessage("commands.common.options.node.param"), I18n.formatMessage("commands.common.options.node.description"), "!NODE_URL")
69
- .option(I18n.formatMessage("commands.common.options.network.param"), I18n.formatMessage("commands.common.options.network.description"), "!NETWORK")
70
- .option(I18n.formatMessage("commands.common.options.explorer.param"), I18n.formatMessage("commands.common.options.explorer.description"), "!EXPLORER_URL")
71
- .action(actionCommandNftBurn);
72
- return command;
73
- }
74
- /**
75
- * Action the nft burn command.
76
- * @param opts The options for the command.
77
- * @param opts.seed The seed required for signing by the issuer.
78
- * @param opts.id The id of the NFT to burn in urn format.
79
- * @param opts.node The node URL.
80
- * @param opts.network The network to use for connector.
81
- * @param opts.explorer The explorer URL.
82
- */
83
- async function actionCommandNftBurn(opts) {
84
- const seed = CLIParam.hexBase64("seed", opts.seed);
85
- const id = CLIParam.stringValue("id", opts.id);
86
- const nodeEndpoint = CLIParam.url("node", opts.node);
87
- const network = CLIParam.stringValue("network", opts.network);
88
- const explorerEndpoint = CLIParam.url("explorer", opts.explorer);
89
- CLIDisplay.value(I18n.formatMessage("commands.nft-burn.labels.nftId"), id);
90
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.node"), nodeEndpoint);
91
- if (Is.stringValue(network)) {
92
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.network"), network);
93
- }
94
- CLIDisplay.break();
95
- setupVault();
96
- const localIdentity = "local";
97
- const vaultSeedId = "local-seed";
98
- const vaultConnector = VaultConnectorFactory.get("vault");
99
- await vaultConnector.setSecret(`${localIdentity}/${vaultSeedId}`, Converter.bytesToBase64(seed));
100
- const walletConnector = setupWalletConnector({ nodeEndpoint, network, vaultSeedId }, WalletConnectorTypes.Iota);
101
- WalletConnectorFactory.register("wallet", () => walletConnector);
102
- const nftConnector = setupNftConnector({ nodeEndpoint, network, vaultSeedId });
103
- if (Is.function(nftConnector.start)) {
104
- await nftConnector.start(localIdentity);
105
- }
106
- CLIDisplay.task(I18n.formatMessage("commands.nft-burn.progress.burningNft"));
107
- CLIDisplay.break();
108
- CLIDisplay.spinnerStart();
109
- await nftConnector.burn(localIdentity, id);
110
- CLIDisplay.spinnerStop();
111
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.explore"), `${StringHelper.trimTrailingSlashes(explorerEndpoint)}/object/${IotaNftUtils.nftIdToObjectId(id)}?network=${network}`);
112
- CLIDisplay.break();
113
- CLIDisplay.done();
114
- }
115
-
116
- // Copyright 2024 IOTA Stiftung.
117
- // SPDX-License-Identifier: Apache-2.0.
118
- /**
119
- * Build the nft mint command for the CLI.
120
- * @returns The command.
121
- */
122
- function buildCommandNftMint() {
123
- const command = new Command();
124
- command
125
- .name("nft-mint")
126
- .summary(I18n.formatMessage("commands.nft-mint.summary"))
127
- .description(I18n.formatMessage("commands.nft-mint.description"))
128
- .requiredOption(I18n.formatMessage("commands.nft-mint.options.seed.param"), I18n.formatMessage("commands.nft-mint.options.seed.description"))
129
- .requiredOption(I18n.formatMessage("commands.nft-mint.options.issuer.param"), I18n.formatMessage("commands.nft-mint.options.issuer.description"))
130
- .option(I18n.formatMessage("commands.nft-mint.options.wallet-address-index.param"), I18n.formatMessage("commands.nft-mint.options.wallet-address-index.description"), "0")
131
- .requiredOption(I18n.formatMessage("commands.nft-mint.options.tag.param"), I18n.formatMessage("commands.nft-mint.options.tag.description"))
132
- .option(I18n.formatMessage("commands.nft-mint.options.immutable-json.param"), I18n.formatMessage("commands.nft-mint.options.immutable-json.description"))
133
- .option(I18n.formatMessage("commands.nft-mint.options.mutable-json.param"), I18n.formatMessage("commands.nft-mint.options.mutable-json.description"));
134
- CLIOptions.output(command, {
135
- noConsole: true,
136
- json: true,
137
- env: true,
138
- mergeJson: true,
139
- mergeEnv: true
140
- });
141
- command
142
- .option(I18n.formatMessage("commands.common.options.network.param"), I18n.formatMessage("commands.common.options.network.description"), "!NETWORK")
143
- .option(I18n.formatMessage("commands.common.options.explorer.param"), I18n.formatMessage("commands.common.options.explorer.description"), "!EXPLORER_URL")
144
- .option(I18n.formatMessage("commands.common.options.node.param"), I18n.formatMessage("commands.common.options.node.description"), "!NODE_URL")
145
- .action(actionCommandNftMint);
146
- return command;
147
- }
148
- /**
149
- * Action the nft mint command.
150
- * @param opts The options for the command.
151
- * @param opts.seed The seed required for signing by the issuer.
152
- * @param opts.issuer The identity of the issuer.
153
- * @param opts.walletAddressIndex The wallet address index.
154
- * @param opts.tag The tag for the NFT.
155
- * @param opts.immutableJson Filename of the immutable JSON data.
156
- * @param opts.mutableJson Filename of the mutable JSON data.
157
- * @param opts.node The node URL.
158
- * @param opts.network The network to use for connector.
159
- * @param opts.explorer The explorer URL.
160
- */
161
- async function actionCommandNftMint(opts) {
162
- const seed = CLIParam.hexBase64("seed", opts.seed);
163
- const issuer = CLIParam.stringValue("issuer", opts.issuer);
164
- const walletAddressIndex = Is.empty(opts.walletAddressIndex)
165
- ? undefined
166
- : CLIParam.integer("wallet-address-index", opts.walletAddressIndex);
167
- const tag = CLIParam.stringValue("tag", opts.tag);
168
- const immutableJson = opts.immutableJson
169
- ? path.resolve(opts.immutableJson)
170
- : undefined;
171
- const mutableJson = opts.mutableJson
172
- ? path.resolve(opts.mutableJson)
173
- : undefined;
174
- const nodeEndpoint = CLIParam.url("node", opts.node);
175
- const network = CLIParam.stringValue("network", opts.network);
176
- const explorerEndpoint = CLIParam.url("explorer", opts.explorer);
177
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.issuer"), issuer);
178
- if (Is.integer(walletAddressIndex)) {
179
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.walletAddressIndex"), walletAddressIndex);
180
- }
181
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.tag"), tag);
182
- if (Is.stringValue(immutableJson)) {
183
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.immutableJsonFilename"), immutableJson);
184
- }
185
- if (Is.stringValue(mutableJson)) {
186
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.mutableJsonFilename"), mutableJson);
187
- }
188
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.node"), nodeEndpoint);
189
- if (Is.stringValue(network)) {
190
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.network"), network);
191
- }
192
- CLIDisplay.break();
193
- setupVault();
194
- const localIdentity = issuer;
195
- const vaultSeedId = "local-seed";
196
- const vaultConnector = VaultConnectorFactory.get("vault");
197
- await vaultConnector.setSecret(`${localIdentity}/${vaultSeedId}`, Converter.bytesToBase64(seed));
198
- const walletConnector = setupWalletConnector({ nodeEndpoint, network, vaultSeedId }, WalletConnectorTypes.Iota);
199
- WalletConnectorFactory.register("wallet", () => walletConnector);
200
- const nftConnector = setupNftConnector({
201
- nodeEndpoint,
202
- network,
203
- vaultSeedId,
204
- walletAddressIndex
205
- });
206
- if (Is.function(nftConnector.start)) {
207
- await nftConnector.start(localIdentity);
208
- }
209
- const immutableJsonData = Is.stringValue(immutableJson)
210
- ? await CLIUtils.readJsonFile(immutableJson)
211
- : undefined;
212
- const mutableJsonData = Is.stringValue(mutableJson)
213
- ? await CLIUtils.readJsonFile(mutableJson)
214
- : undefined;
215
- if (Is.object(immutableJsonData)) {
216
- CLIDisplay.section(I18n.formatMessage("commands.nft-mint.labels.immutableJson"));
217
- CLIDisplay.json(immutableJsonData);
218
- CLIDisplay.break();
219
- }
220
- if (Is.object(mutableJsonData)) {
221
- CLIDisplay.section(I18n.formatMessage("commands.nft-mint.labels.mutableJson"));
222
- CLIDisplay.json(mutableJsonData);
223
- CLIDisplay.break();
224
- }
225
- CLIDisplay.task(I18n.formatMessage("commands.nft-mint.progress.mintingNft"));
226
- CLIDisplay.break();
227
- CLIDisplay.spinnerStart();
228
- const nftId = await nftConnector.mint(localIdentity, tag, immutableJsonData, mutableJsonData);
229
- CLIDisplay.spinnerStop();
230
- if (opts.console) {
231
- CLIDisplay.value(I18n.formatMessage("commands.nft-mint.labels.nftId"), nftId);
232
- CLIDisplay.break();
233
- }
234
- if (Is.stringValue(opts?.json)) {
235
- await CLIUtils.writeJsonFile(opts.json, { nftId }, opts.mergeJson);
236
- }
237
- if (Is.stringValue(opts?.env)) {
238
- await CLIUtils.writeEnvFile(opts.env, [`NFT_ID="${nftId}"`], opts.mergeEnv);
239
- }
240
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.explore"), `${StringHelper.trimTrailingSlashes(explorerEndpoint)}/object/${IotaNftUtils.nftIdToObjectId(nftId)}?network=${network}`);
241
- CLIDisplay.break();
242
- CLIDisplay.done();
243
- }
244
-
245
- // Copyright 2024 IOTA Stiftung.
246
- // SPDX-License-Identifier: Apache-2.0.
247
- /**
248
- * Build the nft resolve command for the CLI.
249
- * @returns The command.
250
- */
251
- function buildCommandNftResolve() {
252
- const command = new Command();
253
- command
254
- .name("nft-resolve")
255
- .summary(I18n.formatMessage("commands.nft-resolve.summary"))
256
- .description(I18n.formatMessage("commands.nft-resolve.description"))
257
- .requiredOption(I18n.formatMessage("commands.nft-resolve.options.id.param"), I18n.formatMessage("commands.nft-resolve.options.id.description"));
258
- CLIOptions.output(command, {
259
- noConsole: true,
260
- json: true,
261
- env: false,
262
- mergeJson: true,
263
- mergeEnv: false
264
- });
265
- command
266
- .option(I18n.formatMessage("commands.common.options.node.param"), I18n.formatMessage("commands.common.options.node.description"), "!NODE_URL")
267
- .option(I18n.formatMessage("commands.common.options.network.param"), I18n.formatMessage("commands.common.options.network.description"), "!NETWORK")
268
- .option(I18n.formatMessage("commands.common.options.explorer.param"), I18n.formatMessage("commands.common.options.explorer.description"), "!EXPLORER_URL")
269
- .action(actionCommandNftResolve);
270
- return command;
271
- }
272
- /**
273
- * Action the nft resolve command.
274
- * @param opts The options for the command.
275
- * @param opts.id The id of the NFT to resolve in urn format.
276
- * @param opts.node The node URL.
277
- * @param opts.network The network to use for connector.
278
- * @param opts.explorer The explorer URL.
279
- */
280
- async function actionCommandNftResolve(opts) {
281
- const id = CLIParam.stringValue("id", opts.id);
282
- const nodeEndpoint = CLIParam.url("node", opts.node);
283
- const network = CLIParam.stringValue("network", opts.network);
284
- const explorerEndpoint = CLIParam.url("explorer", opts.explorer);
285
- CLIDisplay.value(I18n.formatMessage("commands.nft-resolve.labels.nftId"), id);
286
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.node"), nodeEndpoint);
287
- if (Is.stringValue(network)) {
288
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.network"), network);
289
- }
290
- CLIDisplay.break();
291
- setupVault();
292
- const walletConnector = setupWalletConnector({ nodeEndpoint, network }, WalletConnectorTypes.Iota);
293
- WalletConnectorFactory.register("wallet", () => walletConnector);
294
- const nftConnector = setupNftConnector({ nodeEndpoint, network });
295
- CLIDisplay.task(I18n.formatMessage("commands.nft-resolve.progress.resolvingNft"));
296
- CLIDisplay.break();
297
- CLIDisplay.spinnerStart();
298
- const nft = await nftConnector.resolve(id);
299
- CLIDisplay.spinnerStop();
300
- if (opts.console) {
301
- CLIDisplay.section(I18n.formatMessage("commands.nft-resolve.labels.nft"));
302
- CLIDisplay.json(nft);
303
- CLIDisplay.break();
304
- }
305
- if (Is.stringValue(opts?.json)) {
306
- await CLIUtils.writeJsonFile(opts.json, nft, opts.mergeJson);
307
- }
308
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.explore"), `${StringHelper.trimTrailingSlashes(explorerEndpoint)}/object/${IotaNftUtils.nftIdToObjectId(id)}?network=${network}`);
309
- CLIDisplay.break();
310
- CLIDisplay.done();
311
- }
312
-
313
- // Copyright 2024 IOTA Stiftung.
314
- // SPDX-License-Identifier: Apache-2.0.
315
- /**
316
- * Build the nft transfer command for the CLI.
317
- * @returns The command.
318
- */
319
- function buildCommandNftTransfer() {
320
- const command = new Command();
321
- command
322
- .name("nft-transfer")
323
- .summary(I18n.formatMessage("commands.nft-transfer.summary"))
324
- .description(I18n.formatMessage("commands.nft-transfer.description"))
325
- .requiredOption(I18n.formatMessage("commands.nft-transfer.options.seed.param"), I18n.formatMessage("commands.nft-transfer.options.seed.description"))
326
- .requiredOption(I18n.formatMessage("commands.nft-transfer.options.id.param"), I18n.formatMessage("commands.nft-transfer.options.id.description"))
327
- .requiredOption(I18n.formatMessage("commands.nft-transfer.options.recipient-identity.param"), I18n.formatMessage("commands.nft-transfer.options.recipient-identity.description"))
328
- .requiredOption(I18n.formatMessage("commands.nft-transfer.options.recipient-address.param"), I18n.formatMessage("commands.nft-transfer.options.recipient-address.description"));
329
- command
330
- .option(I18n.formatMessage("commands.common.options.node.param"), I18n.formatMessage("commands.common.options.node.description"), "!NODE_URL")
331
- .option(I18n.formatMessage("commands.common.options.network.param"), I18n.formatMessage("commands.common.options.network.description"), "!NETWORK")
332
- .option(I18n.formatMessage("commands.common.options.explorer.param"), I18n.formatMessage("commands.common.options.explorer.description"), "!EXPLORER_URL")
333
- .action(actionCommandNftTransfer);
334
- return command;
335
- }
336
- /**
337
- * Action the nft transfer command.
338
- * @param opts The options for the command.
339
- * @param opts.seed The seed required for signing by the issuer.
340
- * @param opts.id The id of the NFT to transfer in urn format.
341
- * @param opts.recipientIdentity The recipient address of the NFT.
342
- * @param opts.recipientAddress The recipient address of the NFT.
343
- * @param opts.node The node URL.
344
- * @param opts.network The network to use for connector.
345
- * @param opts.explorer The explorer URL.
346
- */
347
- async function actionCommandNftTransfer(opts) {
348
- const seed = CLIParam.hexBase64("seed", opts.seed);
349
- const id = CLIParam.stringValue("id", opts.id);
350
- const recipientIdentity = CLIParam.stringValue("recipientIdentity", opts.recipientIdentity);
351
- const recipientAddress = Converter.bytesToHex(CLIParam.hex("recipientAddress", opts.recipientAddress), true);
352
- const nodeEndpoint = CLIParam.url("node", opts.node);
353
- const network = CLIParam.stringValue("network", opts.network);
354
- const explorerEndpoint = CLIParam.url("explorer", opts.explorer);
355
- CLIDisplay.value(I18n.formatMessage("commands.nft-transfer.labels.nftId"), id);
356
- CLIDisplay.value(I18n.formatMessage("commands.nft-transfer.labels.recipientIdentity"), recipientIdentity);
357
- CLIDisplay.value(I18n.formatMessage("commands.nft-transfer.labels.recipientAddress"), recipientAddress);
358
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.node"), nodeEndpoint);
359
- if (Is.stringValue(network)) {
360
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.network"), network);
361
- }
362
- CLIDisplay.break();
363
- setupVault();
364
- const walletConnector = setupWalletConnector({ nodeEndpoint, network }, WalletConnectorTypes.Iota);
365
- WalletConnectorFactory.register("wallet", () => walletConnector);
366
- const localIdentity = "local";
367
- const vaultSeedId = "local-seed";
368
- const vaultConnector = VaultConnectorFactory.get("vault");
369
- await vaultConnector.setSecret(`${localIdentity}/${vaultSeedId}`, Converter.bytesToBase64(seed));
370
- const nftConnector = setupNftConnector({ nodeEndpoint, network, vaultSeedId });
371
- if (Is.function(nftConnector.start)) {
372
- await nftConnector.start(localIdentity);
373
- }
374
- CLIDisplay.task(I18n.formatMessage("commands.nft-transfer.progress.transferringNft"));
375
- CLIDisplay.break();
376
- CLIDisplay.spinnerStart();
377
- await nftConnector.transfer(localIdentity, id, recipientIdentity, recipientAddress);
378
- CLIDisplay.spinnerStop();
379
- CLIDisplay.value(I18n.formatMessage("commands.common.labels.explore"), `${StringHelper.trimTrailingSlashes(explorerEndpoint)}/object/${IotaNftUtils.nftIdToObjectId(id)}?network=${network}`);
380
- CLIDisplay.break();
381
- CLIDisplay.done();
382
- }
383
-
384
- // Copyright 2024 IOTA Stiftung.
385
- // SPDX-License-Identifier: Apache-2.0.
386
- /**
387
- * The main entry point for the CLI.
388
- */
389
- class CLI extends CLIBase {
390
- /**
391
- * Run the app.
392
- * @param argv The process arguments.
393
- * @param localesDirectory The directory for the locales, default to relative to the script.
394
- * @param options Additional options for the CLI.
395
- * @param options.overrideOutputWidth Override the output width.
396
- * @returns The exit code.
397
- */
398
- async run(argv, localesDirectory, options) {
399
- return this.execute({
400
- title: "TWIN NFT",
401
- appName: "twin-nft",
402
- version: "0.0.2-next.8", // x-release-please-version
403
- icon: "🌍",
404
- supportsEnvFiles: true,
405
- overrideOutputWidth: options?.overrideOutputWidth,
406
- showDevToolWarning: true
407
- }, localesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), "../locales"), argv);
408
- }
409
- /**
410
- * Get the commands for the CLI.
411
- * @param program The main program to add the commands to.
412
- * @internal
413
- */
414
- getCommands(program) {
415
- return [
416
- buildCommandMnemonic(),
417
- buildCommandAddress(),
418
- buildCommandFaucet(),
419
- buildCommandNftMint(),
420
- buildCommandNftResolve(),
421
- buildCommandNftBurn(),
422
- buildCommandNftTransfer()
423
- ];
424
- }
425
- }
426
-
427
- export { CLI, actionCommandNftBurn, actionCommandNftMint, actionCommandNftResolve, actionCommandNftTransfer, buildCommandNftBurn, buildCommandNftMint, buildCommandNftResolve, buildCommandNftTransfer, setupNftConnector, setupVault };