Skip to content

Commit 1027b35

Browse files
committed
feat(1671): Create nft command expansion
Signed-off-by: matevszm <mateusz.marcinkowski@blockydevs.com>
1 parent 94cf56a commit 1027b35

File tree

9 files changed

+387
-8
lines changed

9 files changed

+387
-8
lines changed

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
FeeAssessmentMethod,
2222
Hbar,
2323
NftId,
24+
Timestamp,
2425
TokenAssociateTransaction,
2526
TokenCreateTransaction,
2627
TokenId,
@@ -94,6 +95,11 @@ export class TokenServiceImpl implements TokenService {
9495
freezePublicKey,
9596
pausePublicKey,
9697
feeSchedulePublicKey,
98+
metadataPublicKey,
99+
autoRenewPeriod,
100+
autoRenewAccountId,
101+
expirationTime,
102+
freezeDefault,
97103
customFees,
98104
memo,
99105
} = params;
@@ -172,6 +178,39 @@ export class TokenServiceImpl implements TokenService {
172178
this.logger.debug(`[TOKEN SERVICE] Set fee schedule key`);
173179
}
174180

181+
if (metadataPublicKey) {
182+
tokenCreateTx.setMetadataKey(metadataPublicKey);
183+
this.logger.debug(`[TOKEN SERVICE] Set metadata key`);
184+
}
185+
186+
if (freezeDefault !== undefined) {
187+
tokenCreateTx.setFreezeDefault(freezeDefault);
188+
this.logger.debug(`[TOKEN SERVICE] Set freeze default: ${freezeDefault}`);
189+
}
190+
191+
if (autoRenewPeriod !== undefined) {
192+
tokenCreateTx.setAutoRenewPeriod(autoRenewPeriod);
193+
this.logger.debug(
194+
`[TOKEN SERVICE] Set auto renew period: ${autoRenewPeriod}s`,
195+
);
196+
}
197+
198+
if (autoRenewAccountId) {
199+
tokenCreateTx.setAutoRenewAccountId(
200+
AccountId.fromString(autoRenewAccountId),
201+
);
202+
this.logger.debug(
203+
`[TOKEN SERVICE] Set auto renew account: ${autoRenewAccountId}`,
204+
);
205+
}
206+
207+
if (expirationTime) {
208+
tokenCreateTx.setExpirationTime(Timestamp.fromDate(expirationTime));
209+
this.logger.debug(
210+
`[TOKEN SERVICE] Set expiration time: ${expirationTime.toISOString()}`,
211+
);
212+
}
213+
175214
this.logger.debug(
176215
`[TOKEN SERVICE] Created token creation transaction for ${name}`,
177216
);

src/core/types/token.types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export interface TokenCreateParams {
7070
freezePublicKey?: PublicKey;
7171
pausePublicKey?: PublicKey;
7272
feeSchedulePublicKey?: PublicKey;
73+
metadataPublicKey?: PublicKey;
74+
autoRenewPeriod?: number;
75+
autoRenewAccountId?: string;
76+
expirationTime?: Date;
77+
freezeDefault?: boolean;
7378
customFees?: CustomFee[];
7479
memo?: string;
7580
}

src/plugins/token/README.md

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

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

