Skip to content

Commit 61df21e

Browse files
authored
feat(1671): Create nft command expansion (#1726)
Signed-off-by: matevszm <mateusz.marcinkowski@blockydevs.com>
1 parent 6ec118a commit 61df21e

File tree

11 files changed

+589
-14
lines changed

11 files changed

+589
-14
lines changed

docs/output-schemas-guide.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,22 @@ interface CommandOutputSpec {
368368
"supplyType": "FINITE",
369369
"transactionId": "0.0.123@1700000000.123456789",
370370
"adminAccountId": "0.0.12345",
371+
"adminPublicKey": "302a300506032b6570032100...",
371372
"supplyAccountId": "0.0.12345",
373+
"supplyPublicKey": "302a300506032b6570032100...",
374+
"freezePublicKey": "302a300506032b6570032100...",
375+
"wipePublicKey": "302a300506032b6570032100...",
376+
"pausePublicKey": "302a300506032b6570032100...",
377+
"kycPublicKey": "302a300506032b6570032100...",
378+
"feeSchedulePublicKey": "302a300506032b6570032100...",
379+
"metadataPublicKey": "302a300506032b6570032100...",
372380
"alias": "my-nft",
373381
"network": "testnet"
374382
}
375383
```
376384

385+
All key fields (`adminPublicKey`, `supplyPublicKey`, `freezePublicKey`, `wipePublicKey`, `pausePublicKey`, `kycPublicKey`, `feeSchedulePublicKey`, `metadataPublicKey`) are optional and only appear when the corresponding key was provided.
386+
377387
#### `token mint-ft`
378388

379389
**Output**:

src/core/services/token/token-service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ export class TokenServiceImpl implements TokenService {
9797
wipePublicKey,
9898
kycPublicKey,
9999
freezePublicKey,
100-
freezeDefault,
101100
pausePublicKey,
102101
feeSchedulePublicKey,
103102
metadataPublicKey,
103+
freezeDefault,
104104
customFees,
105105
memo,
106106
autoRenewPeriodSeconds,
@@ -191,6 +191,11 @@ export class TokenServiceImpl implements TokenService {
191191
this.logger.debug(`[TOKEN SERVICE] Set metadata key`);
192192
}
193193

194+
if (freezeDefault !== undefined) {
195+
tokenCreateTx.setFreezeDefault(freezeDefault);
196+
this.logger.debug(`[TOKEN SERVICE] Set freeze default: ${freezeDefault}`);
197+
}
198+
194199
if (autoRenewPeriodSeconds && autoRenewAccountId) {
195200
tokenCreateTx
196201
.setAutoRenewAccountId(AccountId.fromString(autoRenewAccountId))

src/core/types/token.types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ export interface TokenCreateParams {
7272
pausePublicKey?: PublicKey;
7373
feeSchedulePublicKey?: PublicKey;
7474
metadataPublicKey?: PublicKey;
75+
autoRenewPeriod?: number;
76+
autoRenewAccountId?: string;
77+
expirationTime?: Date;
7578
customFees?: CustomFee[];
7679
memo?: string;
7780
autoRenewPeriodSeconds?: number;
78-
autoRenewAccountId?: string;
79-
expirationTime?: Date;
8081
}
8182

8283
/**

src/plugins/token/README.md

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,103 @@ hcli token create-ft \
182182

183183
**Batch support:** Pass `--batch <batch-name>` to add token creation to a batch instead of executing immediately. See the [Batch Support](#-batch-support) section.
184184

185+
### Token Create NFT
186+
187+
Create a new non-fungible token (NFT) collection with specified properties.
188+
189+
```bash
190+
# Using account alias
191+
hcli token create-nft \
192+
--token-name "My NFT Collection" \
193+
--symbol "MNFT" \
194+
--treasury alice \
195+
--supply-type FINITE \
196+
--max-supply 1000 \
197+
--admin-key alice \
198+
--supply-key alice \
199+
--freeze-key alice \
200+
--wipe-key alice \
201+
--name my-nft-collection
202+
203+
# With additional optional keys and settings
204+
hcli token create-nft \
205+
--token-name "My Collection" \
206+
--symbol "MC" \
207+
--treasury 0.0.123456:302e020100300506032b657004220420... \
208+
--supply-type INFINITE \
209+
--admin-key alice \
210+
--supply-key alice \
211+
--kyc-key alice \
212+
--pause-key alice \
213+
--fee-schedule-key alice \
214+
--metadata-key alice \
215+
--auto-renew-period 7776000 \
216+
--auto-renew-account-id 0.0.123456 \
217+
--freeze-default false \
218+
--name my-collection
219+
```
220+
221+
**Parameters:**
222+
223+
- `--token-name` / `-T`: Token name - **Required**
224+
- `--symbol` / `-s`: Token symbol/ticker - **Required**
225+
- `--treasury`: Treasury account for the NFT collection - **Optional** (defaults to operator)
226+
- Account alias: `alice`
227+
- Account with key: `0.0.123456:private-key`
228+
- `--supply-type`: Supply type - **Optional** (defaults to `INFINITE`)
229+
- `INFINITE` - Unlimited supply
230+
- `FINITE` - Fixed maximum supply (requires `--max-supply`)
231+
- `--max-supply`: Maximum number of NFTs in collection (required for FINITE) - **Optional**
232+
- `--admin-key`: Admin key for administrative operations - **Optional**
233+
- `--supply-key`: Supply key for minting NFTs - **Optional**
234+
- `--freeze-key`: Freeze key to freeze token transfers for accounts - **Optional**
235+
- `--wipe-key`: Wipe key to wipe token balances - **Optional**
236+
- `--kyc-key`: KYC key to grant/revoke KYC status - **Optional**
237+
- `--pause-key`: Pause key to pause all token transfers - **Optional**
238+
- `--fee-schedule-key`: Fee schedule key to modify custom fees - **Optional**
239+
- `--metadata-key`: Metadata key to update token metadata - **Optional**
240+
- `--freeze-default`: Default freeze status for new associations (requires `--freeze-key`) - **Optional** (defaults to false)
241+
- `--auto-renew-period`: Token auto-renewal period in seconds (e.g., 7776000 for 90 days) - **Optional**
242+
- `--auto-renew-account-id`: Account ID that pays for token auto-renewal fees - **Optional**
243+
- `--expiration-time`: Token expiration time in ISO 8601 format (e.g., 2027-01-01T00:00:00Z) - **Optional**
244+
- `--name`: Token alias to register - **Optional**
245+
- `--key-manager`: Key manager type - **Optional** (defaults to config setting)
246+
- `local` or `local_encrypted`
247+
- `--memo`: Optional memo for the token (max 100 characters) - **Optional**
248+
- `--batch`: Add to batch instead of executing immediately - **Optional**
249+
250+
**Output:**
251+
252+
```json
253+
{
254+
"tokenId": "0.0.123456",
255+
"name": "My NFT Collection",
256+
"symbol": "MNFT",
257+
"treasuryId": "0.0.111",
258+
"supplyType": "FINITE",
259+
"transactionId": "0.0.123@1700000000.123456789",
260+
"adminPublicKey": "302e020100300506032b657004220420...",
261+
"supplyPublicKey": "302e020100300506032b657004220420...",
262+
"freezePublicKey": "302e020100300506032b657004220420...",
263+
"wipePublicKey": "302e020100300506032b657004220420...",
264+
"kycPublicKey": "302e020100300506032b657004220420...",
265+
"pausePublicKey": "302e020100300506032b657004220420...",
266+
"feeSchedulePublicKey": "302e020100300506032b657004220420...",
267+
"metadataPublicKey": "302e020100300506032b657004220420...",
268+
"network": "testnet"
269+
}
270+
```
271+
272+
**Notes:**
273+
274+
- NFTs are non-fungible, meaning each NFT is unique and tracked by serial number
275+
- No decimals field applies to NFTs
276+
- Use `mint-nft` command to mint individual NFTs to the collection
277+
- Token name is automatically registered as an alias after successful creation
278+
- Freeze default requires freeze key to be set
279+
280+
**Batch support:** Pass `--batch <batch-name>` to add NFT collection creation to a batch instead of executing immediately. See the [Batch Support](#-batch-support) section.
281+
185282
### Token Mint FT
186283

187284
Mint additional fungible tokens to increase supply. Tokens are minted to the token's treasury account.
@@ -609,6 +706,11 @@ The token file supports aliases and raw keys with optional key type prefixes:
609706
"freezeKey": "<alias or accountId:privateKey>",
610707
"pauseKey": "<alias or accountId:privateKey>",
611708
"feeScheduleKey": "<alias or accountId:privateKey>",
709+
"metadataKey": "<alias or accountId:privateKey>",
710+
"freezeDefault": false,
711+
"autoRenewPeriod": 7776000,
712+
"autoRenewAccountId": "<accountId>",
713+
"expirationTime": "2027-01-01T00:00:00Z",
612714
"memo": "Optional token memo",
613715
"autoRenewPeriod": "86400",
614716
"autoRenewAccount": "<alias or accountId:privateKey>",
@@ -676,6 +778,11 @@ The NFT file supports aliases and raw keys with optional key type prefixes:
676778
"freezeKey": "<alias or accountId:privateKey>",
677779
"pauseKey": "<alias or accountId:privateKey>",
678780
"feeScheduleKey": "<alias or accountId:privateKey>",
781+
"metadataKey": "<alias or accountId:privateKey>",
782+
"freezeDefault": false,
783+
"autoRenewPeriod": 7776000,
784+
"autoRenewAccountId": "<accountId>",
785+
"expirationTime": "2027-01-01T00:00:00Z",
679786
"memo": "Optional NFT collection memo",
680787
"associations": ["<alias or accountId:privateKey>", "..."]
681788
}
@@ -803,14 +910,36 @@ interface TokenData {
803910
supplyType: SupplyType;
804911
maxSupply: number;
805912
memo?: string;
913+
adminPublicKey?: string;
914+
supplyPublicKey?: string;
915+
wipePublicKey?: string;
916+
kycPublicKey?: string;
917+
freezePublicKey?: string;
918+
pausePublicKey?: string;
919+
feeSchedulePublicKey?: string;
920+
metadataPublicKey?: string;
806921
keys: TokenKeys;
807922
network: 'mainnet' | 'testnet' | 'previewnet' | 'localnet';
808923
associations: TokenAssociation[];
809924
customFees: CustomFee[];
810925
}
811926
```
812927

813-
The `tokenType` field discriminates fungible tokens (`FUNGIBLE_COMMON`) from NFT collections (`NON_FUNGIBLE_UNIQUE`). NFT tokens use zero for `decimals` and `initialSupply`; minted NFTs are tracked by serial number on the ledger. The schema is validated using Zod (`TokenDataSchema`) and stored as JSON Schema in the plugin manifest for runtime validation.
928+
**Field Descriptions:**
929+
930+
- `tokenType`: Discriminates fungible tokens (`FUNGIBLE_COMMON`) from NFT collections (`NON_FUNGIBLE_UNIQUE`)
931+
- `decimals`: Number of decimal places for fungible tokens; zero for NFTs
932+
- `initialSupply`: Initial supply amount; zero for NFTs
933+
- `adminPublicKey`: Public key with admin privileges for token operations
934+
- `supplyPublicKey`: Public key authorized to mint/burn tokens
935+
- `wipePublicKey`: Public key authorized to wipe token balances
936+
- `kycPublicKey`: Public key authorized to grant/revoke KYC status
937+
- `freezePublicKey`: Public key authorized to freeze token transfers
938+
- `pausePublicKey`: Public key authorized to pause all token transfers
939+
- `feeSchedulePublicKey`: Public key authorized to update custom fees
940+
- `metadataPublicKey`: Public key authorized to update token metadata
941+
942+
NFT tokens use zero for `decimals` and `initialSupply`; minted NFTs are tracked by serial number on the ledger. The schema is validated using Zod (`TokenDataSchema`) and stored as JSON Schema in the plugin manifest for runtime validation.
814943

815944
## 🧪 Testing
816945

@@ -849,7 +978,7 @@ All commands support multiple output formats:
849978

850979
### Human-Readable (Default)
851980

852-
**Token Create:**
981+
**Fungible Token Create:**
853982

854983
```
855984
✅ Token created successfully: 0.0.12345
@@ -862,6 +991,17 @@ All commands support multiple output formats:
862991
Transaction ID: 0.0.123@1700000000.123456789
863992
```
864993

994+
**Non-Fungible Token Create:**
995+
996+
```
997+
✅ NFT created successfully: 0.0.123456
998+
Name: My NFT Collection (MNFT)
999+
Treasury: 0.0.111
1000+
Supply Type: FINITE
1001+
Network: testnet
1002+
Transaction ID: 0.0.123@1700000000.123456789
1003+
```
1004+
8651005
**FT Mint:**
8661006

8671007
```
@@ -898,6 +1038,28 @@ All commands support multiple output formats:
8981038
}
8991039
```
9001040

1041+
**Non-Fungible Token Create:**
1042+
1043+
```json
1044+
{
1045+
"tokenId": "0.0.123456",
1046+
"name": "My NFT Collection",
1047+
"symbol": "MNFT",
1048+
"treasuryId": "0.0.111",
1049+
"supplyType": "FINITE",
1050+
"transactionId": "0.0.123@1700000000.123456789",
1051+
"adminPublicKey": "302e020100300506032b657004220420...",
1052+
"supplyPublicKey": "302e020100300506032b657004220420...",
1053+
"freezePublicKey": "302e020100300506032b657004220420...",
1054+
"wipePublicKey": "302e020100300506032b657004220420...",
1055+
"kycPublicKey": "302e020100300506032b657004220420...",
1056+
"pausePublicKey": "302e020100300506032b657004220420...",
1057+
"feeSchedulePublicKey": "302e020100300506032b657004220420...",
1058+
"metadataPublicKey": "302e020100300506032b657004220420...",
1059+
"network": "testnet"
1060+
}
1061+
```
1062+
9011063
**FT Mint:**
9021064

9031065
```json

0 commit comments

Comments
 (0)