diff --git a/src/tokenManagement/resources.ts b/src/tokenManagement/resources.ts index 90c38eb3d..1886c4920 100644 --- a/src/tokenManagement/resources.ts +++ b/src/tokenManagement/resources.ts @@ -117,3 +117,21 @@ export type MintNftOutput = { }; export type EsdtOutput = { tokenIdentifier: string }; +export type ModifyRoyaltiesOutput = { tokenIdentifier: string; nonce: bigint; royalties: bigint }; +export type SetNewUrisOutput = { tokenIdentifier: string; nonce: bigint; uri: string }; +export type ModifyingCreatorOutput = { tokenIdentifier: string; nonce: bigint }; +export type UpdateAttibutesOutput = { tokenIdentifier: string; nonce: bigint; metadata: Uint8Array }; +export type ChangeToDynamicOutput = { + tokenIdentifier: string; + tokenName: string; + tickerName: string; + tokenType: string; +}; +export type UpdateTokenIDOutput = { caller: Address; tokenIdentifier: string; token: string }; +export type RegisterDynamicOutput = { + tokenIdentifier: string; + tokenName: string; + tokenTicker: string; + tokenType: string; + numOfDecimals: number; +}; diff --git a/src/tokenManagement/tokenManagementController.ts b/src/tokenManagement/tokenManagementController.ts index 45d99ed62..a00400d4e 100644 --- a/src/tokenManagement/tokenManagementController.ts +++ b/src/tokenManagement/tokenManagementController.ts @@ -491,4 +491,200 @@ export class TokenManagementController { parseBurnQuantity(transactionOnNetwork: TransactionOnNetwork): resources.EsdtOutput[] { return this.parser.parseBurnQuantity(transactionOnNetwork); } + + async createTransactionForModifyingRoyalties( + sender: IAccount, + nonce: bigint, + options: resources.ModifyRoyaltiesInput, + ): Promise { + const transaction = this.factory.createTransactionForModifyingRoyalties(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedModifyRoyalties(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseModifyRoyalties(transaction); + } + + parseModifyRoyalties(transactionOnNetwork: TransactionOnNetwork): resources.EsdtOutput[] { + return this.parser.parseModifyRoyalties(transactionOnNetwork); + } + + async createTransactionForSettingNewUris( + sender: IAccount, + nonce: bigint, + options: resources.SetNewUriInput, + ): Promise { + const transaction = this.factory.createTransactionForSettingNewUris(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedSetNewUris(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseSetNewUris(transaction); + } + + parseSetNewUris(transactionOnNetwork: TransactionOnNetwork): resources.EsdtOutput[] { + return this.parser.parseSetNewUris(transactionOnNetwork); + } + + async createTransactionForModifyingCreator( + sender: IAccount, + nonce: bigint, + options: resources.SetNewUriInput, + ): Promise { + const transaction = this.factory.createTransactionForModifyingCreator(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedModifyCreator(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseModifyCreator(transaction); + } + + parseModifyCreator(transactionOnNetwork: TransactionOnNetwork): resources.ModifyingCreatorOutput[] { + return this.parser.parseModifyCreator(transactionOnNetwork); + } + + async createTransactionForUpdatingMetadata( + sender: IAccount, + nonce: bigint, + options: resources.SetNewUriInput, + ): Promise { + const transaction = this.factory.createTransactionForModifyingCreator(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedUpdateMetadata(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseUpdateMetadata(transaction); + } + + parseUpdateMetadata(transactionOnNetwork: TransactionOnNetwork): resources.EsdtOutput[] { + return this.parser.parseUpdateMetadata(transactionOnNetwork); + } + + async createTransactionForMetadataRecreate( + sender: IAccount, + nonce: bigint, + options: resources.SetNewUriInput, + ): Promise { + const transaction = this.factory.createTransactionForMetadataRecreate(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedMetadataRecreate(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseMetadataRecreate(transaction); + } + + parseMetadataRecreate(transactionOnNetwork: TransactionOnNetwork): resources.EsdtOutput[] { + return this.parser.parseMetadataRecreate(transactionOnNetwork); + } + + async createTransactionForChangingTokenToDynamic( + sender: IAccount, + nonce: bigint, + options: resources.SetNewUriInput, + ): Promise { + const transaction = this.factory.createTransactionForChangingTokenToDynamic(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedChangeTokenToDynamic(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseChangeTokenToDynamic(transaction); + } + + parseChangeTokenToDynamic(transactionOnNetwork: TransactionOnNetwork): resources.ChangeToDynamicOutput[] { + return this.parser.parseChangeTokenToDynamic(transactionOnNetwork); + } + + async createTransactionForUpdatingTokenId( + sender: IAccount, + nonce: bigint, + options: resources.UpdateTokenIDInput, + ): Promise { + const transaction = this.factory.createTransactionForUpdatingTokenId(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedUpdateTokenId(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return transaction; + } + + async createTransactionForRegisteringDynamicToken( + sender: IAccount, + nonce: bigint, + options: resources.RegisteringDynamicTokenInput, + ): Promise { + const transaction = this.factory.createTransactionForRegisteringDynamicToken(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedRegisterDynamicToken(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseRegisterDynamicToken(transaction); + } + + parseRegisterDynamicToken(transactionOnNetwork: TransactionOnNetwork): resources.RegisterDynamicOutput[] { + return this.parser.parseRegisterDynamicToken(transactionOnNetwork); + } + + async createTransactionForRegisteringDynamicTokenAndSettingRoles( + sender: IAccount, + nonce: bigint, + options: resources.RegisteringDynamicTokenInput, + ): Promise { + const transaction = this.factory.createTransactionForRegisteringDynamicAndSettingRoles(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async awaitCompletedRegisterDynamicTokenAndSettingRoles(txHash: string): Promise { + const transaction = await this.transactionAwaiter.awaitCompleted(txHash); + return this.parseRegisterDynamicTokenAndSettingRoles(transaction); + } + + parseRegisterDynamicTokenAndSettingRoles( + transactionOnNetwork: TransactionOnNetwork, + ): resources.RegisterDynamicOutput[] { + return this.parser.parseRegisterDynamicTokenAndSettingRoles(transactionOnNetwork); + } } diff --git a/src/tokenManagement/tokenManagementTransactionsOutcomeParser.spec.ts b/src/tokenManagement/tokenManagementTransactionsOutcomeParser.spec.ts index d1749dbf6..583c137a4 100644 --- a/src/tokenManagement/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/tokenManagement/tokenManagementTransactionsOutcomeParser.spec.ts @@ -604,4 +604,260 @@ describe("test token management transactions outcome parser", () => { assert.equal(outcome[0].nonce, nonce); assert.equal(outcome[0].burntQuantity, burntQuantity); }); + + it("should test parse modify royalties", () => { + const identifier = "TEST-e2b0f9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const nonce = BigInt(1); + const royalties = 20n; + + const encodedTopics = [base64Identifier, "AQ==", "", "FA=="]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "ESDTModifyRoyalties", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseModifyRoyalties(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].royalties, royalties); + }); + + it("should test parse set new uris", () => { + const identifier = "TEST-e2b0f9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const nonce = BigInt(1); + const uri = "thisianuri.com"; + + const encodedTopics = [base64Identifier, "AQ==", "", "dGhpc2lhbnVyaS5jb20="]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "ESDTSetNewURIs", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseSetNewUris(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].uri, uri); + }); + + it("should test parse modify creator", () => { + const identifier = "TEST-e2b0f9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const nonce = BigInt(1); + + const encodedTopics = [base64Identifier, "AQ=="]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "ESDTModifyCreator", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseModifyCreator(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + }); + + it("should test parse update metadata", () => { + const identifier = "TEST-e2b0f9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const nonce = BigInt(1); + const metadata = new Uint8Array( + Buffer.from( + "CAUSAgABIlQIARIHVEVTVE5GVBogATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeEgHioIbmV3X2hhc2gyDnRoaXNpYW51cmkuY29tOgkAAAAAAAAAAwUqHgjH9a4DEMf1rgMYx/WuAyDH9a4DKMb1rgMwx/WuAw==", + "base64", + ), + ); + + const encodedTopics = [ + base64Identifier, + "AQ==", + "", + "CAUSAgABIlQIARIHVEVTVE5GVBogATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeEgHioIbmV3X2hhc2gyDnRoaXNpYW51cmkuY29tOgkAAAAAAAAAAwUqHgjH9a4DEMf1rgMYx/WuAyDH9a4DKMb1rgMwx/WuAw==", + ]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "ESDTMetaDataUpdate", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseUpdateMetadata(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.deepEqual(outcome[0].metadata, metadata); + }); + + it("should test parse recreate metadata", () => { + const identifier = "TEST-e2b0f9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const nonce = BigInt(1); + const metadata = new Uint8Array( + Buffer.from( + "CAUSAgABIlAIARIHVEVTVE5GVBogATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeEgHioSbmV3X2hhc2hfcmVjcmVhdGVkMgA6CQAAAAAAAABkASoeCMj1rgMQyPWuAxjI9a4DIMj1rgMoyPWuAzDI9a4D", + "base64", + ), + ); + + const encodedTopics = [ + base64Identifier, + "AQ==", + "", + "CAUSAgABIlAIARIHVEVTVE5GVBogATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeEgHioSbmV3X2hhc2hfcmVjcmVhdGVkMgA6CQAAAAAAAABkASoeCMj1rgMQyPWuAxjI9a4DIMj1rgMoyPWuAzDI9a4D", + ]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "ESDTMetaDataRecreate", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseMetadataRecreate(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.deepEqual(outcome[0].metadata, metadata); + }); + + it("should test parse change to dynamic", () => { + const identifier = "LKXOXNO-503365"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const tokenName = "LKXOXNO"; + const tokenTicker = "LKXOXNO"; + const tokenType = "DynamicMetaESDT"; + + const encodedTopics = [base64Identifier, "TEtYT1hOTw==", "TEtYT1hOTw==", "RHluYW1pY01ldGFFU0RU"]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "changeToDynamic", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseChangeTokenToDynamic(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].tokenName, tokenName); + assert.equal(outcome[0].tickerName, tokenTicker); + assert.deepEqual(outcome[0].tokenType, tokenType); + }); + + it("should test parse register dynamic", () => { + const identifier = "TEST-9bbb21"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const tokenName = "TESTNFT"; + const tokenTicker = "TEST"; + const tokenType = "DynamicNonFungibleESDT"; + + const encodedTopics = [base64Identifier, "VEVTVE5GVA==", "VEVTVA==", "RHluYW1pY05vbkZ1bmdpYmxlRVNEVA=="]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "registerDynamic", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseRegisterDynamicToken(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].tokenName, tokenName); + assert.equal(outcome[0].tokenTicker, tokenTicker); + assert.deepEqual(outcome[0].tokenType, tokenType); + }); + + it("should test parse register dynamic", () => { + const identifier = "TEST-9bbb21"; + const base64Identifier = Buffer.from(identifier).toString("base64"); + const tokenName = "TESTNFT"; + const tokenTicker = "TEST"; + const tokenType = "DynamicNonFungibleESDT"; + + const encodedTopics = [base64Identifier, "VEVTVE5GVA==", "VEVTVA==", "RHluYW1pY05vbkZ1bmdpYmxlRVNEVA=="]; + const event = new TransactionEvent({ + address: new Address("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"), + identifier: "registerAndSetAllRolesDynamic", + topics: b64TopicsToBytes(encodedTopics), + }); + + const transactionLogs = new TransactionLogs({ + address: new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), + events: [event], + }); + + const transaction = new TransactionOnNetwork({ + logs: transactionLogs, + }); + + const outcome = parser.parseRegisterDynamicTokenAndSettingRoles(transaction); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].tokenName, tokenName); + assert.equal(outcome[0].tokenTicker, tokenTicker); + assert.deepEqual(outcome[0].tokenType, tokenType); + }); }); diff --git a/src/tokenManagement/tokenManagementTransactionsOutcomeParser.ts b/src/tokenManagement/tokenManagementTransactionsOutcomeParser.ts index 8f9770706..81078d1ba 100644 --- a/src/tokenManagement/tokenManagementTransactionsOutcomeParser.ts +++ b/src/tokenManagement/tokenManagementTransactionsOutcomeParser.ts @@ -1,10 +1,20 @@ +import BigNumber from "bignumber.js"; import { bufferToBigInt } from "../abi/codec/utils"; import { Address } from "../address"; import { ErrParseTransactionOutcome } from "../errors"; import { TransactionEvent } from "../transactionEvents"; import { TransactionOnNetwork } from "../transactionOnNetwork"; import { findEventsByIdentifier } from "../transactionsOutcomeParsers/resources"; -import { MintNftOutput, SpecialRoleOutput } from "./resources"; +import { + ChangeToDynamicOutput, + MintNftOutput, + ModifyingCreatorOutput, + ModifyRoyaltiesOutput, + RegisterDynamicOutput, + SetNewUrisOutput, + SpecialRoleOutput, + UpdateAttibutesOutput, +} from "./resources"; export class TokenManagementTransactionsOutcomeParser { constructor() {} @@ -349,6 +359,135 @@ export class TokenManagementTransactionsOutcomeParser { }; } + parseModifyRoyalties(transaction: TransactionOnNetwork): ModifyRoyaltiesOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "ESDTModifyRoyalties"); + return events.map((event) => this.getOutputForESDTModifyRoyaltiesEvent(event)); + } + + private getOutputForESDTModifyRoyaltiesEvent(event: TransactionEvent): ModifyRoyaltiesOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const royalties = !event.topics[3]?.length + ? BigInt(0) + : BigInt(new BigNumber(Buffer.from(event.topics[3]).toString("hex"), 16).toFixed()); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + royalties, + }; + } + + parseSetNewUris(transaction: TransactionOnNetwork): SetNewUrisOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "ESDTSetNewURIs"); + return events.map((event) => this.getOutputForESDTSetNewURIsEvent(event)); + } + + private getOutputForESDTSetNewURIsEvent(event: TransactionEvent): SetNewUrisOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const uri = event.topics[3]?.length ? event.topics[3].toString() : ""; + return { tokenIdentifier, nonce, uri }; + } + + parseModifyCreator(transaction: TransactionOnNetwork): ModifyingCreatorOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "ESDTModifyCreator"); + return events.map((event) => this.getOutputForESDTModifyCreatorEvent(event)); + } + + private getOutputForESDTModifyCreatorEvent(event: TransactionEvent): ModifyingCreatorOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + + return { tokenIdentifier, nonce }; + } + + parseUpdateMetadata(transaction: TransactionOnNetwork): UpdateAttibutesOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "ESDTMetaDataUpdate"); + return events.map((event) => this.getOutputForESDTUpdateMetadataEvent(event)); + } + + private getOutputForESDTUpdateMetadataEvent(event: TransactionEvent): UpdateAttibutesOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const metadata = event.topics[3]?.length ? new Uint8Array(Buffer.from(event.topics[3])) : new Uint8Array(); + + return { tokenIdentifier, nonce, metadata }; + } + + parseMetadataRecreate(transaction: TransactionOnNetwork): UpdateAttibutesOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "ESDTMetaDataRecreate"); + return events.map((event) => this.getOutputForESDTMetadataRecreateEvent(event)); + } + + private getOutputForESDTMetadataRecreateEvent(event: TransactionEvent): UpdateAttibutesOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const metadata = event.topics[3]?.length ? new Uint8Array(Buffer.from(event.topics[3])) : new Uint8Array(); + + return { tokenIdentifier, nonce, metadata }; + } + + parseChangeTokenToDynamic(transaction: TransactionOnNetwork): ChangeToDynamicOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "changeToDynamic"); + return events.map((event) => this.getOutputForChangeToDynamicEvent(event)); + } + + private getOutputForChangeToDynamicEvent(event: TransactionEvent): ChangeToDynamicOutput { + const tokenIdentifier = this.extractTokenIdentifier(event); + const tokenName = event.topics[1]?.length ? event.topics[1].toString() : ""; + const tickerName = event.topics[2]?.length ? event.topics[2].toString() : ""; + const tokenType = event.topics[3]?.length ? event.topics[3].toString() : ""; + + return { tokenIdentifier, tokenName, tickerName, tokenType }; + } + + parseRegisterDynamicToken(transaction: TransactionOnNetwork): RegisterDynamicOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "registerDynamic"); + return events.map((event) => this.getOutputForRegisterDynamicToken(event)); + } + + private getOutputForRegisterDynamicToken(event: TransactionEvent): RegisterDynamicOutput { + const tokenIdentifier = event.topics[0]?.length ? event.topics[0].toString() : ""; + const tokenName = event.topics[1]?.length ? event.topics[1].toString() : ""; + const tokenTicker = event.topics[2]?.length ? event.topics[2].toString() : ""; + const tokenType = event.topics[3]?.length ? event.topics[3].toString() : ""; + const numOfDecimals = event.topics[4]?.length ? Number(Buffer.from(event.topics[4]).toString()) : 0; + + return { tokenIdentifier, tokenName, tokenTicker, tokenType, numOfDecimals }; + } + + parseRegisterDynamicTokenAndSettingRoles(transaction: TransactionOnNetwork): RegisterDynamicOutput[] { + this.ensureNoError(transaction.logs.events); + + const events = findEventsByIdentifier(transaction, "registerAndSetAllRolesDynamic"); + return events.map((event) => this.getOutputForRegisterDynamicTokenAndSettingRoles(event)); + } + + private getOutputForRegisterDynamicTokenAndSettingRoles(event: TransactionEvent): RegisterDynamicOutput { + const tokenIdentifier = event.topics[0]?.length ? event.topics[0].toString() : ""; + const tokenName = event.topics[1]?.length ? event.topics[1].toString() : ""; + const tokenTicker = event.topics[2]?.length ? event.topics[2].toString() : ""; + const tokenType = event.topics[3]?.length ? event.topics[3].toString() : ""; + const numOfDecimals = event.topics[4]?.length ? Number(Buffer.from(event.topics[4]).toString()) : 0; + + return { tokenIdentifier, tokenName, tokenTicker, tokenType, numOfDecimals }; + } + private ensureNoError(transactionEvents: TransactionEvent[]) { for (const event of transactionEvents) { if (event.identifier == "signalError") {