156+
### Token Create NFT
157+
158+
Create a new non-fungible token (NFT) collection with specified properties.
159+
160+
```bash
161+
# Using account alias
162+
hcli token create-nft \
163+
--token-name "My NFT Collection" \
164+
--symbol "MNFT" \
165+
--treasury alice \
166+
--supply-type FINITE \
167+
--max-supply 1000 \
168+
--admin-key alice \
169+
--supply-key alice \
170+
--freeze-key alice \
171+
--wipe-key alice \
172+
--name my-nft-collection
173+
174+
# With additional optional keys and settings
175+
hcli token create-nft \
176+
--token-name "My Collection" \
177+
--symbol "MC" \
178+
--treasury 0.0.123456:302e020100300506032b657004220420... \
179+
--supply-type INFINITE \
180+
--admin-key alice \
181+
--supply-key alice \
182+
--kyc-key alice \
183+
--pause-key alice \
184+
--fee-schedule-key alice \
185+
--metadata-key alice \
186+
--auto-renew-period 7776000 \
187+
--auto-renew-account-id 0.0.123456 \
188+
--freeze-default false \
189+
--name my-collection
190+
```
191+
192+
**Parameters:**
193+
194+
- `--token-name` / `-T`: Token name - **Required**
195+
- `--symbol` / `-s`: Token symbol/ticker - **Required**
196+
- `--treasury`: Treasury account for the NFT collection - **Optional** (defaults to operator)
197+
- Account alias: `alice`
198+
- Account with key: `0.0.123456:private-key`
199+
- `--supply-type`: Supply type - **Optional** (defaults to `INFINITE`)
200+
- `INFINITE` - Unlimited supply
201+
- `FINITE` - Fixed maximum supply (requires `--max-supply`)
202+
- `--max-supply`: Maximum number of NFTs in collection (required for FINITE) - **Optional**
203+
- `--admin-key`: Admin key for administrative operations - **Optional**
204+
- `--supply-key`: Supply key for minting NFTs - **Optional**
205+
- `--freeze-key`: Freeze key to freeze token transfers for accounts - **Optional**
206+
- `--wipe-key`: Wipe key to wipe token balances - **Optional**
207+
- `--kyc-key`: KYC key to grant/revoke KYC status - **Optional**
208+
- `--pause-key`: Pause key to pause all token transfers - **Optional**
209+
- `--fee-schedule-key`: Fee schedule key to modify custom fees - **Optional**
210+
- `--metadata-key`: Metadata key to update token metadata - **Optional**
211+
- `--freeze-default`: Default freeze status for new associations (requires `--freeze-key`) - **Optional** (defaults to false)
212+
- `--auto-renew-period`: Token auto-renewal period in seconds (e.g., 7776000 for 90 days) - **Optional**
213+
- `--auto-renew-account-id`: Account ID that pays for token auto-renewal fees - **Optional**
214+
- `--expiration-time`: Token expiration time in ISO 8601 format (e.g., 2027-01-01T00:00:00Z) - **Optional**
215+
- `--name`: Token alias to register - **Optional**
216+
- `--key-manager`: Key manager type - **Optional** (defaults to config setting)
217+
- `local` or `local_encrypted`
218+
- `--memo`: Optional memo for the token (max 100 characters) - **Optional**
219+
- `--batch`: Add to batch instead of executing immediately - **Optional**
220+
221+
**Output:**
222+
223+
```json
224+
{
225+
"tokenId": "0.0.123456",
226+
"name": "My NFT Collection",
227+
"symbol": "MNFT",
228+
"treasuryId": "0.0.111",
229+
"supplyType": "FINITE",
230+
"transactionId": "0.0.123@1700000000.123456789",
231+
"adminPublicKey": "302e020100300506032b657004220420...",
232+
"supplyPublicKey": "302e020100300506032b657004220420...",
233+
"freezePublicKey": "302e020100300506032b657004220420...",
234+
"wipePublicKey": "302e020100300506032b657004220420...",
235+
"kycPublicKey": "302e020100300506032b657004220420...",
236+
"pausePublicKey": "302e020100300506032b657004220420...",
237+
"feeSchedulePublicKey": "302e020100300506032b657004220420...",
238+
"metadataPublicKey": "302e020100300506032b657004220420...",
239+
"network": "testnet"
240+
}
241+
```
242+
243+
**Notes:**
244+
245+
- NFTs are non-fungible, meaning each NFT is unique and tracked by serial number
246+
- No decimals field applies to NFTs
247+
- Use `mint-nft` command to mint individual NFTs to the collection
248+
- Token name is automatically registered as an alias after successful creation
249+
- Freeze default requires freeze key to be set
250+
251+
**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.
252+
156253
### Token Mint FT
157254

