11import type { CommandHandlerArgs } from '@/core/plugins/plugin.interface' ;
2+ import type { TokenCreateNftOutput } from '@/plugins/token/commands/create-nft/output' ;
23
34import { assertOutput } from '@/__tests__/utils/assert-output' ;
45import { AliasType } from '@/core/services/alias/alias-service.interface' ;
@@ -14,6 +15,7 @@ import {
1415 expectedNftTransactionParams ,
1516 makeNftCreateCommandArgs ,
1617 mockAccountIds ,
18+ mockAccountKeyPairs ,
1719 mockTransactions ,
1820} from './helpers/fixtures' ;
1921import {
@@ -173,7 +175,167 @@ describe('tokenCreateNftHandler', () => {
173175 } ) ;
174176 } ) ;
175177
178+ describe ( 'optional key scenarios' , ( ) => {
179+ test ( 'should create NFT with all optional keys' , async ( ) => {
180+ const mockSaveToken = jest . fn ( ) ;
181+ const mockSignResult = makeTransactionResult ( {
182+ tokenId : mockAccountIds . treasury ,
183+ } ) ;
184+
185+ MockedHelper . mockImplementation ( ( ) => ( {
186+ saveToken : mockSaveToken ,
187+ } ) ) ;
188+
189+ const { api, tokenTransactions } = makeApiMocks ( {
190+ tokenTransactions : {
191+ createTokenTransaction : jest
192+ . fn ( )
193+ . mockReturnValue ( mockTransactions . token ) ,
194+ } ,
195+ txExecute : {
196+ execute : jest . fn ( ) . mockResolvedValue ( mockSignResult ) ,
197+ } ,
198+ alias : {
199+ resolve : jest . fn ( ) . mockImplementation ( ( alias , type ) => {
200+ if ( type === AliasType . Account && alias === 'treasury-account' ) {
201+ return {
202+ entityId : '0.0.123456' ,
203+ publicKey : '302a300506032b6570032100' + '1' . repeat ( 64 ) ,
204+ keyRefId : 'treasury-key-ref-id' ,
205+ } ;
206+ }
207+ return null ;
208+ } ) ,
209+ } ,
210+ } ) ;
211+
212+ const logger = makeLogger ( ) ;
213+ const args : CommandHandlerArgs = {
214+ args : {
215+ tokenName : 'TestNFT' ,
216+ symbol : 'TNFT' ,
217+ supplyType : SupplyType . INFINITE ,
218+ treasury : 'treasury-account' ,
219+ freezeKey : mockAccountKeyPairs . freeze ,
220+ wipeKey : mockAccountKeyPairs . wipe ,
221+ pauseKey : mockAccountKeyPairs . pause ,
222+ kycKey : mockAccountKeyPairs . kyc ,
223+ feeScheduleKey : mockAccountKeyPairs . feeSchedule ,
224+ metadataKey : mockAccountKeyPairs . supply ,
225+ } ,
226+ api,
227+ state : api . state ,
228+ config : api . config ,
229+ logger,
230+ } ;
231+
232+ const result = await tokenCreateNft ( args ) ;
233+
234+ expect ( tokenTransactions . createTokenTransaction ) . toHaveBeenCalledWith (
235+ expect . objectContaining ( {
236+ freezePublicKey : expect . any ( Object ) ,
237+ wipePublicKey : expect . any ( Object ) ,
238+ pausePublicKey : expect . any ( Object ) ,
239+ kycPublicKey : expect . any ( Object ) ,
240+ feeSchedulePublicKey : expect . any ( Object ) ,
241+ metadataPublicKey : expect . any ( Object ) ,
242+ } ) ,
243+ ) ;
244+ assertOutput ( result . result , TokenCreateNftOutputSchema ) ;
245+ const output = result . result as TokenCreateNftOutput ;
246+ expect ( output . freezePublicKey ) . toBeDefined ( ) ;
247+ expect ( output . wipePublicKey ) . toBeDefined ( ) ;
248+ expect ( output . pausePublicKey ) . toBeDefined ( ) ;
249+ expect ( output . kycPublicKey ) . toBeDefined ( ) ;
250+ expect ( output . feeSchedulePublicKey ) . toBeDefined ( ) ;
251+ expect ( output . metadataPublicKey ) . toBeDefined ( ) ;
252+ } ) ;
253+
254+ test ( 'should create NFT with lifecycle params' , async ( ) => {
255+ const mockSaveToken = jest . fn ( ) ;
256+ const mockSignResult = makeTransactionResult ( {
257+ tokenId : mockAccountIds . treasury ,
258+ } ) ;
259+
260+ MockedHelper . mockImplementation ( ( ) => ( {
261+ saveToken : mockSaveToken ,
262+ } ) ) ;
263+
264+ const { api, tokenTransactions } = makeApiMocks ( {
265+ tokenTransactions : {
266+ createTokenTransaction : jest
267+ . fn ( )
268+ . mockReturnValue ( mockTransactions . token ) ,
269+ } ,
270+ txExecute : {
271+ execute : jest . fn ( ) . mockResolvedValue ( mockSignResult ) ,
272+ } ,
273+ alias : {
274+ resolve : jest . fn ( ) . mockImplementation ( ( alias , type ) => {
275+ if ( type === AliasType . Account && alias === 'treasury-account' ) {
276+ return {
277+ entityId : '0.0.123456' ,
278+ publicKey : '302a300506032b6570032100' + '1' . repeat ( 64 ) ,
279+ keyRefId : 'treasury-key-ref-id' ,
280+ } ;
281+ }
282+ return null ;
283+ } ) ,
284+ } ,
285+ } ) ;
286+
287+ const logger = makeLogger ( ) ;
288+ const args : CommandHandlerArgs = {
289+ args : {
290+ tokenName : 'TestNFT' ,
291+ symbol : 'TNFT' ,
292+ supplyType : SupplyType . INFINITE ,
293+ treasury : 'treasury-account' ,
294+ autoRenewPeriod : 7776000 ,
295+ autoRenewAccountId : '0.0.100000' ,
296+ expirationTime : '2027-01-01T00:00:00Z' ,
297+ } ,
298+ api,
299+ state : api . state ,
300+ config : api . config ,
301+ logger,
302+ } ;
303+
304+ const result = await tokenCreateNft ( args ) ;
305+
306+ expect ( tokenTransactions . createTokenTransaction ) . toHaveBeenCalledWith (
307+ expect . objectContaining ( {
308+ autoRenewPeriod : 7776000 ,
309+ autoRenewAccountId : '0.0.100000' ,
310+ expirationTime : expect . any ( Date ) ,
311+ } ) ,
312+ ) ;
313+ assertOutput ( result . result , TokenCreateNftOutputSchema ) ;
314+ } ) ;
315+ } ) ;
316+
176317 describe ( 'validation scenarios' , ( ) => {
318+ test ( 'should reject freezeDefault without freezeKey' , async ( ) => {
319+ const { api } = makeApiMocks ( ) ;
320+ const logger = makeLogger ( ) ;
321+ const args : CommandHandlerArgs = {
322+ args : {
323+ tokenName : 'TestNFT' ,
324+ symbol : 'TNFT' ,
325+ supplyType : SupplyType . INFINITE ,
326+ freezeDefault : true ,
327+ } ,
328+ api,
329+ state : api . state ,
330+ config : api . config ,
331+ logger,
332+ } ;
333+
334+ await expect ( tokenCreateNft ( args ) ) . rejects . toThrow (
335+ / f r e e z e D e f a u l t r e q u i r e s f r e e z e K e y / ,
336+ ) ;
337+ } ) ;
338+
177339 test ( 'should exit with error when no credentials found' , async ( ) => {
178340 // Arrange
179341 const { api, keyResolver } = makeApiMocks ( ) ;
0 commit comments