158255
Mint additional fungible tokens to increase supply. Tokens are minted to the token's treasury account.
@@ -433,6 +530,11 @@ The token file supports aliases and raw keys with optional key type prefixes:
433530
"freezeKey": "<alias or accountId:privateKey>",
434531
"pauseKey": "<alias or accountId:privateKey>",
435532
"feeScheduleKey": "<alias or accountId:privateKey>",
533+
"metadataKey": "<alias or accountId:privateKey>",
534+
"freezeDefault": false,
535+
"autoRenewPeriod": 7776000,
536+
"autoRenewAccountId": "<accountId>",
537+
"expirationTime": "2027-01-01T00:00:00Z",
436538
"memo": "Optional token memo",
437539
"associations": ["<alias or accountId:privateKey>", "..."],
438540
"customFees": [
@@ -491,6 +593,11 @@ The NFT file supports aliases and raw keys with optional key type prefixes:
491593
"freezeKey": "<alias or accountId:privateKey>",
492594
"pauseKey": "<alias or accountId:privateKey>",
493595
"feeScheduleKey": "<alias or accountId:privateKey>",
596+
"metadataKey": "<alias or accountId:privateKey>",
597+
"freezeDefault": false,
598+
"autoRenewPeriod": 7776000,
599+
"autoRenewAccountId": "<accountId>",
600+
"expirationTime": "2027-01-01T00:00:00Z",
494601
"memo": "Optional NFT collection memo",
495602
"associations": ["<alias or accountId:privateKey>", "..."]
496603
}
@@ -618,14 +725,36 @@ interface TokenData {
618725
supplyType: SupplyType;
619726
maxSupply: number;
620727
memo?: string;
728+
adminPublicKey?: string;
729+
supplyPublicKey?: string;
730+
wipePublicKey?: string;
731+
kycPublicKey?: string;
732+
freezePublicKey?: string;
733+
pausePublicKey?: string;
734+
feeSchedulePublicKey?: string;
735+
metadataPublicKey?: string;
621736
keys: TokenKeys;
622737
network: 'mainnet' | 'testnet' | 'previewnet' | 'localnet';
623738
associations: TokenAssociation[];
624739
customFees: CustomFee[];
625740
}
626741
```
627742

628-
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.
743+
**Field Descriptions:**
744+
745+
- `tokenType`: Discriminates fungible tokens (`FUNGIBLE_COMMON`) from NFT collections (`NON_FUNGIBLE_UNIQUE`)
746+
- `decimals`: Number of decimal places for fungible tokens; zero for NFTs
747+
- `initialSupply`: Initial supply amount; zero for NFTs
748+
- `adminPublicKey`: Public key with admin privileges for token operations
749+
- `supplyPublicKey`: Public key authorized to mint/burn tokens
750+
- `wipePublicKey`: Public key authorized to wipe token balances
751+
- `kycPublicKey`: Public key authorized to grant/revoke KYC status
752+
- `freezePublicKey`: Public key authorized to freeze token transfers
753+
- `pausePublicKey`: Public key authorized to pause all token transfers
754+
- `feeSchedulePublicKey`: Public key authorized to update custom fees
755+
- `metadataPublicKey`: Public key authorized to update token metadata
756+
757+
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.
629758

630759
## 🧪 Testing
631760

@@ -664,7 +793,7 @@ All commands support multiple output formats:
664793

665794
### Human-Readable (Default)
666795

667-
**Token Create:**
796+
**Fungible Token Create:**
668797

669798
```
670799
✅ Token created successfully: 0.0.12345
@@ -677,6 +806,17 @@ All commands support multiple output formats:
677806
Transaction ID: 0.0.123@1700000000.123456789
678807
```
679808

809+
**Non-Fungible Token Create:**
810+
811+
```
812+
✅ NFT created successfully: 0.0.123456
813+
Name: My NFT Collection (MNFT)
814+
Treasury: 0.0.111
815+
Supply Type: FINITE
816+
Network: testnet
817+
Transaction ID: 0.0.123@1700000000.123456789
818+
```
819+
680820
**FT Mint:**
681821

682822
```
@@ -713,6 +853,28 @@ All commands support multiple output formats:
713853
}
714854
```
715855

856+
**Non-Fungible Token Create:**
857+
858+
```json
859+
{
860+
"tokenId": "0.0.123456",
861+
"name": "My NFT Collection",
862+
"symbol": "MNFT",
863+
"treasuryId": "0.0.111",
864+
"supplyType": "FINITE",
865+
"transactionId": "0.0.123@1700000000.123456789",
866+
"adminPublicKey": "302e020100300506032b657004220420...",
867+
"supplyPublicKey": "302e020100300506032b657004220420...",
868+
"freezePublicKey": "302e020100300506032b657004220420...",
869+
"wipePublicKey": "302e020100300506032b657004220420...",
870+
"kycPublicKey": "302e020100300506032b657004220420...",
871+
"pausePublicKey": "302e020100300506032b657004220420...",
872+
"feeSchedulePublicKey": "302e020100300506032b657004220420...",
873+
"metadataPublicKey": "302e020100300506032b657004220420...",
874+
"network": "testnet"
875+
}
876+
```
877+
716878
**FT Mint:**
717879

718880
```json

0 commit comments

Comments
 (0)