From b2e6b92d9bfbacc1c03d6670c576c05f8edd7f27 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 1 Sep 2023 14:36:25 +0300 Subject: [PATCH 001/275] transactionIntent & transactionIntentBuilder --- src/transactionIntent.ts | 17 ++++++ .../transactionIntentBuilder.ts | 53 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/transactionIntent.ts create mode 100644 src/transactionIntentsFactories/transactionIntentBuilder.ts diff --git a/src/transactionIntent.ts b/src/transactionIntent.ts new file mode 100644 index 000000000..680495a28 --- /dev/null +++ b/src/transactionIntent.ts @@ -0,0 +1,17 @@ +import { BigNumber } from "bignumber.js"; + +export class TransactionIntent { + public sender: string; + public receiver: string; + public gasLimit: BigNumber.Value; + public value?: BigNumber.Value; + public data?: Uint8Array; + + public constructor(sender: string, receiver: string, gasLimit: BigNumber.Value, value?: BigNumber.Value, data?: Uint8Array) { + this.sender = sender; + this.receiver = receiver; + this.gasLimit = gasLimit; + this.value = value; + this.data = data; + } +} diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionIntentsFactories/transactionIntentBuilder.ts new file mode 100644 index 000000000..545c2627b --- /dev/null +++ b/src/transactionIntentsFactories/transactionIntentBuilder.ts @@ -0,0 +1,53 @@ +import { BigNumber } from "bignumber.js"; +import { IAddress, ITransactionPayload } from "../interface"; +import { ARGUMENTS_SEPARATOR } from "../constants"; +import { TransactionPayload } from "../transactionPayload"; +import { TransactionIntent } from "../transactionIntent"; + +interface Config { + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; +} + +export class TransactionIntentBuilder { + private config: Config; + private sender: IAddress; + private receiver: IAddress; + private dataParts: string[]; + private executionGasLimit: BigNumber.Value; + private value?: BigNumber.Value; + + constructor(config: Config, sender: IAddress, receiver: IAddress, dataParts: string[], executionGasLimit: BigNumber.Value, value?: BigNumber.Value) { + this.config = config; + this.sender = sender; + this.receiver = receiver; + this.dataParts = dataParts; + this.executionGasLimit = executionGasLimit; + this.value = value; + } + + private computeGasLimit(payload: ITransactionPayload, executionGasLimit: BigNumber.Value): BigNumber.Value { + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).plus(new BigNumber(payload.length()))); + const gasLimit = new BigNumber(dataMovementGas).plus(new BigNumber(executionGasLimit)); + return gasLimit; + } + + private buildTransactionPayload(dataParts: string[]): ITransactionPayload { + const data = dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + build(): TransactionIntent { + const data = this.buildTransactionPayload(this.dataParts) + const gasLimit = this.computeGasLimit(data, this.executionGasLimit); + + + return new TransactionIntent( + this.sender.bech32(), + this.receiver.bech32(), + gasLimit, + this.value !== 0 ? this.value : 0, + data.valueOf() + ) + } +} From 2099f3d6dd845a636b45aa913e836b62e0bbf767 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 1 Sep 2023 17:21:07 +0300 Subject: [PATCH 002/275] started the sc intent factory --- src/constants.ts | 3 + src/tokenOperations/codec.ts | 5 +- .../smartContractTransactionIntentsFactory.ts | 77 +++++++++++++++++++ src/utils.codec.ts | 5 ++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts diff --git a/src/constants.ts b/src/constants.ts index 66d72198a..11df29f34 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -10,3 +10,6 @@ export const ESDTNFT_TRANSFER_FUNCTION_NAME = "ESDTNFTTransfer"; export const MULTI_ESDTNFT_TRANSFER_FUNCTION_NAME = "MultiESDTNFTTransfer"; export const ESDT_TRANSFER_VALUE = "0"; export const ARGUMENTS_SEPARATOR = "@"; +export const VM_TYPE_WASM_VM = new Uint8Array([0x05, 0x00]); +export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu" + diff --git a/src/tokenOperations/codec.ts b/src/tokenOperations/codec.ts index 3b33abfd6..8b9bc5988 100644 --- a/src/tokenOperations/codec.ts +++ b/src/tokenOperations/codec.ts @@ -32,10 +32,7 @@ export function bigIntToHex(value: BigNumber.Value): string { return contractsCodecUtils.getHexMagnitudeOfBigInt(value); } -export function utf8ToHex(value: string) { - const hex = Buffer.from(value).toString("hex"); - return codecUtils.zeroPadStringIfOddLength(hex); -} +export { utf8ToHex } from "../utils.codec"; export function bufferToHex(value: Buffer) { const hex = value.toString("hex"); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts new file mode 100644 index 000000000..1740d4809 --- /dev/null +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -0,0 +1,77 @@ +import { BigNumber } from "bignumber.js"; +import { IAddress } from "../interface"; +import { TransactionIntent } from "../transactionIntent"; +import { AbiRegistry, ArgSerializer, CodeMetadata, TypedValue } from "../smartcontracts"; +import { utf8ToHex } from "../utils.codec"; +import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; +import { NativeSerializer } from "../smartcontracts/nativeSerializer"; +import { Err } from "../errors"; +import { Address } from "../address"; +import { TransactionIntentBuilder } from "./transactionIntentBuilder"; + +interface Config { + chainID: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; +} + +export class SmartContractTransactionIntentsFactory { + private config: Config; + private abiRegistry?: AbiRegistry; + + constructor(config: Config, abi?: AbiRegistry) { + this.config = config; + this.abiRegistry = abi; + } + + createTransactionIntentForDeploy( + sender: IAddress, + bytecode: Uint8Array, + gasLimit: BigNumber.Value, + args: any[], + isUpgradeable: boolean = true, + isReadable: boolean = true, + isPayable: boolean = false, + isPayableBySmartContract: boolean = false + ): TransactionIntent { + const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); + let parts = [ + utf8ToHex(bytecode.toString()), + utf8ToHex(VM_TYPE_WASM_VM.toString()), + metadata.toString() + ]; + + parts = parts.concat(this.argsToStrings(args)); + + return new TransactionIntentBuilder( + this.config, + sender, + Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), + parts, + gasLimit + ).build() + } + + private argsToStrings(args: any): string[] { + if (this.abiRegistry !== undefined) { + const constructorDefinition = this.abiRegistry.constructorDefinition + const typedArgs = NativeSerializer.nativeToTypedValues(args, constructorDefinition) + return new ArgSerializer().valuesToStrings(args); + } + + if (this.areArgsOfTypedValue(args)) { + return new ArgSerializer().valuesToStrings(args); + } + + throw new Err("Can't convert args to TypedValues"); + } + + private areArgsOfTypedValue(args: any[]): boolean { + for (const arg of args) { + if (!(arg instanceof TypedValue)) { + return false; + } + } + return true; + } +} diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 8867c889f..eb369345e 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -20,3 +20,8 @@ export function zeroPadStringIfOddLength(input: string): string { return input; } + +export function utf8ToHex(value: string) { + const hex = Buffer.from(value).toString("hex"); + return zeroPadStringIfOddLength(hex); +} From a8091a992debf9c9d95c08b6c7e39aa7ddd06cf5 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 4 Sep 2023 14:59:08 +0300 Subject: [PATCH 003/275] add deploy intent and unit tests --- src/testdata/adder.abi.json | 62 ++++++++++++++++++ src/testdata/adder.wasm | Bin 0 -> 687 bytes ...tContractTransactionIntentsFactory.spec.ts | 60 +++++++++++++++++ .../smartContractTransactionIntentsFactory.ts | 10 +-- .../transactionIntentBuilder.ts | 6 +- src/utils.codec.ts | 4 ++ 6 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 src/testdata/adder.abi.json create mode 100755 src/testdata/adder.wasm create mode 100644 src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts diff --git a/src/testdata/adder.abi.json b/src/testdata/adder.abi.json new file mode 100644 index 000000000..88d5bf134 --- /dev/null +++ b/src/testdata/adder.abi.json @@ -0,0 +1,62 @@ +{ + "buildInfo": { + "rustc": { + "version": "1.71.0-nightly", + "commitHash": "7f94b314cead7059a71a265a8b64905ef2511796", + "commitDate": "2023-04-23", + "channel": "Nightly", + "short": "rustc 1.71.0-nightly (7f94b314c 2023-04-23)" + }, + "contractCrate": { + "name": "adder", + "version": "0.0.0" + }, + "framework": { + "name": "multiversx-sc", + "version": "0.41.3" + } + }, + "docs": [ + "One of the simplest smart contracts possible,", + "it holds a single variable in storage, which anyone can increment." + ], + "name": "Adder", + "constructor": { + "inputs": [ + { + "name": "initial_value", + "type": "BigUint" + } + ], + "outputs": [] + }, + "endpoints": [ + { + "name": "getSum", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "docs": [ + "Add desired amount to the storage variable." + ], + "name": "add", + "mutability": "mutable", + "inputs": [ + { + "name": "value", + "type": "BigUint" + } + ], + "outputs": [] + } + ], + "events": [], + "hasCallback": false, + "types": {} +} diff --git a/src/testdata/adder.wasm b/src/testdata/adder.wasm new file mode 100755 index 0000000000000000000000000000000000000000..77ce7e234a7c0110114e1527bd49705ec98ecf88 GIT binary patch literal 687 zcmZuvO>dh(5S`g2n6M3OW2=>;9w?{w)LYNNQXNIAqDpDcur_OK*+8{GBA@V2$hA@q z{XP9t?k?a+m3m-z=e;*?J_Lv=M*zT&P6Chswh3w5{)7ZuNNC%|<}v`b@8ztkbSl%c(}A6dtEGU|MAyrVW0x|qbRizhX24mLq@p$|T(}Jio literal 0 HcmV?d00001 diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts new file mode 100644 index 000000000..fbcd147ca --- /dev/null +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -0,0 +1,60 @@ +import { assert, expect } from "chai"; +import { SmartContractTransactionIntentsFactory } from "./smartContractTransactionIntentsFactory"; +import { Address } from "../address"; +import { Code } from "../smartcontracts/code"; +import { promises } from "fs"; +import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; +import { U32Value } from "../smartcontracts"; +import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; + +describe("test smart contract intents factory", function () { + let smartContractIntentsFactory: SmartContractTransactionIntentsFactory; + let abiSmartContractIntentsFactory: SmartContractTransactionIntentsFactory; + let adderByteCode: Code; + let abiRegistry: AbiRegistry; + + before(async function () { + smartContractIntentsFactory = new SmartContractTransactionIntentsFactory({ chainID: "D", minGasLimit: 50000, gasLimitPerByte: 1500 }); + let adderBuffer = await promises.readFile("src/testdata/adder.wasm"); + adderByteCode = Code.fromBuffer(adderBuffer); + + let abiJson = await promises.readFile("src/testdata/adder.abi.json", { encoding: "utf8" }); + let abiObj = JSON.parse(abiJson); + abiRegistry = AbiRegistry.create(abiObj); + + abiSmartContractIntentsFactory = new SmartContractTransactionIntentsFactory({ chainID: "D", minGasLimit: 50000, gasLimitPerByte: 1500 }, abiRegistry); + }); + + it("should throw error", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const gasLimit = 6000000; + const args = [0]; + try { + smartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); + } + catch (err) { + expect(err.message).to.equal("Can't convert args to TypedValues"); + } + }); + + it("should build deploy intent", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const gasLimit = 6000000; + const args = [new U32Value(0)]; + + const deployIntent = smartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); + const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); + + assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(deployIntent.receiver, CONTRACT_DEPLOY_ADDRESS); + assert.isDefined(deployIntent.data); + + if (deployIntent.data) { + const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; + assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); + } + assert.equal(deployIntent.value, 0); + + assert.deepEqual(deployIntent, abiDeployIntent); + }); +}); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 1740d4809..ec95be6de 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -2,7 +2,7 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { TransactionIntent } from "../transactionIntent"; import { AbiRegistry, ArgSerializer, CodeMetadata, TypedValue } from "../smartcontracts"; -import { utf8ToHex } from "../utils.codec"; +import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err } from "../errors"; @@ -32,12 +32,12 @@ export class SmartContractTransactionIntentsFactory { isUpgradeable: boolean = true, isReadable: boolean = true, isPayable: boolean = false, - isPayableBySmartContract: boolean = false + isPayableBySmartContract: boolean = true ): TransactionIntent { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [ - utf8ToHex(bytecode.toString()), - utf8ToHex(VM_TYPE_WASM_VM.toString()), + byteArrayToHex(bytecode), + byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString() ]; @@ -52,7 +52,7 @@ export class SmartContractTransactionIntentsFactory { ).build() } - private argsToStrings(args: any): string[] { + private argsToStrings(args: any[]): string[] { if (this.abiRegistry !== undefined) { const constructorDefinition = this.abiRegistry.constructorDefinition const typedArgs = NativeSerializer.nativeToTypedValues(args, constructorDefinition) diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionIntentsFactories/transactionIntentBuilder.ts index 545c2627b..5f80c4b06 100644 --- a/src/transactionIntentsFactories/transactionIntentBuilder.ts +++ b/src/transactionIntentsFactories/transactionIntentBuilder.ts @@ -27,12 +27,12 @@ export class TransactionIntentBuilder { } private computeGasLimit(payload: ITransactionPayload, executionGasLimit: BigNumber.Value): BigNumber.Value { - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).plus(new BigNumber(payload.length()))); + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(new BigNumber(payload.length()))); const gasLimit = new BigNumber(dataMovementGas).plus(new BigNumber(executionGasLimit)); return gasLimit; } - private buildTransactionPayload(dataParts: string[]): ITransactionPayload { + private buildTransactionPayload(dataParts: string[]): TransactionPayload { const data = dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } @@ -46,7 +46,7 @@ export class TransactionIntentBuilder { this.sender.bech32(), this.receiver.bech32(), gasLimit, - this.value !== 0 ? this.value : 0, + this.value !== undefined ? this.value : 0, data.valueOf() ) } diff --git a/src/utils.codec.ts b/src/utils.codec.ts index eb369345e..2d79785b5 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -25,3 +25,7 @@ export function utf8ToHex(value: string) { const hex = Buffer.from(value).toString("hex"); return zeroPadStringIfOddLength(hex); } + +export function byteArrayToHex(byteArray: Uint8Array): string { + return Buffer.from(byteArray).toString("hex"); +} From 7db0a4a96f6aade942e37adda931c349389ba166 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 4 Sep 2023 20:17:12 +0300 Subject: [PATCH 004/275] smart contract transaction intents factory --- ...tContractTransactionIntentsFactory.spec.ts | 48 ++++++++++ .../smartContractTransactionIntentsFactory.ts | 94 ++++++++++++++++--- .../transactionIntentBuilder.ts | 7 +- 3 files changed, 133 insertions(+), 16 deletions(-) diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index fbcd147ca..1b02baa79 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -57,4 +57,52 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); + + it("should build execute intent", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + + const deployIntent = smartContractIntentsFactory.createTransactionIntentForExecute(sender, contract, func, gasLimit, args); + const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForExecute(sender, contract, func, gasLimit, args); + + assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + + assert.isDefined(deployIntent.data); + let decoder = new TextDecoder(); + assert.equal(decoder.decode(deployIntent.data), "add@07"); + + assert.equal(deployIntent.gasLimit.valueOf(), 6059000); + assert.equal(deployIntent.value, 0); + + assert.deepEqual(deployIntent, abiDeployIntent); + }); + + it("should build upgrade intent", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const gasLimit = 6000000; + const args = [new U32Value(0)]; + + const deployIntent = smartContractIntentsFactory.createTransactionIntentForUpgrade(sender, contract, adderByteCode.valueOf(), gasLimit, args); + const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForUpgrade(sender, contract, adderByteCode.valueOf(), gasLimit, args); + + assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.isDefined(deployIntent.data); + + if (deployIntent.data) { + let decoder = new TextDecoder(); + assert(decoder.decode(deployIntent.data).startsWith("upgradeContract@", 0)); + + const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; + assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); + } + assert.equal(deployIntent.value, 0); + + assert.deepEqual(deployIntent, abiDeployIntent); + }); }); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index ec95be6de..89fb089c9 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { TransactionIntent } from "../transactionIntent"; -import { AbiRegistry, ArgSerializer, CodeMetadata, TypedValue } from "../smartcontracts"; +import { AbiRegistry, ArgSerializer, CodeMetadata, EndpointDefinition, TypedValue } from "../smartcontracts"; import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; @@ -29,10 +29,10 @@ export class SmartContractTransactionIntentsFactory { bytecode: Uint8Array, gasLimit: BigNumber.Value, args: any[], - isUpgradeable: boolean = true, - isReadable: boolean = true, - isPayable: boolean = false, - isPayableBySmartContract: boolean = true + isUpgradeable = true, + isReadable = true, + isPayable = false, + isPayableBySmartContract = true ): TransactionIntent { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [ @@ -41,7 +41,14 @@ export class SmartContractTransactionIntentsFactory { metadata.toString() ]; - parts = parts.concat(this.argsToStrings(args)); + let preparedArgs: string[]; + if (this.abiRegistry) { + preparedArgs = this.argsToStrings(args, this.abiRegistry.constructorDefinition) + } + else { + preparedArgs = this.argsToStrings(args) + } + parts = parts.concat(preparedArgs); return new TransactionIntentBuilder( this.config, @@ -49,14 +56,77 @@ export class SmartContractTransactionIntentsFactory { Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), parts, gasLimit - ).build() + ).build(); } - private argsToStrings(args: any[]): string[] { - if (this.abiRegistry !== undefined) { - const constructorDefinition = this.abiRegistry.constructorDefinition - const typedArgs = NativeSerializer.nativeToTypedValues(args, constructorDefinition) - return new ArgSerializer().valuesToStrings(args); + createTransactionIntentForExecute( + sender: IAddress, + contractAddress: IAddress, + func: string, + gasLimit: BigNumber.Value, + args: any[] = [] + ): TransactionIntent { + let parts: string[] = [func]; + + let preparedArgs: string[]; + if (this.abiRegistry) { + preparedArgs = this.argsToStrings(args, this.abiRegistry.getEndpoint(func)); + } + else { + preparedArgs = this.argsToStrings(args); + } + parts = parts.concat(preparedArgs); + + return new TransactionIntentBuilder( + this.config, + sender, + contractAddress, + parts, + gasLimit + ).build(); + } + + createTransactionIntentForUpgrade( + sender: IAddress, + contract: IAddress, + bytecode: Uint8Array, + gasLimit: BigNumber.Value, + args: any[], + isUpgradeable = true, + isReadable = true, + isPayable = false, + isPayableBySmartContract = true + ): TransactionIntent { + const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); + + let parts = [ + "upgradeContract", + byteArrayToHex(bytecode), + metadata.toString() + ]; + + let preparedArgs: string[]; + if (this.abiRegistry) { + preparedArgs = this.argsToStrings(args, this.abiRegistry.constructorDefinition) + } + else { + preparedArgs = this.argsToStrings(args) + } + parts = parts.concat(preparedArgs); + + return new TransactionIntentBuilder( + this.config, + sender, + contract, + parts, + gasLimit + ).build(); + } + + private argsToStrings(args: any[], endpoint?: EndpointDefinition): string[] { + if (endpoint) { + const typedArgs = NativeSerializer.nativeToTypedValues(args, endpoint) + return new ArgSerializer().valuesToStrings(typedArgs); } if (this.areArgsOfTypedValue(args)) { diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionIntentsFactories/transactionIntentBuilder.ts index 5f80c4b06..ffa1f42bb 100644 --- a/src/transactionIntentsFactories/transactionIntentBuilder.ts +++ b/src/transactionIntentsFactories/transactionIntentBuilder.ts @@ -32,16 +32,15 @@ export class TransactionIntentBuilder { return gasLimit; } - private buildTransactionPayload(dataParts: string[]): TransactionPayload { - const data = dataParts.join(ARGUMENTS_SEPARATOR); + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } build(): TransactionIntent { - const data = this.buildTransactionPayload(this.dataParts) + const data = this.buildTransactionPayload() const gasLimit = this.computeGasLimit(data, this.executionGasLimit); - return new TransactionIntent( this.sender.bech32(), this.receiver.bech32(), From c3d746846fb73543d757df34725d570ff52c39f6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 5 Sep 2023 14:56:18 +0300 Subject: [PATCH 005/275] start delegation transaction intents factory --- src/constants.ts | 1 + ...elegationTransactionIntentsFactory.spec.ts | 123 ++++++++++++++++ .../delegationTransactionIntentsFactory.ts | 137 ++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts create mode 100644 src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts diff --git a/src/constants.ts b/src/constants.ts index 11df29f34..eb3ea8c8c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -12,4 +12,5 @@ export const ESDT_TRANSFER_VALUE = "0"; export const ARGUMENTS_SEPARATOR = "@"; export const VM_TYPE_WASM_VM = new Uint8Array([0x05, 0x00]); export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu" +export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts new file mode 100644 index 000000000..57588fefc --- /dev/null +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts @@ -0,0 +1,123 @@ +import BigNumber from "bignumber.js"; +import { Address } from "../address"; +import { DelegationTransactionIntentsFactory } from "./delegationTransactionIntentsFactory"; +import { assert } from "chai"; +import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; +import { ValidatorPublicKey } from "@multiversx/sdk-wallet-next"; +import { SignableMessage } from "../signableMessage"; + +describe("test delegation intents factory", function () { + const delegationFactory = new DelegationTransactionIntentsFactory({ + chainID: "D", + minGasLimit: 50000, + gasLimitPerByte: 1500, + gasLimitStake: 5000000, + gasLimitUnstake: 5000000, + gasLimitUnbond: 5000000, + gasLimitCreateDelegationContract: 50000000, + gasLimitDelegationOperations: 1000000, + additionalGasLimitPerValidatorNode: 6000000, + additionalGasLimitForDelegationOperations: 10000000 + }); + + it("should build intent for new delegation contract", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delagationCap = new BigNumber("5000000000000000000000"); + const serviceFee = new BigNumber(10); + const value = new BigNumber("1250000000000000000000"); + + const intent = delegationFactory.createTransactionIntentForNewDelegationContract( + sender, + delagationCap, + serviceFee, + value + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, DELEGATION_MANAGER_SC_ADDRESS); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "createNewDelegationContract@010f0cf064dd59200000@0a"); + + assert.equal(intent.gasLimit.valueOf(), 60126500); + assert.equal(intent.value, value); + }); + + it("should build intent for adding nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); + + const signedMessage = new SignableMessage(); + signedMessage.applySignature(Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex")); + + const intent = delegationFactory.createTransactionIntentForAddingNodes( + sender, + delegationContract, + [publicKey], + [signedMessage.getSignature()] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for removing nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const publicKey = { + hex(): string { + return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + } + }; + + const intent = delegationFactory.createTransactionIntentForRemovingNodes( + sender, + delegationContract, + [publicKey] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "removeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); + + assert.equal(intent.value, 0); + }); + + it.only("should build intent for staking nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const publicKey = { + hex(): string { + return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + } + }; + + const intent = delegationFactory.createTransactionIntentForStakingNodes( + sender, + delegationContract, + [publicKey] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "stakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); + + assert.equal(intent.value, 0); + }); +}); diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts new file mode 100644 index 000000000..91247e459 --- /dev/null +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -0,0 +1,137 @@ +import { IAddress } from "../interface"; +import { BigNumber } from "bignumber.js"; +import { numberToPaddedHex, byteArrayToHex } from "../utils.codec"; +import { TransactionIntent } from "../transactionIntent"; +import { TransactionIntentBuilder } from "./transactionIntentBuilder"; +import { Address } from "../address"; +import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; +import { Err } from "../errors"; + +interface Config { + chainID: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; + gasLimitStake: BigNumber.Value; + gasLimitUnstake: BigNumber.Value; + gasLimitUnbond: BigNumber.Value; + gasLimitCreateDelegationContract: BigNumber.Value; + gasLimitDelegationOperations: BigNumber.Value; + additionalGasLimitPerValidatorNode: BigNumber.Value; + additionalGasLimitForDelegationOperations: BigNumber.Value; +} + +interface ValidatorPublicKey { + hex(): string; +} + +export class DelegationTransactionIntentsFactory { + private config: Config; + + constructor(config: Config) { + this.config = config; + } + + createTransactionIntentForNewDelegationContract( + sender: IAddress, + totalDelegationCap: BigNumber.Value, + serviceFee: BigNumber.Value, + value: BigNumber.Value + ): TransactionIntent { + const dataParts = [ + "createNewDelegationContract", + numberToPaddedHex(totalDelegationCap.toString()), + numberToPaddedHex(serviceFee.toString()) + ]; + + const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)); + + return new TransactionIntentBuilder( + this.config, + sender, + Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), + dataParts, + executionGasLimit, + value + ).build(); + } + + createTransactionIntentForAddingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[], + signedMessages: Uint8Array[] + ): TransactionIntent { + if (publicKeys.length !== signedMessages.length) { + throw new Err("The number of public keys should match the number of signed messages"); + } + + const numNodes = publicKeys.length; + + let dataParts = ["addNodes"]; + for (let i = 0; i < numNodes; i++) { + dataParts = dataParts.concat(publicKeys[i].hex()); + dataParts = dataParts.concat(byteArrayToHex(signedMessages[i])); + } + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + this.computeExecutionGasLimitForNodesManagement(numNodes) + ).build(); + } + + createTransactionIntentForRemovingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[] + ): TransactionIntent { + let dataParts = ["removeNodes"]; + + for (const key of publicKeys) { + dataParts = dataParts.concat(key.hex()); + } + + const numNodes = publicKeys.length; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + this.computeExecutionGasLimitForNodesManagement(numNodes) + ).build(); + } + + createTransactionIntentForStakingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[] + ): TransactionIntent { + let dataParts = ["stakeNodes"]; + + for (const key of publicKeys) { + dataParts = dataParts.concat(key.hex()); + } + + const numNodes = publicKeys.length; + const executionGasLimit = new BigNumber(numNodes).multipliedBy( + new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( + new BigNumber(this.config.gasLimitStake) + ).plus(this.config.gasLimitDelegationOperations); + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + executionGasLimit + ).build(); + } + + private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { + const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(new BigNumber(numNodes)); + return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); + } +} From 5ca9d42536427c2d6a3aa6c8650ecff4b52bfeeb Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 6 Sep 2023 12:16:03 +0300 Subject: [PATCH 006/275] delegation transaction intents factory --- ...elegationTransactionIntentsFactory.spec.ts | 222 +++++++++++++++++- .../delegationTransactionIntentsFactory.ts | 215 ++++++++++++++++- 2 files changed, 432 insertions(+), 5 deletions(-) diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts index 57588fefc..1277d8031 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts @@ -95,7 +95,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it.only("should build intent for staking nodes", async function () { + it("should build intent for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -120,4 +120,224 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); + + it("should build intent for unbonding nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const publicKey = { + hex(): string { + return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + } + }; + + const intent = delegationFactory.createTransactionIntentForUnbondingNodes( + sender, + delegationContract, + [publicKey] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "unBondNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); + + assert.equal(intent.value, 0); + assert.equal(intent.gasLimit.valueOf(), 12143000); + }); + + it("should build intent for unstaking nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const publicKey = { + hex(): string { + return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + } + }; + + const intent = delegationFactory.createTransactionIntentForUnstakingNodes( + sender, + delegationContract, + [publicKey] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "unStakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); + + assert.equal(intent.value, 0); + assert.equal(intent.gasLimit.valueOf(), 12144500); + }); + + it("should build intent for unjailing nodes", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const publicKey = { + hex(): string { + return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + } + }; + + const intent = delegationFactory.createTransactionIntentForUnjailingNodes( + sender, + delegationContract, + [publicKey] + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "unJailNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for changing service fee", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + const serviceFee = new BigNumber(10); + + const intent = delegationFactory.createTransactionIntentForChangingServiceFee( + sender, + delegationContract, + serviceFee + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "changeServiceFee@0a"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for changing delegation cap", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + const delegationCap = new BigNumber("5000000000000000000000"); + + const intent = delegationFactory.createTransactionIntentForModifyingDelegationCap( + sender, + delegationContract, + delegationCap + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "modifyTotalDelegationCap@010f0cf064dd59200000"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for setting automatic activation", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const intent = delegationFactory.createTransactionIntentForSettingAutomaticActivation( + sender, + delegationContract + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "setAutomaticActivation@74727565"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for unsetting automatic activation", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const intent = delegationFactory.createTransactionIntentForUnsettingAutomaticActivation( + sender, + delegationContract + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "setAutomaticActivation@66616c7365"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for setting cap check on redelegate rewards", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const intent = delegationFactory.createTransactionIntentForSettingCapCheckOnRedelegateRewards( + sender, + delegationContract + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "setCheckCapOnReDelegateRewards@74727565"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for unsetting cap check on redelegate rewards", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const intent = delegationFactory.createTransactionIntentForUnsettingCapCheckOnRedelegateRewards( + sender, + delegationContract + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "setCheckCapOnReDelegateRewards@66616c7365"); + + assert.equal(intent.value, 0); + }); + + it("should build intent for setting metadata", async function () { + const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + + const intent = delegationFactory.createTransactionIntentForSettingMetadata( + sender, + delegationContract, + "name", + "website", + "identifier" + ); + + assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(intent.data); + + let decoder = new TextDecoder(); + assert.equal(decoder.decode(intent.data), "setMetaData@6e616d65@77656273697465@6964656e746966696572"); + + assert.equal(intent.value, 0); + }); }); diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index 91247e459..9da652d4a 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -1,6 +1,6 @@ import { IAddress } from "../interface"; import { BigNumber } from "bignumber.js"; -import { numberToPaddedHex, byteArrayToHex } from "../utils.codec"; +import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TransactionIntent } from "../transactionIntent"; import { TransactionIntentBuilder } from "./transactionIntentBuilder"; import { Address } from "../address"; @@ -82,6 +82,11 @@ export class DelegationTransactionIntentsFactory { ).build(); } + private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { + const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(new BigNumber(numNodes)); + return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); + } + createTransactionIntentForRemovingNodes( sender: IAddress, delegationContract: IAddress, @@ -130,8 +135,210 @@ export class DelegationTransactionIntentsFactory { ).build(); } - private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { - const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(new BigNumber(numNodes)); - return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); + createTransactionIntentForUnbondingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[] + ): TransactionIntent { + let dataParts = ["unBondNodes"]; + + for (const key of publicKeys) { + dataParts = dataParts.concat(key.hex()); + } + + const numNodes = publicKeys.length; + const executionGasLimit = new BigNumber(numNodes).multipliedBy( + new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( + new BigNumber(this.config.gasLimitUnbond) + ).plus(this.config.gasLimitDelegationOperations); + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + executionGasLimit + ).build(); + } + + createTransactionIntentForUnstakingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[] + ): TransactionIntent { + let dataParts = ["unStakeNodes"]; + + for (const key of publicKeys) { + dataParts = dataParts.concat(key.hex()); + } + + const numNodes = publicKeys.length; + const executionGasLimit = new BigNumber(numNodes).multipliedBy( + new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( + new BigNumber(this.config.gasLimitUnstake) + ).plus(this.config.gasLimitDelegationOperations); + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + executionGasLimit + ).build(); + } + + createTransactionIntentForUnjailingNodes( + sender: IAddress, + delegationContract: IAddress, + publicKeys: ValidatorPublicKey[] + ): TransactionIntent { + let dataParts = ["unJailNodes"]; + + for (const key of publicKeys) { + dataParts = dataParts.concat(key.hex()); + } + + const numNodes = publicKeys.length; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + this.computeExecutionGasLimitForNodesManagement(numNodes) + ).build(); + } + + createTransactionIntentForChangingServiceFee( + sender: IAddress, + delegationContract: IAddress, + serviceFee: BigNumber.Value + ): TransactionIntent { + const dataParts = [ + "changeServiceFee", + numberToPaddedHex(serviceFee) + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForModifyingDelegationCap( + sender: IAddress, + delegationContract: IAddress, + delegationCap: BigNumber.Value + ): TransactionIntent { + const dataParts = [ + "modifyTotalDelegationCap", + numberToPaddedHex(delegationCap) + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForSettingAutomaticActivation( + sender: IAddress, + delegationContract: IAddress + ): TransactionIntent { + const dataParts = [ + "setAutomaticActivation", + utf8ToHex("true") + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForUnsettingAutomaticActivation( + sender: IAddress, + delegationContract: IAddress + ): TransactionIntent { + const dataParts = [ + "setAutomaticActivation", + utf8ToHex("false") + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForSettingCapCheckOnRedelegateRewards( + sender: IAddress, + delegationContract: IAddress + ): TransactionIntent { + const dataParts = [ + "setCheckCapOnReDelegateRewards", + utf8ToHex("true") + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForUnsettingCapCheckOnRedelegateRewards( + sender: IAddress, + delegationContract: IAddress + ): TransactionIntent { + const dataParts = [ + "setCheckCapOnReDelegateRewards", + utf8ToHex("false") + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); + } + + createTransactionIntentForSettingMetadata( + sender: IAddress, + delegationContract: IAddress, + name: string, + website: string, + identifier: string + ): TransactionIntent { + const dataParts = [ + "setMetaData", + utf8ToHex(name), + utf8ToHex(website), + utf8ToHex(identifier) + ]; + + return new TransactionIntentBuilder( + this.config, + sender, + delegationContract, + dataParts, + new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + ).build(); } } From 5ba4506d488371109b3bb2250283ac54deeaf984 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 7 Sep 2023 17:26:35 +0300 Subject: [PATCH 007/275] fixes after review --- src/transactionIntent.ts | 18 ++- ...tContractTransactionIntentsFactory.spec.ts | 123 ++++++++++++---- .../smartContractTransactionIntentsFactory.ts | 138 +++++++++--------- .../transactionIntentBuilder.ts | 39 +++-- src/utils.codec.spec.ts | 16 +- 5 files changed, 212 insertions(+), 122 deletions(-) diff --git a/src/transactionIntent.ts b/src/transactionIntent.ts index 680495a28..43cb9e36c 100644 --- a/src/transactionIntent.ts +++ b/src/transactionIntent.ts @@ -7,11 +7,17 @@ export class TransactionIntent { public value?: BigNumber.Value; public data?: Uint8Array; - public constructor(sender: string, receiver: string, gasLimit: BigNumber.Value, value?: BigNumber.Value, data?: Uint8Array) { - this.sender = sender; - this.receiver = receiver; - this.gasLimit = gasLimit; - this.value = value; - this.data = data; + public constructor(options: { + sender: string, + receiver: string, + gasLimit: BigNumber.Value, + value?: BigNumber.Value, + data?: Uint8Array + }) { + this.sender = options.sender; + this.receiver = options.receiver; + this.gasLimit = options.gasLimit; + this.value = options.value; + this.data = options.data; } } diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index 1b02baa79..c2a8513c6 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -2,52 +2,78 @@ import { assert, expect } from "chai"; import { SmartContractTransactionIntentsFactory } from "./smartContractTransactionIntentsFactory"; import { Address } from "../address"; import { Code } from "../smartcontracts/code"; -import { promises } from "fs"; import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; import { U32Value } from "../smartcontracts"; import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; +import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; +import { Err } from "../errors"; describe("test smart contract intents factory", function () { - let smartContractIntentsFactory: SmartContractTransactionIntentsFactory; - let abiSmartContractIntentsFactory: SmartContractTransactionIntentsFactory; + let factory: SmartContractTransactionIntentsFactory; + let abiAwareFactory: SmartContractTransactionIntentsFactory; let adderByteCode: Code; let abiRegistry: AbiRegistry; before(async function () { - smartContractIntentsFactory = new SmartContractTransactionIntentsFactory({ chainID: "D", minGasLimit: 50000, gasLimitPerByte: 1500 }); - let adderBuffer = await promises.readFile("src/testdata/adder.wasm"); - adderByteCode = Code.fromBuffer(adderBuffer); - - let abiJson = await promises.readFile("src/testdata/adder.abi.json", { encoding: "utf8" }); - let abiObj = JSON.parse(abiJson); - abiRegistry = AbiRegistry.create(abiObj); - - abiSmartContractIntentsFactory = new SmartContractTransactionIntentsFactory({ chainID: "D", minGasLimit: 50000, gasLimitPerByte: 1500 }, abiRegistry); + factory = new SmartContractTransactionIntentsFactory({ + config: + { + chainID: "D", + minGasLimit: 50000, + gasLimitPerByte: 1500 + } + }); + + adderByteCode = await loadContractCode("src/testdata/adder.wasm"); + abiRegistry = await loadAbiRegistry("src/testdata/adder.abi.json"); + + abiAwareFactory = new SmartContractTransactionIntentsFactory({ + config: + { + chainID: "D", + minGasLimit: 50000, + gasLimitPerByte: 1500 + }, + abi: abiRegistry + }, + ); }); - it("should throw error", async function () { + it("should throw error when args are not of type 'TypedValue'", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [0]; - try { - smartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); - } - catch (err) { - expect(err.message).to.equal("Can't convert args to TypedValues"); - } + + assert.throws(() => factory.createTransactionIntentForDeploy({ + sender: sender, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args + }), Err, "Can't convert args to TypedValues"); }); - it("should build deploy intent", async function () { + it("should build intent for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = smartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); - const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForDeploy(sender, adderByteCode.valueOf(), gasLimit, args); + const deployIntent = factory.createTransactionIntentForDeploy({ + sender: sender, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args + }); + const abiDeployIntent = abiAwareFactory.createTransactionIntentForDeploy({ + sender: sender, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args + }); assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, CONTRACT_DEPLOY_ADDRESS); assert.isDefined(deployIntent.data); + expect(deployIntent.data?.length).to.be.greaterThan(0); if (deployIntent.data) { const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; @@ -58,22 +84,33 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should build execute intent", async function () { + it("should build intent for execute", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; const gasLimit = 6000000; const args = [new U32Value(7)]; - const deployIntent = smartContractIntentsFactory.createTransactionIntentForExecute(sender, contract, func, gasLimit, args); - const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForExecute(sender, contract, func, gasLimit, args); + const deployIntent = factory.createTransactionIntentForExecute({ + sender: sender, + contractAddress: contract, + func: func, + gasLimit: gasLimit, + args: args + }); + const abiDeployIntent = abiAwareFactory.createTransactionIntentForExecute({ + sender: sender, + contractAddress: contract, + func: func, + gasLimit: gasLimit, + args: args + }); assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.isDefined(deployIntent.data); - let decoder = new TextDecoder(); - assert.equal(decoder.decode(deployIntent.data), "add@07"); + assert.deepEqual(deployIntent.data, Buffer.from("add@07")); assert.equal(deployIntent.gasLimit.valueOf(), 6059000); assert.equal(deployIntent.value, 0); @@ -81,22 +118,33 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should build upgrade intent", async function () { + it("should build intent for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = smartContractIntentsFactory.createTransactionIntentForUpgrade(sender, contract, adderByteCode.valueOf(), gasLimit, args); - const abiDeployIntent = abiSmartContractIntentsFactory.createTransactionIntentForUpgrade(sender, contract, adderByteCode.valueOf(), gasLimit, args); + const deployIntent = factory.createTransactionIntentForUpgrade({ + sender: sender, + contract: contract, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args + }); + const abiDeployIntent = abiAwareFactory.createTransactionIntentForUpgrade({ + sender: sender, + contract: contract, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args + }); assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.isDefined(deployIntent.data); if (deployIntent.data) { - let decoder = new TextDecoder(); - assert(decoder.decode(deployIntent.data).startsWith("upgradeContract@", 0)); + assert(checkIfByteArrayStartsWith(deployIntent.data, "upgradeContract@")); const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); @@ -105,4 +153,15 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); + + function checkIfByteArrayStartsWith(array: Uint8Array, sequence: string) { + const sequenceBytes = Buffer.from(sequence); + + for (let i = 0; i < sequenceBytes.length; i++) { + if (sequenceBytes[i] !== array[i]) { + return false; + } + } + return true; + } }); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 89fb089c9..21b5a83c7 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { TransactionIntent } from "../transactionIntent"; -import { AbiRegistry, ArgSerializer, CodeMetadata, EndpointDefinition, TypedValue } from "../smartcontracts"; +import { AbiRegistry, ArgSerializer, CodeMetadata, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; @@ -16,114 +16,118 @@ interface Config { } export class SmartContractTransactionIntentsFactory { - private config: Config; - private abiRegistry?: AbiRegistry; - - constructor(config: Config, abi?: AbiRegistry) { + private readonly config: Config; + private readonly abiRegistry?: AbiRegistry; + + constructor({ + config, + abi + }: { + config: Config; + abi?: AbiRegistry; + }) { this.config = config; this.abiRegistry = abi; } - createTransactionIntentForDeploy( + createTransactionIntentForDeploy(options: { sender: IAddress, bytecode: Uint8Array, gasLimit: BigNumber.Value, - args: any[], - isUpgradeable = true, - isReadable = true, - isPayable = false, - isPayableBySmartContract = true - ): TransactionIntent { + args?: any[], + isUpgradeable?: boolean, + isReadable?: boolean, + isPayable?: boolean, + isPayableBySmartContract?: boolean + }): TransactionIntent { + const isUpgradeable = options.isUpgradeable || true; + const isReadable = options.isReadable || true; + const isPayable = options.isPayable || false; + const isPayableBySmartContract = options.isPayableBySmartContract || true; + + const args = options.args || []; + const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [ - byteArrayToHex(bytecode), + byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString() ]; - let preparedArgs: string[]; - if (this.abiRegistry) { - preparedArgs = this.argsToStrings(args, this.abiRegistry.constructorDefinition) - } - else { - preparedArgs = this.argsToStrings(args) - } + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder( - this.config, - sender, - Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), - parts, - gasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), + dataParts: parts, + executionGasLimit: options.gasLimit + }).build(); } - createTransactionIntentForExecute( + createTransactionIntentForExecute(options: { sender: IAddress, contractAddress: IAddress, func: string, gasLimit: BigNumber.Value, - args: any[] = [] + args?: any[] + } ): TransactionIntent { - let parts: string[] = [func]; + const args = options.args || []; + let parts: string[] = [options.func]; - let preparedArgs: string[]; - if (this.abiRegistry) { - preparedArgs = this.argsToStrings(args, this.abiRegistry.getEndpoint(func)); - } - else { - preparedArgs = this.argsToStrings(args); - } + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder( - this.config, - sender, - contractAddress, - parts, - gasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.contractAddress, + dataParts: parts, + executionGasLimit: options.gasLimit + }).build(); } - createTransactionIntentForUpgrade( + createTransactionIntentForUpgrade(options: { sender: IAddress, contract: IAddress, bytecode: Uint8Array, gasLimit: BigNumber.Value, - args: any[], - isUpgradeable = true, - isReadable = true, - isPayable = false, - isPayableBySmartContract = true + args?: any[], + isUpgradeable?: boolean, + isReadable?: boolean, + isPayable?: boolean, + isPayableBySmartContract?: boolean + } ): TransactionIntent { + const isUpgradeable = options.isUpgradeable || true; + const isReadable = options.isReadable || true; + const isPayable = options.isPayable || false; + const isPayableBySmartContract = options.isPayableBySmartContract || true; + + const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [ "upgradeContract", - byteArrayToHex(bytecode), + byteArrayToHex(options.bytecode), metadata.toString() ]; - let preparedArgs: string[]; - if (this.abiRegistry) { - preparedArgs = this.argsToStrings(args, this.abiRegistry.constructorDefinition) - } - else { - preparedArgs = this.argsToStrings(args) - } + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder( - this.config, - sender, - contract, - parts, - gasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.contract, + dataParts: parts, + executionGasLimit: options.gasLimit + }).build(); } - private argsToStrings(args: any[], endpoint?: EndpointDefinition): string[] { + private argsToDataParts(args: any[], endpoint?: EndpointDefinition): string[] { if (endpoint) { const typedArgs = NativeSerializer.nativeToTypedValues(args, endpoint) return new ArgSerializer().valuesToStrings(typedArgs); @@ -138,7 +142,7 @@ export class SmartContractTransactionIntentsFactory { private areArgsOfTypedValue(args: any[]): boolean { for (const arg of args) { - if (!(arg instanceof TypedValue)) { + if (!(arg.belongsToTypesystem)) { return false; } } diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionIntentsFactories/transactionIntentBuilder.ts index ffa1f42bb..c294f6d2f 100644 --- a/src/transactionIntentsFactories/transactionIntentBuilder.ts +++ b/src/transactionIntentsFactories/transactionIntentBuilder.ts @@ -17,18 +17,25 @@ export class TransactionIntentBuilder { private executionGasLimit: BigNumber.Value; private value?: BigNumber.Value; - constructor(config: Config, sender: IAddress, receiver: IAddress, dataParts: string[], executionGasLimit: BigNumber.Value, value?: BigNumber.Value) { - this.config = config; - this.sender = sender; - this.receiver = receiver; - this.dataParts = dataParts; - this.executionGasLimit = executionGasLimit; - this.value = value; + constructor(options: { + config: Config, + sender: IAddress, + receiver: IAddress, + dataParts: string[], + executionGasLimit: BigNumber.Value, + value?: BigNumber.Value + }) { + this.config = options.config; + this.sender = options.sender; + this.receiver = options.receiver; + this.dataParts = options.dataParts; + this.executionGasLimit = options.executionGasLimit; + this.value = options.value; } private computeGasLimit(payload: ITransactionPayload, executionGasLimit: BigNumber.Value): BigNumber.Value { - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(new BigNumber(payload.length()))); - const gasLimit = new BigNumber(dataMovementGas).plus(new BigNumber(executionGasLimit)); + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(executionGasLimit); return gasLimit; } @@ -41,12 +48,12 @@ export class TransactionIntentBuilder { const data = this.buildTransactionPayload() const gasLimit = this.computeGasLimit(data, this.executionGasLimit); - return new TransactionIntent( - this.sender.bech32(), - this.receiver.bech32(), - gasLimit, - this.value !== undefined ? this.value : 0, - data.valueOf() - ) + return new TransactionIntent({ + sender: this.sender.bech32(), + receiver: this.receiver.bech32(), + gasLimit: gasLimit, + value: this.value || 0, + data: data.valueOf() + }) } } diff --git a/src/utils.codec.spec.ts b/src/utils.codec.spec.ts index 1ab1660ba..ba38f632c 100644 --- a/src/utils.codec.spec.ts +++ b/src/utils.codec.spec.ts @@ -1,5 +1,5 @@ import { assert } from "chai"; -import { isPaddedHex, numberToPaddedHex, zeroPadStringIfOddLength } from "./utils.codec"; +import { isPaddedHex, numberToPaddedHex, zeroPadStringIfOddLength, byteArrayToHex, utf8ToHex } from "./utils.codec"; describe("test codec utils", () => { it("should convert numberToPaddedHex", () => { @@ -21,4 +21,18 @@ describe("test codec utils", () => { assert.equal(zeroPadStringIfOddLength("1"), "01"); assert.equal(zeroPadStringIfOddLength("01"), "01"); }); + + it("should convert byteArrayToHex", () => { + const firstArray = new Uint8Array([0x05, 0x00]); + const secondArray = new Uint8Array([0x7]); + + assert.equal(byteArrayToHex(firstArray), "0500"); + assert.equal(byteArrayToHex(secondArray), "07"); + }); + + it("should convert utf8ToHex", () => { + assert.equal(utf8ToHex("stringandnumber7"), "737472696e67616e646e756d62657237"); + assert.equal(utf8ToHex("somestring"), "736f6d65737472696e67"); + assert.equal(utf8ToHex("aaa"), "616161"); + }); }); From d31bb919437dda7ac731bda71c26f714db8005b6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Sep 2023 10:35:41 +0300 Subject: [PATCH 008/275] started refactoring --- ...elegationTransactionIntentsFactory.spec.ts | 44 +++++++------- .../delegationTransactionIntentsFactory.ts | 59 ++++++++++--------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts index 1277d8031..b24d28be6 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts @@ -26,12 +26,12 @@ describe("test delegation intents factory", function () { const serviceFee = new BigNumber(10); const value = new BigNumber("1250000000000000000000"); - const intent = delegationFactory.createTransactionIntentForNewDelegationContract( - sender, - delagationCap, - serviceFee, - value - ); + const intent = delegationFactory.createTransactionIntentForNewDelegationContract({ + sender: sender, + totalDelegationCap: delagationCap, + serviceFee: serviceFee, + value: value + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, DELEGATION_MANAGER_SC_ADDRESS); @@ -52,12 +52,12 @@ describe("test delegation intents factory", function () { const signedMessage = new SignableMessage(); signedMessage.applySignature(Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex")); - const intent = delegationFactory.createTransactionIntentForAddingNodes( - sender, - delegationContract, - [publicKey], - [signedMessage.getSignature()] - ); + const intent = delegationFactory.createTransactionIntentForAddingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey], + signedMessages: [signedMessage.getSignature()] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -79,11 +79,11 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForRemovingNodes( - sender, - delegationContract, - [publicKey] - ); + const intent = delegationFactory.createTransactionIntentForRemovingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -105,11 +105,11 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForStakingNodes( - sender, - delegationContract, - [publicKey] - ); + const intent = delegationFactory.createTransactionIntentForStakingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index 9da652d4a..c231a2524 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -25,111 +25,114 @@ interface ValidatorPublicKey { } export class DelegationTransactionIntentsFactory { - private config: Config; + private readonly config: Config; constructor(config: Config) { this.config = config; } - createTransactionIntentForNewDelegationContract( + createTransactionIntentForNewDelegationContract(options: { sender: IAddress, totalDelegationCap: BigNumber.Value, serviceFee: BigNumber.Value, value: BigNumber.Value - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "createNewDelegationContract", - numberToPaddedHex(totalDelegationCap.toString()), - numberToPaddedHex(serviceFee.toString()) + numberToPaddedHex(options.totalDelegationCap.toString()), + numberToPaddedHex(options.serviceFee.toString()) ]; - const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)); + const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); return new TransactionIntentBuilder( this.config, - sender, + options.sender, Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), dataParts, executionGasLimit, - value + options.value ).build(); } - createTransactionIntentForAddingNodes( + createTransactionIntentForAddingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[], signedMessages: Uint8Array[] + } ): TransactionIntent { - if (publicKeys.length !== signedMessages.length) { + if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; let dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts = dataParts.concat(publicKeys[i].hex()); - dataParts = dataParts.concat(byteArrayToHex(signedMessages[i])); + dataParts = dataParts.concat(options.publicKeys[i].hex()); + dataParts = dataParts.concat(byteArrayToHex(options.signedMessages[i])); } return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, this.computeExecutionGasLimitForNodesManagement(numNodes) ).build(); } private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { - const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(new BigNumber(numNodes)); + const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } - createTransactionIntentForRemovingNodes( + createTransactionIntentForRemovingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] + } ): TransactionIntent { let dataParts = ["removeNodes"]; - for (const key of publicKeys) { + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, this.computeExecutionGasLimitForNodesManagement(numNodes) ).build(); } - createTransactionIntentForStakingNodes( + createTransactionIntentForStakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] + } ): TransactionIntent { let dataParts = ["stakeNodes"]; - for (const key of publicKeys) { + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; const executionGasLimit = new BigNumber(numNodes).multipliedBy( - new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( - new BigNumber(this.config.gasLimitStake) + this.config.additionalGasLimitPerValidatorNode).plus( + this.config.gasLimitStake ).plus(this.config.gasLimitDelegationOperations); return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, executionGasLimit ).build(); From 08dd376001cdbbd533d310ba4b0920f8dd5426f7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Sep 2023 10:55:46 +0300 Subject: [PATCH 009/275] small fixes for tests --- ...artContractTransactionIntentsFactory.spec.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index c2a8513c6..75d65332f 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -73,12 +73,10 @@ describe("test smart contract intents factory", function () { assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, CONTRACT_DEPLOY_ADDRESS); assert.isDefined(deployIntent.data); - expect(deployIntent.data?.length).to.be.greaterThan(0); + expect(deployIntent.data!.length).to.be.greaterThan(0); - if (deployIntent.data) { - const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; - assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); - } + const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data!.length; + assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); assert.equal(deployIntent.value, 0); assert.deepEqual(deployIntent, abiDeployIntent); @@ -142,13 +140,10 @@ describe("test smart contract intents factory", function () { assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.isDefined(deployIntent.data); + assert(checkIfByteArrayStartsWith(deployIntent.data!, "upgradeContract@")); - if (deployIntent.data) { - assert(checkIfByteArrayStartsWith(deployIntent.data, "upgradeContract@")); - - const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data.length; - assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); - } + const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data!.length; + assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); assert.equal(deployIntent.value, 0); assert.deepEqual(deployIntent, abiDeployIntent); From 23ad3be1b647e3fb6619128334cc2119e9e1b9bd Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Sep 2023 12:46:17 +0300 Subject: [PATCH 010/275] refactoring --- ...elegationTransactionIntentsFactory.spec.ts | 166 +++++++----------- .../delegationTransactionIntentsFactory.ts | 133 +++++++------- 2 files changed, 127 insertions(+), 172 deletions(-) diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts index b24d28be6..1036e9eeb 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts @@ -36,10 +36,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, DELEGATION_MANAGER_SC_ADDRESS); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "createNewDelegationContract@010f0cf064dd59200000@0a"); - + assert.deepEqual(intent.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); assert.equal(intent.gasLimit.valueOf(), 60126500); assert.equal(intent.value, value); }); @@ -62,10 +59,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216"); - + assert.deepEqual(intent.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); assert.equal(intent.value, 0); }); @@ -88,10 +82,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "removeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); - + assert.deepEqual(intent.data, Buffer.from("removeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); assert.equal(intent.value, 0); }); @@ -114,10 +105,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "stakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); - + assert.deepEqual(intent.data, Buffer.from("stakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); assert.equal(intent.value, 0); }); @@ -131,19 +119,16 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnbondingNodes( - sender, - delegationContract, - [publicKey] - ); + const intent = delegationFactory.createTransactionIntentForUnbondingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "unBondNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); - + assert.deepEqual(intent.data, Buffer.from("unBondNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); assert.equal(intent.value, 0); assert.equal(intent.gasLimit.valueOf(), 12143000); }); @@ -158,19 +143,16 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnstakingNodes( - sender, - delegationContract, - [publicKey] - ); + const intent = delegationFactory.createTransactionIntentForUnstakingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "unStakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); - + assert.deepEqual(intent.data, Buffer.from("unStakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); assert.equal(intent.value, 0); assert.equal(intent.gasLimit.valueOf(), 12144500); }); @@ -185,19 +167,16 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnjailingNodes( - sender, - delegationContract, - [publicKey] - ); + const intent = delegationFactory.createTransactionIntentForUnjailingNodes({ + sender: sender, + delegationContract: delegationContract, + publicKeys: [publicKey] + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "unJailNodes@6e6f746176616c6964626c736b6579686578656e636f646564"); - + assert.deepEqual(intent.data, Buffer.from("unJailNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); assert.equal(intent.value, 0); }); @@ -206,19 +185,16 @@ describe("test delegation intents factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const intent = delegationFactory.createTransactionIntentForChangingServiceFee( - sender, - delegationContract, - serviceFee - ); + const intent = delegationFactory.createTransactionIntentForChangingServiceFee({ + sender: sender, + delegationContract: delegationContract, + serviceFee: serviceFee + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "changeServiceFee@0a"); - + assert.deepEqual(intent.data, Buffer.from("changeServiceFee@0a")); assert.equal(intent.value, 0); }); @@ -227,19 +203,16 @@ describe("test delegation intents factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const intent = delegationFactory.createTransactionIntentForModifyingDelegationCap( - sender, - delegationContract, - delegationCap - ); + const intent = delegationFactory.createTransactionIntentForModifyingDelegationCap({ + sender: sender, + delegationContract: delegationContract, + delegationCap: delegationCap + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "modifyTotalDelegationCap@010f0cf064dd59200000"); - + assert.deepEqual(intent.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); assert.equal(intent.value, 0); }); @@ -247,18 +220,15 @@ describe("test delegation intents factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingAutomaticActivation( - sender, - delegationContract - ); + const intent = delegationFactory.createTransactionIntentForSettingAutomaticActivation({ + sender: sender, + delegationContract: delegationContract + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "setAutomaticActivation@74727565"); - + assert.deepEqual(intent.data, Buffer.from("setAutomaticActivation@74727565")); assert.equal(intent.value, 0); }); @@ -266,18 +236,15 @@ describe("test delegation intents factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForUnsettingAutomaticActivation( - sender, - delegationContract - ); + const intent = delegationFactory.createTransactionIntentForUnsettingAutomaticActivation({ + sender: sender, + delegationContract: delegationContract + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "setAutomaticActivation@66616c7365"); - + assert.deepEqual(intent.data, Buffer.from("setAutomaticActivation@66616c7365")); assert.equal(intent.value, 0); }); @@ -285,18 +252,15 @@ describe("test delegation intents factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingCapCheckOnRedelegateRewards( - sender, - delegationContract - ); + const intent = delegationFactory.createTransactionIntentForSettingCapCheckOnRedelegateRewards({ + sender: sender, + delegationContract: delegationContract + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "setCheckCapOnReDelegateRewards@74727565"); - + assert.deepEqual(intent.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); assert.equal(intent.value, 0); }); @@ -304,18 +268,15 @@ describe("test delegation intents factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForUnsettingCapCheckOnRedelegateRewards( - sender, - delegationContract - ); + const intent = delegationFactory.createTransactionIntentForUnsettingCapCheckOnRedelegateRewards({ + sender: sender, + delegationContract: delegationContract + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "setCheckCapOnReDelegateRewards@66616c7365"); - + assert.deepEqual(intent.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); assert.equal(intent.value, 0); }); @@ -323,21 +284,18 @@ describe("test delegation intents factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingMetadata( - sender, - delegationContract, - "name", - "website", - "identifier" - ); + const intent = delegationFactory.createTransactionIntentForSettingMetadata({ + sender: sender, + delegationContract: delegationContract, + name: "name", + website: "website", + identifier: "identifier" + }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - - let decoder = new TextDecoder(); - assert.equal(decoder.decode(intent.data), "setMetaData@6e616d65@77656273697465@6964656e746966696572"); - + assert.deepEqual(intent.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); assert.equal(intent.value, 0); }); }); diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index c231a2524..1077426c0 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -60,8 +60,7 @@ export class DelegationTransactionIntentsFactory { delegationContract: IAddress, publicKeys: ValidatorPublicKey[], signedMessages: Uint8Array[] - } - ): TransactionIntent { + }): TransactionIntent { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } @@ -92,8 +91,7 @@ export class DelegationTransactionIntentsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] - } - ): TransactionIntent { + }): TransactionIntent { let dataParts = ["removeNodes"]; for (const key of options.publicKeys) { @@ -115,8 +113,7 @@ export class DelegationTransactionIntentsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] - } - ): TransactionIntent { + }): TransactionIntent { let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { @@ -138,122 +135,122 @@ export class DelegationTransactionIntentsFactory { ).build(); } - createTransactionIntentForUnbondingNodes( + createTransactionIntentForUnbondingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] - ): TransactionIntent { + }): TransactionIntent { let dataParts = ["unBondNodes"]; - for (const key of publicKeys) { + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; const executionGasLimit = new BigNumber(numNodes).multipliedBy( - new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( - new BigNumber(this.config.gasLimitUnbond) + this.config.additionalGasLimitPerValidatorNode).plus( + this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, executionGasLimit ).build(); } - createTransactionIntentForUnstakingNodes( + createTransactionIntentForUnstakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] - ): TransactionIntent { + }): TransactionIntent { let dataParts = ["unStakeNodes"]; - for (const key of publicKeys) { + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; const executionGasLimit = new BigNumber(numNodes).multipliedBy( - new BigNumber(this.config.additionalGasLimitPerValidatorNode)).plus( - new BigNumber(this.config.gasLimitUnstake) + this.config.additionalGasLimitPerValidatorNode).plus( + this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, executionGasLimit ).build(); } - createTransactionIntentForUnjailingNodes( + createTransactionIntentForUnjailingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: ValidatorPublicKey[] - ): TransactionIntent { + }): TransactionIntent { let dataParts = ["unJailNodes"]; - for (const key of publicKeys) { + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - const numNodes = publicKeys.length; + const numNodes = options.publicKeys.length; return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, this.computeExecutionGasLimitForNodesManagement(numNodes) ).build(); } - createTransactionIntentForChangingServiceFee( + createTransactionIntentForChangingServiceFee(options: { sender: IAddress, delegationContract: IAddress, serviceFee: BigNumber.Value - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "changeServiceFee", - numberToPaddedHex(serviceFee) + numberToPaddedHex(options.serviceFee) ]; return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForModifyingDelegationCap( + createTransactionIntentForModifyingDelegationCap(options: { sender: IAddress, delegationContract: IAddress, delegationCap: BigNumber.Value - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "modifyTotalDelegationCap", - numberToPaddedHex(delegationCap) + numberToPaddedHex(options.delegationCap) ]; return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForSettingAutomaticActivation( + createTransactionIntentForSettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "setAutomaticActivation", utf8ToHex("true") @@ -261,17 +258,17 @@ export class DelegationTransactionIntentsFactory { return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForUnsettingAutomaticActivation( + createTransactionIntentForUnsettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "setAutomaticActivation", utf8ToHex("false") @@ -279,17 +276,17 @@ export class DelegationTransactionIntentsFactory { return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForSettingCapCheckOnRedelegateRewards( + createTransactionIntentForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") @@ -297,17 +294,17 @@ export class DelegationTransactionIntentsFactory { return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForUnsettingCapCheckOnRedelegateRewards( + createTransactionIntentForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") @@ -315,33 +312,33 @@ export class DelegationTransactionIntentsFactory { return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } - createTransactionIntentForSettingMetadata( + createTransactionIntentForSettingMetadata(options: { sender: IAddress, delegationContract: IAddress, name: string, website: string, identifier: string - ): TransactionIntent { + }): TransactionIntent { const dataParts = [ "setMetaData", - utf8ToHex(name), - utf8ToHex(website), - utf8ToHex(identifier) + utf8ToHex(options.name), + utf8ToHex(options.website), + utf8ToHex(options.identifier) ]; return new TransactionIntentBuilder( this.config, - sender, - delegationContract, + options.sender, + options.delegationContract, dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(new BigNumber(this.config.additionalGasLimitForDelegationOperations)) + new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) ).build(); } } From 28d6a07466fd3a92d9560e183e3d36cd1aeec42f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Sep 2023 14:20:58 +0300 Subject: [PATCH 011/275] fixes after merge --- .../delegationTransactionIntentsFactory.ts | 198 +++++++++--------- ...tContractTransactionIntentsFactory.spec.ts | 14 +- 2 files changed, 101 insertions(+), 111 deletions(-) diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index 1077426c0..57b364443 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -45,14 +45,14 @@ export class DelegationTransactionIntentsFactory { const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - return new TransactionIntentBuilder( - this.config, - options.sender, - Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), - dataParts, - executionGasLimit, - options.value - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), + dataParts: dataParts, + executionGasLimit: executionGasLimit, + value: options.value + }).build(); } createTransactionIntentForAddingNodes(options: { @@ -73,13 +73,13 @@ export class DelegationTransactionIntentsFactory { dataParts = dataParts.concat(byteArrayToHex(options.signedMessages[i])); } - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - this.computeExecutionGasLimitForNodesManagement(numNodes) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + }).build(); } private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { @@ -100,13 +100,13 @@ export class DelegationTransactionIntentsFactory { const numNodes = options.publicKeys.length; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - this.computeExecutionGasLimitForNodesManagement(numNodes) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + }).build(); } createTransactionIntentForStakingNodes(options: { @@ -126,13 +126,13 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitStake ).plus(this.config.gasLimitDelegationOperations); - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - executionGasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: executionGasLimit + }).build(); } createTransactionIntentForUnbondingNodes(options: { @@ -152,13 +152,13 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - executionGasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: executionGasLimit + }).build(); } createTransactionIntentForUnstakingNodes(options: { @@ -178,13 +178,13 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - executionGasLimit - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: executionGasLimit + }).build(); } createTransactionIntentForUnjailingNodes(options: { @@ -200,13 +200,13 @@ export class DelegationTransactionIntentsFactory { const numNodes = options.publicKeys.length; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - this.computeExecutionGasLimitForNodesManagement(numNodes) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + }).build(); } createTransactionIntentForChangingServiceFee(options: { @@ -219,13 +219,13 @@ export class DelegationTransactionIntentsFactory { numberToPaddedHex(options.serviceFee) ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForModifyingDelegationCap(options: { @@ -238,13 +238,13 @@ export class DelegationTransactionIntentsFactory { numberToPaddedHex(options.delegationCap) ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForSettingAutomaticActivation(options: { @@ -256,13 +256,13 @@ export class DelegationTransactionIntentsFactory { utf8ToHex("true") ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForUnsettingAutomaticActivation(options: { @@ -274,13 +274,13 @@ export class DelegationTransactionIntentsFactory { utf8ToHex("false") ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForSettingCapCheckOnRedelegateRewards(options: { @@ -292,13 +292,13 @@ export class DelegationTransactionIntentsFactory { utf8ToHex("true") ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForUnsettingCapCheckOnRedelegateRewards(options: { @@ -310,13 +310,13 @@ export class DelegationTransactionIntentsFactory { utf8ToHex("false") ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } createTransactionIntentForSettingMetadata(options: { @@ -333,12 +333,12 @@ export class DelegationTransactionIntentsFactory { utf8ToHex(options.identifier) ]; - return new TransactionIntentBuilder( - this.config, - options.sender, - options.delegationContract, - dataParts, - new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) - ).build(); + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + }).build(); } } diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index 75d65332f..a6f8e7a31 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -129,6 +129,7 @@ describe("test smart contract intents factory", function () { gasLimit: gasLimit, args: args }); + const abiDeployIntent = abiAwareFactory.createTransactionIntentForUpgrade({ sender: sender, contract: contract, @@ -140,7 +141,7 @@ describe("test smart contract intents factory", function () { assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.isDefined(deployIntent.data); - assert(checkIfByteArrayStartsWith(deployIntent.data!, "upgradeContract@")); + assert.isTrue(Buffer.from(deployIntent.data!).toString().startsWith("upgradeContract@")); const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data!.length; assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); @@ -148,15 +149,4 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - - function checkIfByteArrayStartsWith(array: Uint8Array, sequence: string) { - const sequenceBytes = Buffer.from(sequence); - - for (let i = 0; i < sequenceBytes.length; i++) { - if (sequenceBytes[i] !== array[i]) { - return false; - } - } - return true; - } }); From 5a0813c4eb0a9f21859937b6f1ed6165ed8b33ee Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Sep 2023 15:03:49 +0300 Subject: [PATCH 012/275] add trailing semicolon --- src/constants.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index eb3ea8c8c..f6bc96cef 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,6 +11,5 @@ export const MULTI_ESDTNFT_TRANSFER_FUNCTION_NAME = "MultiESDTNFTTransfer"; export const ESDT_TRANSFER_VALUE = "0"; export const ARGUMENTS_SEPARATOR = "@"; export const VM_TYPE_WASM_VM = new Uint8Array([0x05, 0x00]); -export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu" -export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" - +export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu"; +export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6"; From 7ea77f9b44f7c739983f8f1961c9f2aecd409f34 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 11 Sep 2023 13:15:37 +0300 Subject: [PATCH 013/275] started token operations transaction intents factory --- src/constants.ts | 1 + src/tokenOperations/codec.ts | 15 +- ...anagementTransactionIntentsFactory.spec.ts | 0 ...okenManagementTransactionIntentsFactory.ts | 289 ++++++++++++++++++ src/utils.codec.ts | 16 + 5 files changed, 307 insertions(+), 14 deletions(-) create mode 100644 src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts create mode 100644 src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts diff --git a/src/constants.ts b/src/constants.ts index f6bc96cef..266b902ce 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,3 +13,4 @@ export const ARGUMENTS_SEPARATOR = "@"; export const VM_TYPE_WASM_VM = new Uint8Array([0x05, 0x00]); export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu"; export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6"; +export const ESDT_CONTRACT_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; diff --git a/src/tokenOperations/codec.ts b/src/tokenOperations/codec.ts index 8b9bc5988..512e5d162 100644 --- a/src/tokenOperations/codec.ts +++ b/src/tokenOperations/codec.ts @@ -24,22 +24,9 @@ export function bigIntToBuffer(value: BigNumber.Value): Buffer { return contractsCodecUtils.bigIntToBuffer(value); } -export function bigIntToHex(value: BigNumber.Value): string { - if (value == 0) { - return ""; - } - - return contractsCodecUtils.getHexMagnitudeOfBigInt(value); -} - -export { utf8ToHex } from "../utils.codec"; +export { utf8ToHex, bigIntToHex, addressToHex } from "../utils.codec"; export function bufferToHex(value: Buffer) { const hex = value.toString("hex"); return codecUtils.zeroPadStringIfOddLength(hex); } - -export function addressToHex(address: IAddress): string { - const buffer = Address.fromBech32(address.toString()).pubkey(); - return buffer.toString("hex"); -} diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts new file mode 100644 index 000000000..625926ba1 --- /dev/null +++ b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts @@ -0,0 +1,289 @@ +import BigNumber from "bignumber.js"; +import { TransactionIntent } from "../transactionIntent"; +import { TransactionIntentBuilder } from "./transactionIntentBuilder"; +import { IAddress } from "../interface"; +import { utf8ToHex, bigIntToHex, addressToHex } from "../utils.codec"; +import { ESDT_CONTRACT_ADDRESS } from "../constants"; +import { Address } from "../address"; +import { Logger } from "../logger"; + +interface Config { + chainID: string + minGasLimit: BigNumber.Value + gasLimitPerByte: BigNumber.Value + gasLimitIssue: BigNumber.Value + gasLimitToggleBurnRoleGlobally: BigNumber.Value + gasLimitESDTLocalMint: BigNumber.Value + gasLimitESDTLocalBurn: BigNumber.Value + gasLimitSetSpecialRole: BigNumber.Value + gasLimitPausing: BigNumber.Value + gasLimitFreezing: BigNumber.Value + gasLimitWiping: BigNumber.Value + gasLimitESDTNFTCreate: BigNumber.Value + gasLimitESDTNFTUpdateAttributes: BigNumber.Value + gasLimitESDTNFTAddQuantity: BigNumber.Value + gasLimitESDTNFTBurn: BigNumber.Value + gasLimitStorePerByte: BigNumber.Value + issueCost: BigNumber.Value + esdtContractAddress: IAddress +} + +type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; + +export class TokenManagementTransactionIntentsFactory { + private readonly config: Config; + private readonly trueAsHex: string; + + constructor(config: Config) { + this.config = config; + this.trueAsHex = utf8ToHex("true"); + } + + createTransactionIntentForIssuingFungible(options: { + sender: IAddress, + tokenName: string, + tokenTicker: string, + initialSupply: BigNumber.Value, + numDecimals: BigNumber.Value, + canFreeze: boolean, + canWipe: boolean, + canPause: boolean, + canChangeOwner: boolean, + canUpgrade: boolean, + canAddSpecialRoles: boolean + }): TransactionIntent { + this.notifyAboutUnsettingBurnRoleGlobally(); + + const dataParts = [ + "issue", + utf8ToHex(options.tokenName), + utf8ToHex(options.tokenTicker), + bigIntToHex(options.initialSupply), + bigIntToHex(options.numDecimals), + ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), + ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), + ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), + ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), + ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), + ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitIssue, + value: this.config.issueCost + }).build(); + } + + private notifyAboutUnsettingBurnRoleGlobally() { + Logger.info(` +========== +IMPORTANT! +========== +You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). +Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); + } + + createTransactionIntentForIssuingSemiFungible(options: { + sender: IAddress; + tokenName: string; + tokenTicker: string; + canFreeze: boolean; + canWipe: boolean; + canPause: boolean; + canTransferNFTCreateRole: boolean; + canChangeOwner: boolean; + canUpgrade: boolean; + canAddSpecialRoles: boolean; + }): TransactionIntent { + this.notifyAboutUnsettingBurnRoleGlobally(); + + const dataParts = [ + "issueSemiFungible", + utf8ToHex(options.tokenName), + utf8ToHex(options.tokenTicker), + ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), + ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), + ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), + ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), + ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), + ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), + ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitIssue, + value: this.config.issueCost + }).build(); + } + + createTransactionIntentForIssuingNonFungible(options: { + sender: IAddress; + tokenName: string; + tokenTicker: string; + canFreeze: boolean; + canWipe: boolean; + canPause: boolean; + canTransferNFTCreateRole: boolean; + canChangeOwner: boolean; + canUpgrade: boolean; + canAddSpecialRoles: boolean; + }): TransactionIntent { + this.notifyAboutUnsettingBurnRoleGlobally(); + + const dataParts = [ + "issueNonFungible", + utf8ToHex(options.tokenName), + utf8ToHex(options.tokenTicker), + ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), + ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), + ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), + ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), + ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), + ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), + ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitIssue, + value: this.config.issueCost + }).build(); + } + + createTransactionIntentForRegisteringMetaEsdt(options: { + sender: IAddress; + tokenName: string; + tokenTicker: string; + numDecimals: BigNumber.Value, + canFreeze: boolean; + canWipe: boolean; + canPause: boolean; + canTransferNFTCreateRole: boolean; + canChangeOwner: boolean; + canUpgrade: boolean; + canAddSpecialRoles: boolean; + }): TransactionIntent { + this.notifyAboutUnsettingBurnRoleGlobally(); + + const dataParts = [ + "registerMetaESDT", + utf8ToHex(options.tokenName), + utf8ToHex(options.tokenTicker), + bigIntToHex(options.numDecimals), + ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), + ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), + ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), + ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), + ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), + ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), + ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitIssue, + value: this.config.issueCost + }).build(); + } + + createTransactionIntentForRegisteringAndSettingRoles(options: { + sender: IAddress; + tokenName: string; + tokenTicker: string; + tokenType: RegisterAndSetAllRolesTokenType; + numDecimals: BigNumber.Value; + }): TransactionIntent { + this.notifyAboutUnsettingBurnRoleGlobally(); + + const dataParts = [ + "registerAndSetAllRoles", + utf8ToHex(options.tokenName), + utf8ToHex(options.tokenTicker), + utf8ToHex(options.tokenType), + bigIntToHex(options.numDecimals) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitIssue, + value: this.config.issueCost + }).build(); + } + + createTransactionIntentForSettingBurnRoleGlobally(options: { + sender: IAddress, + tokenIdentifier: string + }): TransactionIntent { + const dataParts = [ + "setBurnRoleGlobally", + utf8ToHex(options.tokenIdentifier) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally + }).build(); + } + + createTransactionIntentForUnsettingBurnRoleGlobally(options: { + sender: IAddress, + tokenIdentifier: string + }): TransactionIntent { + const dataParts = [ + "unsetBurnRoleGlobally", + utf8ToHex(options.tokenIdentifier) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally + }).build(); + } + + createTransactionIntentForSettingSpecialRoleOnFungibleToken(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + addRoleLocalMint: boolean; + addRoleLocalBurn: boolean; + }): TransactionIntent { + const dataParts = [ + "setSpecialRole", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user), + ...(options.addRoleLocalMint ? [utf8ToHex("ESDTRoleLocalMint")] : []), + ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitSetSpecialRole + }).build(); + } +} diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 2d79785b5..5be00dd26 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -1,4 +1,7 @@ import BigNumber from "bignumber.js"; +import * as contractsCodecUtils from "./smartcontracts/codec/utils"; +import { Address } from "./address"; +import { IAddress } from "./interface"; export function numberToPaddedHex(value: BigNumber.Value) { let hex = new BigNumber(value).toString(16); @@ -29,3 +32,16 @@ export function utf8ToHex(value: string) { export function byteArrayToHex(byteArray: Uint8Array): string { return Buffer.from(byteArray).toString("hex"); } + +export function bigIntToHex(value: BigNumber.Value): string { + if (value == 0) { + return ""; + } + + return contractsCodecUtils.getHexMagnitudeOfBigInt(value); +} + +export function addressToHex(address: IAddress): string { + const buffer = Address.fromBech32(address.toString()).pubkey(); + return buffer.toString("hex"); +} From 41604d04fb19fd84838172bb094a7801dea51b23 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 11 Sep 2023 15:10:06 +0300 Subject: [PATCH 014/275] fixes after review --- src/constants.ts | 1 + ...elegationTransactionIntentsFactory.spec.ts | 79 ++++++++----------- .../delegationTransactionIntentsFactory.ts | 45 ++++++----- ...tContractTransactionIntentsFactory.spec.ts | 22 ++---- .../transactionIntentsFactoryConfig.ts | 63 +++++++++++++++ 5 files changed, 128 insertions(+), 82 deletions(-) create mode 100644 src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts diff --git a/src/constants.ts b/src/constants.ts index f6bc96cef..88285bbc2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,3 +13,4 @@ export const ARGUMENTS_SEPARATOR = "@"; export const VM_TYPE_WASM_VM = new Uint8Array([0x05, 0x00]); export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu"; export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6"; +export const DEFAULT_HRP = "erd"; diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts index 1036e9eeb..34bd7df41 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts @@ -4,26 +4,16 @@ import { DelegationTransactionIntentsFactory } from "./delegationTransactionInte import { assert } from "chai"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { ValidatorPublicKey } from "@multiversx/sdk-wallet-next"; -import { SignableMessage } from "../signableMessage"; +import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; describe("test delegation intents factory", function () { - const delegationFactory = new DelegationTransactionIntentsFactory({ - chainID: "D", - minGasLimit: 50000, - gasLimitPerByte: 1500, - gasLimitStake: 5000000, - gasLimitUnstake: 5000000, - gasLimitUnbond: 5000000, - gasLimitCreateDelegationContract: 50000000, - gasLimitDelegationOperations: 1000000, - additionalGasLimitPerValidatorNode: 6000000, - additionalGasLimitForDelegationOperations: 10000000 - }); + const config = new TransactionIntentsFactoryConfig("D"); + const delegationFactory = new DelegationTransactionIntentsFactory(config); - it("should build intent for new delegation contract", async function () { + it("should create intent for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - const delagationCap = new BigNumber("5000000000000000000000"); - const serviceFee = new BigNumber(10); + const delagationCap = "5000000000000000000000"; + const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); const intent = delegationFactory.createTransactionIntentForNewDelegationContract({ @@ -41,19 +31,20 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, value); }); - it("should build intent for adding nodes", async function () { + it("should create intent for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); - const signedMessage = new SignableMessage(); - signedMessage.applySignature(Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex")); + const mockMessage = { + getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") + } const intent = delegationFactory.createTransactionIntentForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], - signedMessages: [signedMessage.getSignature()] + signedMessages: [mockMessage.getSignature()] }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); @@ -63,13 +54,13 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for removing nodes", async function () { + it("should create intent for removing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = { hex(): string { - return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + return Buffer.from("abba").toString("hex"); } }; @@ -82,17 +73,17 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("removeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); + assert.deepEqual(intent.data, Buffer.from("removeNodes@61626261")); assert.equal(intent.value, 0); }); - it("should build intent for staking nodes", async function () { + it("should create intent for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = { hex(): string { - return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + return Buffer.from("abba").toString("hex"); } }; @@ -105,17 +96,17 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("stakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); + assert.deepEqual(intent.data, Buffer.from("stakeNodes@61626261")); assert.equal(intent.value, 0); }); - it("should build intent for unbonding nodes", async function () { + it("should create intent for unbonding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = { hex(): string { - return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + return Buffer.from("abba").toString("hex"); } }; @@ -128,18 +119,18 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unBondNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); + assert.deepEqual(intent.data, Buffer.from("unBondNodes@61626261")); assert.equal(intent.value, 0); - assert.equal(intent.gasLimit.valueOf(), 12143000); + assert.equal(intent.gasLimit.valueOf(), 12080000); }); - it("should build intent for unstaking nodes", async function () { + it("should create intent for unstaking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = { hex(): string { - return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + return Buffer.from("abba").toString("hex"); } }; @@ -152,18 +143,18 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unStakeNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); + assert.deepEqual(intent.data, Buffer.from("unStakeNodes@61626261")); assert.equal(intent.value, 0); - assert.equal(intent.gasLimit.valueOf(), 12144500); + assert.equal(intent.gasLimit.valueOf(), 12081500); }); - it("should build intent for unjailing nodes", async function () { + it("should create intent for unjailing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = { hex(): string { - return Buffer.from("notavalidblskeyhexencoded").toString("hex"); + return Buffer.from("abba").toString("hex"); } }; @@ -176,11 +167,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unJailNodes@6e6f746176616c6964626c736b6579686578656e636f646564")); + assert.deepEqual(intent.data, Buffer.from("unJailNodes@61626261")); assert.equal(intent.value, 0); }); - it("should build intent for changing service fee", async function () { + it("should create intent for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); @@ -198,7 +189,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for changing delegation cap", async function () { + it("should create intent for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); @@ -216,7 +207,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for setting automatic activation", async function () { + it("should create intent for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -232,7 +223,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for unsetting automatic activation", async function () { + it("should create intent for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -248,7 +239,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for setting cap check on redelegate rewards", async function () { + it("should create intent for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -264,7 +255,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for unsetting cap check on redelegate rewards", async function () { + it("should create intent for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -280,7 +271,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should build intent for setting metadata", async function () { + it("should create intent for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index 57b364443..ad1a92c82 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -20,7 +20,7 @@ interface Config { additionalGasLimitForDelegationOperations: BigNumber.Value; } -interface ValidatorPublicKey { +interface IValidatorPublicKey { hex(): string; } @@ -58,7 +58,7 @@ export class DelegationTransactionIntentsFactory { createTransactionIntentForAddingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[], + publicKeys: IValidatorPublicKey[], signedMessages: Uint8Array[] }): TransactionIntent { if (options.publicKeys.length !== options.signedMessages.length) { @@ -67,10 +67,9 @@ export class DelegationTransactionIntentsFactory { const numNodes = options.publicKeys.length; - let dataParts = ["addNodes"]; + const dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts = dataParts.concat(options.publicKeys[i].hex()); - dataParts = dataParts.concat(byteArrayToHex(options.signedMessages[i])); + dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } return new TransactionIntentBuilder({ @@ -82,20 +81,15 @@ export class DelegationTransactionIntentsFactory { }).build(); } - private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { - const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); - return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); - } - createTransactionIntentForRemovingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[] + publicKeys: IValidatorPublicKey[] }): TransactionIntent { - let dataParts = ["removeNodes"]; + const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + dataParts.push(key.hex()); } const numNodes = options.publicKeys.length; @@ -112,7 +106,7 @@ export class DelegationTransactionIntentsFactory { createTransactionIntentForStakingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[] + publicKeys: IValidatorPublicKey[] }): TransactionIntent { let dataParts = ["stakeNodes"]; @@ -121,10 +115,10 @@ export class DelegationTransactionIntentsFactory { } const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes).multipliedBy( - this.config.additionalGasLimitPerValidatorNode).plus( - this.config.gasLimitStake - ).plus(this.config.gasLimitDelegationOperations); + const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); + const executionGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( + this.config.gasLimitDelegationOperations + ); return new TransactionIntentBuilder({ config: this.config, @@ -138,7 +132,7 @@ export class DelegationTransactionIntentsFactory { createTransactionIntentForUnbondingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[] + publicKeys: IValidatorPublicKey[] }): TransactionIntent { let dataParts = ["unBondNodes"]; @@ -164,7 +158,7 @@ export class DelegationTransactionIntentsFactory { createTransactionIntentForUnstakingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[] + publicKeys: IValidatorPublicKey[] }): TransactionIntent { let dataParts = ["unStakeNodes"]; @@ -190,12 +184,12 @@ export class DelegationTransactionIntentsFactory { createTransactionIntentForUnjailingNodes(options: { sender: IAddress, delegationContract: IAddress, - publicKeys: ValidatorPublicKey[] + publicKeys: IValidatorPublicKey[] }): TransactionIntent { - let dataParts = ["unJailNodes"]; + const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + dataParts.push(key.hex()); } const numNodes = options.publicKeys.length; @@ -341,4 +335,9 @@ export class DelegationTransactionIntentsFactory { executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) }).build(); } + + private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { + const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); + return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); + } } diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index a6f8e7a31..9fdfb020b 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -7,8 +7,10 @@ import { U32Value } from "../smartcontracts"; import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; +import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; describe("test smart contract intents factory", function () { + const config = new TransactionIntentsFactoryConfig("D"); let factory: SmartContractTransactionIntentsFactory; let abiAwareFactory: SmartContractTransactionIntentsFactory; let adderByteCode: Code; @@ -16,24 +18,14 @@ describe("test smart contract intents factory", function () { before(async function () { factory = new SmartContractTransactionIntentsFactory({ - config: - { - chainID: "D", - minGasLimit: 50000, - gasLimitPerByte: 1500 - } + config: config }); adderByteCode = await loadContractCode("src/testdata/adder.wasm"); abiRegistry = await loadAbiRegistry("src/testdata/adder.abi.json"); abiAwareFactory = new SmartContractTransactionIntentsFactory({ - config: - { - chainID: "D", - minGasLimit: 50000, - gasLimitPerByte: 1500 - }, + config: config, abi: abiRegistry }, ); @@ -52,7 +44,7 @@ describe("test smart contract intents factory", function () { }), Err, "Can't convert args to TypedValues"); }); - it("should build intent for deploy", async function () { + it("should create intent for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [new U32Value(0)]; @@ -82,7 +74,7 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should build intent for execute", async function () { + it("should create intent for execute", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -116,7 +108,7 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should build intent for upgrade", async function () { + it("should create intent for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000; diff --git a/src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts b/src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts new file mode 100644 index 000000000..d8d1c9c94 --- /dev/null +++ b/src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts @@ -0,0 +1,63 @@ +import { BigNumber } from "bignumber.js"; +import { DEFAULT_HRP } from "../constants"; + +export class TransactionIntentsFactoryConfig { + chainID: string; + addressHrp: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; + gasLimitIssue: BigNumber.Value; + gasLimitToggleBurnRoleGlobally: BigNumber.Value; + gasLimitEsdtLocalMint: BigNumber.Value; + gasLimitEsdtLocalBurn: BigNumber.Value; + gasLimitSetSpecialRole: BigNumber.Value; + gasLimitPausing: BigNumber.Value; + gasLimitFreezing: BigNumber.Value; + gasLimitWiping: BigNumber.Value; + gasLimitEsdtNftCreate: BigNumber.Value; + gasLimitEsdtNftUpdateAttributes: BigNumber.Value; + gasLimitEsdtNftAddQuantity: BigNumber.Value; + gasLimitEsdtNftBurn: BigNumber.Value; + gasLimitStorePerByte: BigNumber.Value; + issueCost: BigNumber.Value; + gasLimitStake: BigNumber.Value; + gasLimitUnstake: BigNumber.Value; + gasLimitUnbond: BigNumber.Value; + gasLimitCreateDelegationContract: BigNumber.Value; + gasLimitDelegationOperations: BigNumber.Value; + additionalGasLimitPerValidatorNode: BigNumber.Value; + additionalGasLimitForDelegationOperations: BigNumber.Value; + + constructor(chainId: string) { + // General-purpose configuration + this.chainID = chainId; + this.addressHrp = DEFAULT_HRP; + this.minGasLimit = new BigNumber(50000); + this.gasLimitPerByte = new BigNumber(1500); + + // Configuration for token operations + this.gasLimitIssue = new BigNumber(60000000); + this.gasLimitToggleBurnRoleGlobally = new BigNumber(60000000); + this.gasLimitEsdtLocalMint = new BigNumber(300000); + this.gasLimitEsdtLocalBurn = new BigNumber(300000); + this.gasLimitSetSpecialRole = new BigNumber(60000000); + this.gasLimitPausing = new BigNumber(60000000); + this.gasLimitFreezing = new BigNumber(60000000); + this.gasLimitWiping = new BigNumber(60000000); + this.gasLimitEsdtNftCreate = new BigNumber(3000000); + this.gasLimitEsdtNftUpdateAttributes = new BigNumber(1000000); + this.gasLimitEsdtNftAddQuantity = new BigNumber(1000000); + this.gasLimitEsdtNftBurn = new BigNumber(1000000); + this.gasLimitStorePerByte = new BigNumber(50000); + this.issueCost = new BigNumber("50000000000000000"); + + // Configuration for delegation operations + this.gasLimitStake = new BigNumber(5000000); + this.gasLimitUnstake = new BigNumber(5000000); + this.gasLimitUnbond = new BigNumber(5000000); + this.gasLimitCreateDelegationContract = new BigNumber(50000000); + this.gasLimitDelegationOperations = new BigNumber(1000000); + this.additionalGasLimitPerValidatorNode = new BigNumber(6000000); + this.additionalGasLimitForDelegationOperations = new BigNumber(10000000); + } +} From 9cda5810ecaa5495315abb8c5a882ca23ac3dd59 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 11 Sep 2023 16:39:32 +0300 Subject: [PATCH 015/275] token management transaction intents factory --- src/tokenOperations/codec.ts | 2 - ...okenManagementTransactionIntentsFactory.ts | 328 +++++++++++++++++- src/utils.codec.ts | 3 +- 3 files changed, 319 insertions(+), 14 deletions(-) diff --git a/src/tokenOperations/codec.ts b/src/tokenOperations/codec.ts index 512e5d162..64b4c4844 100644 --- a/src/tokenOperations/codec.ts +++ b/src/tokenOperations/codec.ts @@ -1,6 +1,4 @@ import BigNumber from "bignumber.js"; -import { Address } from "../address"; -import { IAddress } from "../interface"; import * as contractsCodecUtils from "../smartcontracts/codec/utils"; import * as codecUtils from "../utils.codec"; diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts index 625926ba1..cb8a405bc 100644 --- a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts @@ -2,7 +2,7 @@ import BigNumber from "bignumber.js"; import { TransactionIntent } from "../transactionIntent"; import { TransactionIntentBuilder } from "./transactionIntentBuilder"; import { IAddress } from "../interface"; -import { utf8ToHex, bigIntToHex, addressToHex } from "../utils.codec"; +import { utf8ToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { Address } from "../address"; import { Logger } from "../logger"; @@ -78,15 +78,6 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - private notifyAboutUnsettingBurnRoleGlobally() { - Logger.info(` -========== -IMPORTANT! -========== -You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). -Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); - } - createTransactionIntentForIssuingSemiFungible(options: { sender: IAddress; tokenName: string; @@ -161,7 +152,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG }).build(); } - createTransactionIntentForRegisteringMetaEsdt(options: { + createTransactionIntentForRegisteringMetaESDT(options: { sender: IAddress; tokenName: string; tokenTicker: string; @@ -286,4 +277,319 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG executionGasLimit: this.config.gasLimitSetSpecialRole }).build(); } + + createTransactionIntentForSettingSpecialRoleOnSemiFungibleToken(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + addRoleNFTCreate: boolean; + addRoleNFTBurn: boolean; + addRoleNFTAddQuantity: boolean; + addRoleESDTTransferRole: boolean; + }): TransactionIntent { + const dataParts = [ + "setSpecialRole", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user), + ...(options.addRoleNFTCreate ? [utf8ToHex("ESDTRoleNFTCreate")] : []), + ...(options.addRoleNFTBurn ? [utf8ToHex("ESDTRoleNFTBurn")] : []), + ...(options.addRoleNFTAddQuantity ? [utf8ToHex("ESDTRoleNFTAddQuantity")] : []), + ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitSetSpecialRole + }).build(); + } + + createTransactionIntentForSettingSpecialRoleOnMetaESDT(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + addRoleNFTCreate: boolean; + addRoleNFTBurn: boolean; + addRoleNFTAddQuantity: boolean; + addRoleESDTTransferRole: boolean; + }): TransactionIntent { + return this.createTransactionIntentForSettingSpecialRoleOnSemiFungibleToken(options); + } + + createTransactionIntentForSettingSpecialRoleOnNonFungibleToken(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + addRoleNFTCreate: boolean; + addRoleNFTBurn: boolean; + addRoleNFTUpdateAttributes: boolean; + addRoleNFTAddURI: boolean; + addRoleESDTTransferRole: boolean; + }): TransactionIntent { + const dataParts = [ + "setSpecialRole", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user), + ...(options.addRoleNFTCreate ? [utf8ToHex("ESDTRoleNFTCreate")] : []), + ...(options.addRoleNFTBurn ? [utf8ToHex("ESDTRoleNFTBurn")] : []), + ...(options.addRoleNFTUpdateAttributes ? [utf8ToHex("ESDTRoleNFTUpdateAttributes")] : []), + ...(options.addRoleNFTAddURI ? [utf8ToHex("ESDTRoleNFTAddURI")] : []), + ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + executionGasLimit: this.config.gasLimitSetSpecialRole + }).build(); + } + + createTransactionIntentForCreatingNFT(options: { + sender: IAddress; + tokenIdentifier: string; + initialQuantity: BigNumber.Value; + name: string; + royalties: number; + hash: string; + attributes: Uint8Array; + uris: string[]; + }): TransactionIntent { + const dataParts = [ + "ESDTNFTCreate", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.initialQuantity), + utf8ToHex(options.name), + bigIntToHex(options.royalties), + utf8ToHex(options.hash), + byteArrayToHex(options.attributes), + ...options.uris.map(utf8ToHex), + ]; + + // Note that the following is an approximation (a reasonable one): + const nftData = options.name + options.hash + options.attributes + options.uris.join(""); + const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: new BigNumber(this.config.gasLimitESDTNFTCreate).plus(storageGasLimit) + }).build(); + } + + createTransactionIntentForPausing(options: { + sender: IAddress; + tokenIdentifier: string; + }): TransactionIntent { + const dataParts = [ + "pause", + utf8ToHex(options.tokenIdentifier) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitPausing + }).build(); + } + + createTransactionIntentForUnpausing(options: { + sender: IAddress; + tokenIdentifier: string; + }): TransactionIntent { + const dataParts = [ + "unPause", + utf8ToHex(options.tokenIdentifier) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitPausing + }).build(); + } + + createTransactionIntentForFreezing(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + }): TransactionIntent { + const dataParts = [ + "freeze", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitFreezing + }).build(); + } + + createTransactionIntentForUnfreezing(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + }): TransactionIntent { + const dataParts = [ + "UnFreeze", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitFreezing + }).build(); + } + + createTransactionIntentForWiping(options: { + sender: IAddress; + user: IAddress; + tokenIdentifier: string; + }): TransactionIntent { + const dataParts = [ + "wipe", + utf8ToHex(options.tokenIdentifier), + addressToHex(options.user) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitWiping + }).build(); + } + + createTransactionIntentForLocalMint(options: { + sender: IAddress; + tokenIdentifier: string; + supplyToMint: BigNumber.Value; + }): TransactionIntent { + const dataParts = [ + "ESDTLocalMint", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.supplyToMint), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitESDTLocalMint + }).build(); + } + + createTransactionIntentForLocalBurning(options: { + sender: IAddress; + tokenIdentifier: string; + supplyToMint: BigNumber.Value; + }): TransactionIntent { + const dataParts = [ + "ESDTLocalBurn", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.supplyToMint), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitESDTLocalBurn + }).build(); + } + + createTransactionIntentForUpdatingAttributes(options: { + sender: IAddress; + tokenIdentifier: string; + tokenNonce: BigNumber.Value; + attributes: Uint8Array + }): TransactionIntent { + const dataParts = [ + "ESDTNFTUpdateAttributes", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.tokenNonce), + byteArrayToHex(options.attributes), + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitESDTNFTUpdateAttributes + }).build(); + } + + createTransactionIntentForAddingQuantity(options: { + sender: IAddress; + tokenIdentifier: string; + tokenNonce: BigNumber.Value; + quantityToAdd: BigNumber.Value + }): TransactionIntent { + const dataParts = [ + "ESDTNFTAddQuantity", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.tokenNonce), + bigIntToHex(options.quantityToAdd) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitESDTNFTAddQuantity + }).build(); + } + + createTransactionIntentForBurningQuantity(options: { + sender: IAddress; + tokenIdentifier: string; + tokenNonce: BigNumber.Value; + quantityToBurn: BigNumber.Value + }): TransactionIntent { + const dataParts = [ + "ESDTNFTBurn", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(options.tokenNonce), + bigIntToHex(options.quantityToBurn) + ]; + + return new TransactionIntentBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + executionGasLimit: this.config.gasLimitESDTNFTBurn + }).build(); + } + + private notifyAboutUnsettingBurnRoleGlobally() { + Logger.info(` +========== +IMPORTANT! +========== +You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). +Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); + } } diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 5be00dd26..6288b99e6 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -30,7 +30,8 @@ export function utf8ToHex(value: string) { } export function byteArrayToHex(byteArray: Uint8Array): string { - return Buffer.from(byteArray).toString("hex"); + const hexString = Buffer.from(byteArray).toString("hex"); + return zeroPadStringIfOddLength(hexString); } export function bigIntToHex(value: BigNumber.Value): string { From d4f75a0fdeb10ec8dd1b12423ddbc60549df90dd Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 12 Sep 2023 11:21:25 +0300 Subject: [PATCH 016/275] add unit tests --- ...anagementTransactionIntentsFactory.spec.ts | 152 ++++++++++++++++++ ...okenManagementTransactionIntentsFactory.ts | 25 ++- 2 files changed, 164 insertions(+), 13 deletions(-) diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts index e69de29bb..b6fa00a1b 100644 --- a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -0,0 +1,152 @@ +import { assert } from "chai"; +import { loadTestWallets, TestWallet } from "../testutils"; +import { TokenManagementTransactionIntentsFactory } from "./tokenManagementTransactionIntentsFactory"; +import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; +import BigNumber from "bignumber.js"; +import { ESDT_CONTRACT_ADDRESS } from "../constants"; + +describe("test token management transaction intents factory", () => { + let frank: TestWallet, grace: TestWallet; + let factory: TokenManagementTransactionIntentsFactory; + let config: TransactionIntentsFactoryConfig; + + before(async function () { + ({ frank, grace } = await loadTestWallets()); + config = new TransactionIntentsFactoryConfig("T"); + factory = new TokenManagementTransactionIntentsFactory(config); + }); + + it("should create transaction intent for registering and setting roles", () => { + const intent = factory.createTransactionIntentForRegisteringAndSettingRoles({ + sender: frank.address, + tokenName: "TEST", + tokenTicker: "TEST", + tokenType: "FNG", + numDecimals: 2 + }); + + assert.deepEqual(intent.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); + assert.deepEqual(intent.value, config.issueCost); + assert.deepEqual(intent.gasLimit, new BigNumber("60125000")); + }); + + it("should create transaction intent for issuing fungible token", () => { + const intent = factory.createTransactionIntentForIssuingFungible({ + sender: frank.address, + tokenName: "FRANK", + tokenTicker: "FRANK", + initialSupply: 100, + numDecimals: 0, + canFreeze: true, + canWipe: true, + canPause: true, + canChangeOwner: true, + canUpgrade: true, + canAddSpecialRoles: true + }); + + assert.deepEqual(intent.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(intent.value, config.issueCost); + }); + + it("should create transaction intent for issuing semi-fungible token", () => { + const intent = factory.createTransactionIntentForIssuingSemiFungible({ + sender: frank.address, + tokenName: "FRANK", + tokenTicker: "FRANK", + canFreeze: true, + canWipe: true, + canPause: true, + canTransferNFTCreateRole: true, + canChangeOwner: true, + canUpgrade: true, + canAddSpecialRoles: true + }); + + assert.deepEqual(intent.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(intent.value, config.issueCost); + }); + + it("should create transaction intent for issuing non-fungible token", () => { + const intent = factory.createTransactionIntentForIssuingNonFungible({ + sender: frank.address, + tokenName: "FRANK", + tokenTicker: "FRANK", + canFreeze: true, + canWipe: true, + canPause: true, + canTransferNFTCreateRole: true, + canChangeOwner: true, + canUpgrade: true, + canAddSpecialRoles: true + }); + + assert.deepEqual(intent.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(intent.value, config.issueCost); + }); + + it("should create transaction intent for registering metaEsdt", () => { + const intent = factory.createTransactionIntentForRegisteringMetaESDT({ + sender: frank.address, + tokenName: "FRANK", + tokenTicker: "FRANK", + numDecimals: 10, + canFreeze: true, + canWipe: true, + canPause: true, + canTransferNFTCreateRole: true, + canChangeOwner: true, + canUpgrade: true, + canAddSpecialRoles: true + }); + + assert.deepEqual(intent.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(intent.value, config.issueCost); + }); + + it("should create transaction intent for setting spcial role on non-fungible token", () => { + const intent = factory.createTransactionIntentForSettingSpecialRoleOnNonFungibleToken({ + sender: frank.address, + user: grace.address, + tokenIdentifier: "FRANK-11ce3e", + addRoleNFTCreate: true, + addRoleNFTBurn: false, + addRoleNFTUpdateAttributes: true, + addRoleNFTAddURI: true, + addRoleESDTTransferRole: false + }); + + assert.deepEqual(intent.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); + assert.equal(intent.sender, frank.address.toString()); + assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); + assert.equal(intent.value, 0); + }); + + it("should create transaction intent for creating nft", () => { + const intent = factory.createTransactionIntentForCreatingNFT({ + sender: grace.address, + tokenIdentifier: "FRANK-aa9e8d", + initialQuantity: 1, + name: `test`, + royalties: 1000, + hash: "abba", + attributes: Buffer.from("test"), + uris: ["a", "b"] + }); + + assert.deepEqual(intent.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); + assert.equal(intent.sender, grace.address.toString()); + assert.equal(intent.receiver, grace.address.toString()); + assert.equal(intent.value, 0); + }); +}); diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts index cb8a405bc..16269c49a 100644 --- a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts @@ -13,19 +13,18 @@ interface Config { gasLimitPerByte: BigNumber.Value gasLimitIssue: BigNumber.Value gasLimitToggleBurnRoleGlobally: BigNumber.Value - gasLimitESDTLocalMint: BigNumber.Value - gasLimitESDTLocalBurn: BigNumber.Value + gasLimitEsdtLocalMint: BigNumber.Value + gasLimitEsdtLocalBurn: BigNumber.Value gasLimitSetSpecialRole: BigNumber.Value gasLimitPausing: BigNumber.Value gasLimitFreezing: BigNumber.Value gasLimitWiping: BigNumber.Value - gasLimitESDTNFTCreate: BigNumber.Value - gasLimitESDTNFTUpdateAttributes: BigNumber.Value - gasLimitESDTNFTAddQuantity: BigNumber.Value - gasLimitESDTNFTBurn: BigNumber.Value + gasLimitEsdtNftCreate: BigNumber.Value + gasLimitEsdtNftUpdateAttributes: BigNumber.Value + gasLimitEsdtNftAddQuantity: BigNumber.Value + gasLimitEsdtNftBurn: BigNumber.Value gasLimitStorePerByte: BigNumber.Value issueCost: BigNumber.Value - esdtContractAddress: IAddress } type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; @@ -378,7 +377,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitESDTNFTCreate).plus(storageGasLimit) + executionGasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit) }).build(); } @@ -494,7 +493,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitESDTLocalMint + executionGasLimit: this.config.gasLimitEsdtLocalMint }).build(); } @@ -514,7 +513,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitESDTLocalBurn + executionGasLimit: this.config.gasLimitEsdtLocalBurn }).build(); } @@ -536,7 +535,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitESDTNFTUpdateAttributes + executionGasLimit: this.config.gasLimitEsdtNftUpdateAttributes }).build(); } @@ -558,7 +557,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitESDTNFTAddQuantity + executionGasLimit: this.config.gasLimitEsdtNftAddQuantity }).build(); } @@ -580,7 +579,7 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitESDTNFTBurn + executionGasLimit: this.config.gasLimitEsdtNftBurn }).build(); } From a5a141ee0b9489ec2fc13b871bf2c4da1934353b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 12 Sep 2023 17:24:39 +0300 Subject: [PATCH 017/275] started to use sc intents factory in the sc class --- src/smartcontracts/codeMetadata.ts | 19 +++++- src/smartcontracts/interface.ts | 6 +- src/smartcontracts/smartContract.ts | 66 ++++++++++++++----- .../smartContractTransactionIntentsFactory.ts | 13 +++- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/smartcontracts/codeMetadata.ts b/src/smartcontracts/codeMetadata.ts index 46e74a139..1025f4a08 100644 --- a/src/smartcontracts/codeMetadata.ts +++ b/src/smartcontracts/codeMetadata.ts @@ -6,6 +6,7 @@ export class CodeMetadata { private readable: boolean; private payable: boolean; private payableBySc: boolean; + private static readonly lengthOfCodeMetadata = 2; /** * Creates a metadata object. By default, set the `upgradeable` attribute, and uset all others. @@ -22,6 +23,22 @@ export class CodeMetadata { this.payableBySc = payableBySc } + static fromBytes(bytes: Uint8Array): CodeMetadata { + if (bytes.length !== this.lengthOfCodeMetadata) { + return new CodeMetadata(); + } + + const byteZero = bytes[0]; + const byteOne = bytes[1]; + + const upgradeable = (byteZero & ByteZero.Upgradeable) !== 0; + const readable = (byteZero & ByteZero.Readable) !== 0; + const payable = (byteOne & ByteOne.Payable) !== 0; + const payableBySc = (byteOne & ByteOne.PayableBySc) !== 0; + + return new CodeMetadata(upgradeable, readable, payable, payableBySc); + } + /** * Adjust the metadata (the `upgradeable` attribute), when preparing the deployment transaction. */ @@ -49,7 +66,7 @@ export class CodeMetadata { togglePayableBySc(value: boolean) { this.payableBySc = value; } - + /** * Converts the metadata to the protocol-friendly representation. */ diff --git a/src/smartcontracts/interface.ts b/src/smartcontracts/interface.ts index 2aa1815a9..6771d0572 100644 --- a/src/smartcontracts/interface.ts +++ b/src/smartcontracts/interface.ts @@ -31,7 +31,7 @@ export interface ISmartContract { export interface DeployArguments { code: ICode; codeMetadata?: ICodeMetadata; - initArguments?: TypedValue[]; + initArguments?: any[]; value?: ITransactionValue; gasLimit: IGasLimit; gasPrice?: IGasPrice; @@ -42,7 +42,7 @@ export interface DeployArguments { export interface UpgradeArguments { code: ICode; codeMetadata?: ICodeMetadata; - initArguments?: TypedValue[]; + initArguments?: any[]; value?: ITransactionValue; gasLimit: IGasLimit; gasPrice?: IGasPrice; @@ -52,7 +52,7 @@ export interface UpgradeArguments { export interface CallArguments { func: IContractFunction; - args?: TypedValue[]; + args?: any[]; value?: ITransactionValue; gasLimit: IGasLimit; receiver?: IAddress; diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 0ab5e8e00..1b3f11dce 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -9,14 +9,19 @@ import { bigIntToBuffer } from "./codec/utils"; import { CodeMetadata } from "./codeMetadata"; import { ContractFunction } from "./function"; import { Interaction } from "./interaction"; -import { CallArguments, DeployArguments, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; +import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; -import { ArwenVirtualMachine, ContractCallPayloadBuilder, ContractDeployPayloadBuilder, ContractUpgradePayloadBuilder } from "./transactionPayloadBuilders"; +import { ArwenVirtualMachine, ContractCallPayloadBuilder, ContractUpgradePayloadBuilder } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; +import { SmartContractTransactionIntentsFactory } from "../transactionIntentsFactories/smartContractTransactionIntentsFactory"; +import { TransactionIntentsFactoryConfig } from "../transactionIntentsFactories/transactionIntentsFactoryConfig"; +import { TransactionPayload } from "../transactionPayload"; const createKeccakHash = require("keccak"); interface IAbi { + constructorDefinition: EndpointDefinition; + getEndpoints(): EndpointDefinition[]; getEndpoint(name: string | ContractFunction): EndpointDefinition; } @@ -110,27 +115,58 @@ export class SmartContract implements ISmartContract { deploy({ deployer, code, codeMetadata, initArguments, value, gasLimit, gasPrice, chainID }: DeployArguments): Transaction { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); - codeMetadata = codeMetadata || new CodeMetadata(); - initArguments = initArguments || []; - value = value || 0; + const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionIntentsFactory({ + config: config, + abi: this.abi + }); - let payload = new ContractDeployPayloadBuilder() - .setCode(code) - .setCodeMetadata(codeMetadata) - .setInitArgs(initArguments) - .build(); + const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); + const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - let transaction = new Transaction({ - receiver: Address.Zero(), + const intent = scIntentFactory.createTransactionIntentForDeploy({ sender: deployer, + bytecode: bytecode, + gasLimit: gasLimit.valueOf(), + args: initArguments, + isUpgradeable: metadataAsJson.upgradeable, + isReadable: metadataAsJson.readable, + isPayable: metadataAsJson.payable, + isPayableBySmartContract: metadataAsJson.payableBySc + }); + + return new Transaction({ + receiver: Address.fromBech32(intent.receiver), + sender: Address.fromBech32(intent.sender), value: value, - gasLimit: gasLimit, + gasLimit: new BigNumber(intent.gasLimit).toNumber(), gasPrice: gasPrice, - data: payload, + data: new TransactionPayload(Buffer.from(intent.data!)), chainID: chainID }); + } - return transaction; + private getMetadataPropertiesAsObject(codeMetadata?: ICodeMetadata): { + upgradeable: boolean, + readable: boolean, + payable: boolean, + payableBySc: boolean + } { + let metadata: CodeMetadata; + if (codeMetadata) { + metadata = CodeMetadata.fromBytes(Buffer.from(codeMetadata.toString(), "hex")); + } + else { + metadata = new CodeMetadata(); + } + const metadataAsJson = metadata.toJSON() as { + upgradeable: boolean, + readable: boolean, + payable: boolean, + payableBySc: boolean + }; + + return metadataAsJson; } /** diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 21b5a83c7..4a3475ca4 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { TransactionIntent } from "../transactionIntent"; -import { AbiRegistry, ArgSerializer, CodeMetadata, EndpointDefinition } from "../smartcontracts"; +import { AbiRegistry, ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; @@ -15,16 +15,23 @@ interface Config { gasLimitPerByte: BigNumber.Value; } +interface Abi { + constructorDefinition: EndpointDefinition; + + getEndpoint(name: string | ContractFunction): EndpointDefinition; +} + + export class SmartContractTransactionIntentsFactory { private readonly config: Config; - private readonly abiRegistry?: AbiRegistry; + private readonly abiRegistry?: Abi; constructor({ config, abi }: { config: Config; - abi?: AbiRegistry; + abi?: Abi; }) { this.config = config; this.abiRegistry = abi; From bffae4a907c4bb1e6ef2845e0097304d941fc60d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 13 Sep 2023 10:59:28 +0300 Subject: [PATCH 018/275] fix transaction intent for deploy --- src/smartcontracts/smartContract.spec.ts | 2 +- .../smartContractTransactionIntentsFactory.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 51233d058..25ef5f028 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -49,7 +49,7 @@ describe("test contract", () => { deployTransaction.setNonce(alice.account.nonce); assert.equal(deployTransaction.getData().valueOf().toString(), "01020304@0500@0100"); - assert.equal(deployTransaction.getGasLimit().valueOf(), 1000000); + assert.equal(deployTransaction.getGasLimit().valueOf(), 1077000); assert.equal(deployTransaction.getNonce().valueOf(), 42); // Compute & set the contract address diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 4a3475ca4..1aeda4dfb 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -47,10 +47,10 @@ export class SmartContractTransactionIntentsFactory { isPayable?: boolean, isPayableBySmartContract?: boolean }): TransactionIntent { - const isUpgradeable = options.isUpgradeable || true; - const isReadable = options.isReadable || true; - const isPayable = options.isPayable || false; - const isPayableBySmartContract = options.isPayableBySmartContract || true; + const isUpgradeable = options.isUpgradeable ?? true; + const isReadable = options.isReadable ?? true; + const isPayable = options.isPayable ?? false; + const isPayableBySmartContract = options.isPayableBySmartContract ?? true; const args = options.args || []; From 19a643edad7e0bc8d80814c201480fccc4938224 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 13 Sep 2023 11:45:11 +0300 Subject: [PATCH 019/275] contract upgrade --- src/smartcontracts/smartContract.spec.ts | 39 +++++++++++++++++++ src/smartcontracts/smartContract.ts | 37 +++++++++++------- .../smartContractTransactionIntentsFactory.ts | 8 ++-- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 25ef5f028..88a73643b 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -125,4 +125,43 @@ describe("test contract", () => { assert.isTrue((await provider.getTransactionStatus(hashOne)).isExecuted()); assert.isTrue((await provider.getTransactionStatus(hashTwo)).isExecuted()); }); + + it.only("should upgrade", async () => { + setupUnitTestWatcherTimeouts(); + let watcher = new TransactionWatcher(provider); + + let contract = new SmartContract(); + contract.setAddress(Address.fromBech32("erd1qqqqqqqqqqqqqpgq3ytm9m8dpeud35v3us20vsafp77smqghd8ss4jtm0q")) + + let deployTransaction = contract.upgrade({ + code: Code.fromBuffer(Buffer.from([1, 2, 3, 4])), + gasLimit: 1000000, + chainID: chainID, + caller: alice.address + }); + + provider.mockUpdateAccount(alice.address, account => { + account.nonce = 42; + }); + + await alice.sync(provider); + deployTransaction.setNonce(alice.account.nonce); + + assert.equal(deployTransaction.getData().valueOf().toString(), "upgradeContract@01020304@0100"); + assert.equal(deployTransaction.getGasLimit().valueOf(), 1093500); + assert.equal(deployTransaction.getNonce().valueOf(), 42); + + // Sign the transaction + alice.signer.sign(deployTransaction); + + // Now let's broadcast the deploy transaction, and wait for its execution. + let hash = await provider.sendTransaction(deployTransaction); + + await Promise.all([ + provider.mockTransactionTimeline(deployTransaction, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), + watcher.awaitCompleted(deployTransaction) + ]); + + assert.isTrue((await provider.getTransactionStatus(hash)).isExecuted()); + }); }); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 1b3f11dce..784628df2 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -177,27 +177,36 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); - codeMetadata = codeMetadata || new CodeMetadata(); - initArguments = initArguments || []; - value = value || 0; + const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionIntentsFactory({ + config: config, + abi: this.abi + }); - let payload = new ContractUpgradePayloadBuilder() - .setCode(code) - .setCodeMetadata(codeMetadata) - .setInitArgs(initArguments) - .build(); + const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); + const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - let transaction = new Transaction({ + const intent = scIntentFactory.createTransactionIntentForUpgrade({ sender: caller, - receiver: this.getAddress(), + contract: this.getAddress(), + bytecode: bytecode, + gasLimit: gasLimit.valueOf(), + args: initArguments, + isUpgradeable: metadataAsJson.upgradeable, + isReadable: metadataAsJson.readable, + isPayable: metadataAsJson.payable, + isPayableBySmartContract: metadataAsJson.payableBySc + }) + + return new Transaction({ + receiver: Address.fromBech32(intent.receiver), + sender: Address.fromBech32(intent.sender), value: value, - gasLimit: gasLimit, + gasLimit: new BigNumber(intent.gasLimit).toNumber(), gasPrice: gasPrice, - data: payload, + data: new TransactionPayload(Buffer.from(intent.data!)), chainID: chainID }); - - return transaction; } /** diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 1aeda4dfb..15ea40c16 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -108,10 +108,10 @@ export class SmartContractTransactionIntentsFactory { isPayableBySmartContract?: boolean } ): TransactionIntent { - const isUpgradeable = options.isUpgradeable || true; - const isReadable = options.isReadable || true; - const isPayable = options.isPayable || false; - const isPayableBySmartContract = options.isPayableBySmartContract || true; + const isUpgradeable = options.isUpgradeable ?? true; + const isReadable = options.isReadable ?? true; + const isPayable = options.isPayable ?? false; + const isPayableBySmartContract = options.isPayableBySmartContract ?? true; const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); From 48ee42807b3378fbb83400d9366716711cc5f48f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 13 Sep 2023 13:56:07 +0300 Subject: [PATCH 020/275] integrate sc intents factory --- src/smartcontracts/interaction.spec.ts | 6 ++-- src/smartcontracts/smartContract.spec.ts | 6 ++-- src/smartcontracts/smartContract.ts | 31 ++++++++++++------- ...tContractTransactionIntentsFactory.spec.ts | 4 +-- .../smartContractTransactionIntentsFactory.ts | 6 ++-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 2fb119d16..501b11d96 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -41,7 +41,7 @@ describe("test smart contract interactor", function () { assert.deepEqual(transaction.getReceiver(), dummyAddress); assert.equal(transaction.getValue().toString(), "1000000000000000000"); assert.equal(transaction.getNonce(), 7); - assert.equal(transaction.getGasLimit().valueOf(), 20000000); + assert.equal(transaction.getGasLimit().valueOf(), 20057500); }); it("should set transfers (payments) on contract calls (transfer and execute)", async function () { @@ -188,7 +188,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getData().toString(), "getUltimateAnswer"); assert.equal( transaction.getHash().toString(), - "60d0956a8902c1179dce92d91bd9670e31b9a9cd07c1d620edb7754a315b4818" + "3ff6309bfe87ecc4ab541db649d57187f3a012291570552ac003866f77212c19" ); transaction = interaction.withNonce(1).buildTransaction(); @@ -198,7 +198,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getNonce().valueOf(), 1); assert.equal( transaction.getHash().toString(), - "acd207c38f6c3341b18d8ef331fa07ba49615fa12d7610aad5d8495293049f24" + "85a3044ba2e07317a7e5dd866a5e57f900f7e01d0802c8cd634f4a521261dadf" ); // Execute, and wait for execution diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 88a73643b..af74abb2f 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -103,10 +103,10 @@ describe("test contract", () => { assert.equal(callTransactionOne.getNonce().valueOf(), 42); assert.equal(callTransactionOne.getData().valueOf().toString(), "helloEarth@05@0123"); - assert.equal(callTransactionOne.getGasLimit().valueOf(), 150000); + assert.equal(callTransactionOne.getGasLimit().valueOf(), 227000); assert.equal(callTransactionTwo.getNonce().valueOf(), 43); assert.equal(callTransactionTwo.getData().valueOf().toString(), "helloMars@05@0123"); - assert.equal(callTransactionTwo.getGasLimit().valueOf(), 1500000); + assert.equal(callTransactionTwo.getGasLimit().valueOf(), 1575500); // Sign transactions, broadcast them alice.signer.sign(callTransactionOne); @@ -126,7 +126,7 @@ describe("test contract", () => { assert.isTrue((await provider.getTransactionStatus(hashTwo)).isExecuted()); }); - it.only("should upgrade", async () => { + it("should upgrade", async () => { setupUnitTestWatcherTimeouts(); let watcher = new TransactionWatcher(provider); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 784628df2..011187fdb 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -199,8 +199,8 @@ export class SmartContract implements ISmartContract { }) return new Transaction({ - receiver: Address.fromBech32(intent.receiver), sender: Address.fromBech32(intent.sender), + receiver: Address.fromBech32(intent.receiver), value: value, gasLimit: new BigNumber(intent.gasLimit).toNumber(), gasPrice: gasPrice, @@ -217,25 +217,32 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); + const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionIntentsFactory({ + config: config, + abi: this.abi + }); + args = args || []; value = value || 0; - let payload = new ContractCallPayloadBuilder() - .setFunction(func) - .setArgs(args) - .build(); + const intent = scIntentFactory.createTransactionIntentForExecute({ + sender: caller, + contractAddress: receiver ? receiver : this.getAddress(), + functionName: func.toString(), + gasLimit: gasLimit.valueOf(), + args: args + }) - let transaction = new Transaction({ + return new Transaction({ sender: caller, - receiver: receiver ? receiver : this.getAddress(), + receiver: Address.fromBech32(intent.receiver), value: value, - gasLimit: gasLimit, + gasLimit: new BigNumber(intent.gasLimit).toNumber(), gasPrice: gasPrice, - data: payload, - chainID: chainID, + data: new TransactionPayload(Buffer.from(intent.data!)), + chainID: chainID }); - - return transaction; } createQuery({ func, args, value, caller }: QueryArguments): Query { diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index 9fdfb020b..61a5436fd 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -84,14 +84,14 @@ describe("test smart contract intents factory", function () { const deployIntent = factory.createTransactionIntentForExecute({ sender: sender, contractAddress: contract, - func: func, + functionName: func, gasLimit: gasLimit, args: args }); const abiDeployIntent = abiAwareFactory.createTransactionIntentForExecute({ sender: sender, contractAddress: contract, - func: func, + functionName: func, gasLimit: gasLimit, args: args }); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 15ea40c16..85899cfdc 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -76,15 +76,15 @@ export class SmartContractTransactionIntentsFactory { createTransactionIntentForExecute(options: { sender: IAddress, contractAddress: IAddress, - func: string, + functionName: string, gasLimit: BigNumber.Value, args?: any[] } ): TransactionIntent { const args = options.args || []; - let parts: string[] = [options.func]; + let parts: string[] = [options.functionName]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName)); parts = parts.concat(preparedArgs); return new TransactionIntentBuilder({ From bf0a6537f3f75e1fa8ddfedf43a724c2bdd2f9c8 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 13 Sep 2023 14:07:44 +0300 Subject: [PATCH 021/275] rename variable --- src/smartcontracts/codeMetadata.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smartcontracts/codeMetadata.ts b/src/smartcontracts/codeMetadata.ts index 1025f4a08..6b493b5b2 100644 --- a/src/smartcontracts/codeMetadata.ts +++ b/src/smartcontracts/codeMetadata.ts @@ -6,7 +6,7 @@ export class CodeMetadata { private readable: boolean; private payable: boolean; private payableBySc: boolean; - private static readonly lengthOfCodeMetadata = 2; + private static readonly codeMetadataLength = 2; /** * Creates a metadata object. By default, set the `upgradeable` attribute, and uset all others. @@ -24,7 +24,7 @@ export class CodeMetadata { } static fromBytes(bytes: Uint8Array): CodeMetadata { - if (bytes.length !== this.lengthOfCodeMetadata) { + if (bytes.length !== this.codeMetadataLength) { return new CodeMetadata(); } From 8dcf4bd8f639bed811ed62a8431f9aa75cf97b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 17 Sep 2023 20:58:04 +0300 Subject: [PATCH 022/275] New parameter on "transactionIntentBuilder": "addDataMovementGas". --- .../delegationTransactionIntentsFactory.ts | 42 ++++++++----- ...tContractTransactionIntentsFactory.spec.ts | 8 +-- .../smartContractTransactionIntentsFactory.ts | 9 ++- ...okenManagementTransactionIntentsFactory.ts | 63 ++++++++++++------- .../transactionIntentBuilder.ts | 19 ++++-- 5 files changed, 92 insertions(+), 49 deletions(-) diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts index ad1a92c82..1a8cc5be4 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts @@ -50,7 +50,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), dataParts: dataParts, - executionGasLimit: executionGasLimit, + gasLimit: executionGasLimit, + addDataMovementGas: true, value: options.value }).build(); } @@ -77,7 +78,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true }).build(); } @@ -99,7 +101,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true }).build(); } @@ -125,7 +128,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: executionGasLimit + gasLimit: executionGasLimit, + addDataMovementGas: true }).build(); } @@ -151,7 +155,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: executionGasLimit + gasLimit: executionGasLimit, + addDataMovementGas: true }).build(); } @@ -177,7 +182,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: executionGasLimit + gasLimit: executionGasLimit, + addDataMovementGas: true }).build(); } @@ -199,7 +205,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes) + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true }).build(); } @@ -218,7 +225,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -237,7 +245,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -255,7 +264,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -273,7 +283,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -291,7 +302,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -309,7 +321,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } @@ -332,7 +345,8 @@ export class DelegationTransactionIntentsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations) + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true }).build(); } diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts index 9fdfb020b..67b236e25 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts @@ -67,8 +67,7 @@ describe("test smart contract intents factory", function () { assert.isDefined(deployIntent.data); expect(deployIntent.data!.length).to.be.greaterThan(0); - const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data!.length; - assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); + assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); assert.equal(deployIntent.value, 0); assert.deepEqual(deployIntent, abiDeployIntent); @@ -102,7 +101,7 @@ describe("test smart contract intents factory", function () { assert.isDefined(deployIntent.data); assert.deepEqual(deployIntent.data, Buffer.from("add@07")); - assert.equal(deployIntent.gasLimit.valueOf(), 6059000); + assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); assert.equal(deployIntent.value, 0); assert.deepEqual(deployIntent, abiDeployIntent); @@ -135,8 +134,7 @@ describe("test smart contract intents factory", function () { assert.isDefined(deployIntent.data); assert.isTrue(Buffer.from(deployIntent.data!).toString().startsWith("upgradeContract@")); - const expectedGasLimit = 6000000 + 50000 + 1500 * deployIntent.data!.length; - assert.equal(deployIntent.gasLimit.valueOf(), expectedGasLimit); + assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); assert.equal(deployIntent.value, 0); assert.deepEqual(deployIntent, abiDeployIntent); diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts index 21b5a83c7..c33d887ee 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts @@ -62,7 +62,8 @@ export class SmartContractTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), dataParts: parts, - executionGasLimit: options.gasLimit + gasLimit: options.gasLimit, + addDataMovementGas: false }).build(); } @@ -85,7 +86,8 @@ export class SmartContractTransactionIntentsFactory { sender: options.sender, receiver: options.contractAddress, dataParts: parts, - executionGasLimit: options.gasLimit + gasLimit: options.gasLimit, + addDataMovementGas: false }).build(); } @@ -123,7 +125,8 @@ export class SmartContractTransactionIntentsFactory { sender: options.sender, receiver: options.contract, dataParts: parts, - executionGasLimit: options.gasLimit + gasLimit: options.gasLimit, + addDataMovementGas: false }).build(); } diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts index 16269c49a..5c6032027 100644 --- a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts +++ b/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts @@ -72,7 +72,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitIssue, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, value: this.config.issueCost }).build(); } @@ -109,7 +110,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitIssue, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, value: this.config.issueCost }).build(); } @@ -146,7 +148,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitIssue, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, value: this.config.issueCost }).build(); } @@ -185,7 +188,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitIssue, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, value: this.config.issueCost }).build(); } @@ -212,7 +216,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitIssue, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, value: this.config.issueCost }).build(); } @@ -231,7 +236,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally + gasLimit: this.config.gasLimitToggleBurnRoleGlobally, + addDataMovementGas: true }).build(); } @@ -249,7 +255,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally + gasLimit: this.config.gasLimitToggleBurnRoleGlobally, + addDataMovementGas: true, }).build(); } @@ -273,7 +280,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitSetSpecialRole + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true }).build(); } @@ -301,7 +309,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitSetSpecialRole + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true }).build(); } @@ -343,7 +352,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, - executionGasLimit: this.config.gasLimitSetSpecialRole + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true }).build(); } @@ -377,7 +387,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit) + gasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit), + addDataMovementGas: true }).build(); } @@ -395,7 +406,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitPausing + gasLimit: this.config.gasLimitPausing, + addDataMovementGas: true }).build(); } @@ -413,7 +425,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitPausing + gasLimit: this.config.gasLimitPausing, + addDataMovementGas: true }).build(); } @@ -433,7 +446,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitFreezing + gasLimit: this.config.gasLimitFreezing, + addDataMovementGas: true }).build(); } @@ -453,7 +467,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitFreezing + gasLimit: this.config.gasLimitFreezing, + addDataMovementGas: true }).build(); } @@ -473,7 +488,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitWiping + gasLimit: this.config.gasLimitWiping, + addDataMovementGas: true }).build(); } @@ -493,7 +509,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitEsdtLocalMint + gasLimit: this.config.gasLimitEsdtLocalMint, + addDataMovementGas: true }).build(); } @@ -513,7 +530,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitEsdtLocalBurn + gasLimit: this.config.gasLimitEsdtLocalBurn, + addDataMovementGas: true }).build(); } @@ -535,7 +553,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitEsdtNftUpdateAttributes + gasLimit: this.config.gasLimitEsdtNftUpdateAttributes, + addDataMovementGas: true }).build(); } @@ -557,7 +576,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitEsdtNftAddQuantity + gasLimit: this.config.gasLimitEsdtNftAddQuantity, + addDataMovementGas: true }).build(); } @@ -579,7 +599,8 @@ export class TokenManagementTransactionIntentsFactory { sender: options.sender, receiver: options.sender, dataParts: dataParts, - executionGasLimit: this.config.gasLimitEsdtNftBurn + gasLimit: this.config.gasLimitEsdtNftBurn, + addDataMovementGas: true }).build(); } diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionIntentsFactories/transactionIntentBuilder.ts index c294f6d2f..000760173 100644 --- a/src/transactionIntentsFactories/transactionIntentBuilder.ts +++ b/src/transactionIntentsFactories/transactionIntentBuilder.ts @@ -14,7 +14,8 @@ export class TransactionIntentBuilder { private sender: IAddress; private receiver: IAddress; private dataParts: string[]; - private executionGasLimit: BigNumber.Value; + private providedGasLimit: BigNumber; + private addDataMovementGas: boolean; private value?: BigNumber.Value; constructor(options: { @@ -22,20 +23,26 @@ export class TransactionIntentBuilder { sender: IAddress, receiver: IAddress, dataParts: string[], - executionGasLimit: BigNumber.Value, + gasLimit: BigNumber.Value, + addDataMovementGas: boolean, value?: BigNumber.Value }) { this.config = options.config; this.sender = options.sender; this.receiver = options.receiver; this.dataParts = options.dataParts; - this.executionGasLimit = options.executionGasLimit; + this.providedGasLimit = new BigNumber(options.gasLimit); + this.addDataMovementGas = options.addDataMovementGas; this.value = options.value; } - private computeGasLimit(payload: ITransactionPayload, executionGasLimit: BigNumber.Value): BigNumber.Value { + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(executionGasLimit); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); return gasLimit; } @@ -46,7 +53,7 @@ export class TransactionIntentBuilder { build(): TransactionIntent { const data = this.buildTransactionPayload() - const gasLimit = this.computeGasLimit(data, this.executionGasLimit); + const gasLimit = this.computeGasLimit(data); return new TransactionIntent({ sender: this.sender.bech32(), From 74b047887a1d806533f602d5d832f34a25d552bf Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Sep 2023 16:14:41 +0300 Subject: [PATCH 023/275] fixes after review --- src/smartcontracts/codeMetadata.spec.ts | 17 +++++++++++++++++ src/smartcontracts/interaction.spec.ts | 6 +++--- src/smartcontracts/smartContract.spec.ts | 8 ++++---- src/smartcontracts/smartContract.ts | 2 +- 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 src/smartcontracts/codeMetadata.spec.ts diff --git a/src/smartcontracts/codeMetadata.spec.ts b/src/smartcontracts/codeMetadata.spec.ts new file mode 100644 index 000000000..753be4612 --- /dev/null +++ b/src/smartcontracts/codeMetadata.spec.ts @@ -0,0 +1,17 @@ +import { assert } from "chai"; +import { CodeMetadata } from "./codeMetadata"; + +describe("test code metadata", function () { + it("should test code metadata from bytes", () => { + const bytes = new Uint8Array([1, 0]); + const codeMetadata = CodeMetadata.fromBytes(bytes); + + assert.equal(codeMetadata.toString(), "0100"); + assert.deepEqual(codeMetadata.toJSON(), { + upgradeable: true, + readable: false, + payable: false, + payableBySc: false + }); + }); +}); diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 501b11d96..2fb119d16 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -41,7 +41,7 @@ describe("test smart contract interactor", function () { assert.deepEqual(transaction.getReceiver(), dummyAddress); assert.equal(transaction.getValue().toString(), "1000000000000000000"); assert.equal(transaction.getNonce(), 7); - assert.equal(transaction.getGasLimit().valueOf(), 20057500); + assert.equal(transaction.getGasLimit().valueOf(), 20000000); }); it("should set transfers (payments) on contract calls (transfer and execute)", async function () { @@ -188,7 +188,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getData().toString(), "getUltimateAnswer"); assert.equal( transaction.getHash().toString(), - "3ff6309bfe87ecc4ab541db649d57187f3a012291570552ac003866f77212c19" + "60d0956a8902c1179dce92d91bd9670e31b9a9cd07c1d620edb7754a315b4818" ); transaction = interaction.withNonce(1).buildTransaction(); @@ -198,7 +198,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getNonce().valueOf(), 1); assert.equal( transaction.getHash().toString(), - "85a3044ba2e07317a7e5dd866a5e57f900f7e01d0802c8cd634f4a521261dadf" + "acd207c38f6c3341b18d8ef331fa07ba49615fa12d7610aad5d8495293049f24" ); // Execute, and wait for execution diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index af74abb2f..337f7ac18 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -49,7 +49,7 @@ describe("test contract", () => { deployTransaction.setNonce(alice.account.nonce); assert.equal(deployTransaction.getData().valueOf().toString(), "01020304@0500@0100"); - assert.equal(deployTransaction.getGasLimit().valueOf(), 1077000); + assert.equal(deployTransaction.getGasLimit().valueOf(), 1000000); assert.equal(deployTransaction.getNonce().valueOf(), 42); // Compute & set the contract address @@ -103,10 +103,10 @@ describe("test contract", () => { assert.equal(callTransactionOne.getNonce().valueOf(), 42); assert.equal(callTransactionOne.getData().valueOf().toString(), "helloEarth@05@0123"); - assert.equal(callTransactionOne.getGasLimit().valueOf(), 227000); + assert.equal(callTransactionOne.getGasLimit().valueOf(), 150000); assert.equal(callTransactionTwo.getNonce().valueOf(), 43); assert.equal(callTransactionTwo.getData().valueOf().toString(), "helloMars@05@0123"); - assert.equal(callTransactionTwo.getGasLimit().valueOf(), 1575500); + assert.equal(callTransactionTwo.getGasLimit().valueOf(), 1500000); // Sign transactions, broadcast them alice.signer.sign(callTransactionOne); @@ -148,7 +148,7 @@ describe("test contract", () => { deployTransaction.setNonce(alice.account.nonce); assert.equal(deployTransaction.getData().valueOf().toString(), "upgradeContract@01020304@0100"); - assert.equal(deployTransaction.getGasLimit().valueOf(), 1093500); + assert.equal(deployTransaction.getGasLimit().valueOf(), 1000000); assert.equal(deployTransaction.getNonce().valueOf(), 42); // Sign the transaction diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 011187fdb..0b6d7124f 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -121,7 +121,7 @@ export class SmartContract implements ISmartContract { abi: this.abi }); - const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); + const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); const intent = scIntentFactory.createTransactionIntentForDeploy({ From 19960657790b81950bf33cbc74039d54c5b87b7f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 16 Oct 2023 17:05:11 +0300 Subject: [PATCH 024/275] renamings & adjust delegation factory to sdk-specs --- ...ansactionIntent.ts => draftTransaction.ts} | 2 +- .../delegationTransactionsFactory.spec.ts} | 62 ++++++------- .../delegationTransactionsFactory.ts} | 90 +++++++++---------- .../draftTransactionBuilder.ts} | 8 +- ...tContractTransactionIntentsFactory.spec.ts | 0 .../smartContractTransactionIntentsFactory.ts | 4 +- ...anagementTransactionIntentsFactory.spec.ts | 0 ...okenManagementTransactionIntentsFactory.ts | 4 +- .../transactionIntentsFactoryConfig.ts | 0 9 files changed, 85 insertions(+), 85 deletions(-) rename src/{transactionIntent.ts => draftTransaction.ts} (94%) rename src/{transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts => transactionsFactories/delegationTransactionsFactory.spec.ts} (82%) rename src/{transactionIntentsFactories/delegationTransactionIntentsFactory.ts => transactionsFactories/delegationTransactionsFactory.ts} (83%) rename src/{transactionIntentsFactories/transactionIntentBuilder.ts => transactionsFactories/draftTransactionBuilder.ts} (92%) rename src/{transactionIntentsFactories => transactionsFactories}/smartContractTransactionIntentsFactory.spec.ts (100%) rename src/{transactionIntentsFactories => transactionsFactories}/smartContractTransactionIntentsFactory.ts (97%) rename src/{transactionIntentsFactories => transactionsFactories}/tokenManagementTransactionIntentsFactory.spec.ts (100%) rename src/{transactionIntentsFactories => transactionsFactories}/tokenManagementTransactionIntentsFactory.ts (99%) rename src/{transactionIntentsFactories => transactionsFactories}/transactionIntentsFactoryConfig.ts (100%) diff --git a/src/transactionIntent.ts b/src/draftTransaction.ts similarity index 94% rename from src/transactionIntent.ts rename to src/draftTransaction.ts index 43cb9e36c..5470c44e8 100644 --- a/src/transactionIntent.ts +++ b/src/draftTransaction.ts @@ -1,6 +1,6 @@ import { BigNumber } from "bignumber.js"; -export class TransactionIntent { +export class DraftTransaction { public sender: string; public receiver: string; public gasLimit: BigNumber.Value; diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts similarity index 82% rename from src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts rename to src/transactionsFactories/delegationTransactionsFactory.spec.ts index 34bd7df41..8ebd661c8 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -1,22 +1,22 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; -import { DelegationTransactionIntentsFactory } from "./delegationTransactionIntentsFactory"; +import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { assert } from "chai"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { ValidatorPublicKey } from "@multiversx/sdk-wallet-next"; import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; -describe("test delegation intents factory", function () { +describe("test delegation transactions factory", function () { const config = new TransactionIntentsFactoryConfig("D"); - const delegationFactory = new DelegationTransactionIntentsFactory(config); + const delegationFactory = new DelegationTransactionsFactory(config); - it("should create intent for new delegation contract", async function () { + it("should create draft transaction for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delagationCap = "5000000000000000000000"; const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); - const intent = delegationFactory.createTransactionIntentForNewDelegationContract({ + const intent = delegationFactory.createTransactionForNewDelegationContract({ sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, @@ -31,7 +31,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, value); }); - it("should create intent for adding nodes", async function () { + it("should create draft transaction for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); @@ -40,7 +40,7 @@ describe("test delegation intents factory", function () { getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") } - const intent = delegationFactory.createTransactionIntentForAddingNodes({ + const intent = delegationFactory.createTransactionForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], @@ -54,7 +54,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for removing nodes", async function () { + it("should create draft transaction for removing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -64,7 +64,7 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForRemovingNodes({ + const intent = delegationFactory.createTransactionForRemovingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -77,7 +77,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for staking nodes", async function () { + it("should create draft transaction for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -87,7 +87,7 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForStakingNodes({ + const intent = delegationFactory.createTransactionForStakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -100,7 +100,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for unbonding nodes", async function () { + it("should create draft transaction for unbonding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -110,7 +110,7 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnbondingNodes({ + const intent = delegationFactory.createTransactionForUnbondingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -124,7 +124,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.gasLimit.valueOf(), 12080000); }); - it("should create intent for unstaking nodes", async function () { + it("should create draft transaction for unstaking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -134,7 +134,7 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnstakingNodes({ + const intent = delegationFactory.createTransactionForUnstakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -148,7 +148,7 @@ describe("test delegation intents factory", function () { assert.equal(intent.gasLimit.valueOf(), 12081500); }); - it("should create intent for unjailing nodes", async function () { + it("should create draft transaction for unjailing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -158,7 +158,7 @@ describe("test delegation intents factory", function () { } }; - const intent = delegationFactory.createTransactionIntentForUnjailingNodes({ + const intent = delegationFactory.createTransactionForUnjailingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -171,12 +171,12 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for changing service fee", async function () { + it("should create draft transaction for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const intent = delegationFactory.createTransactionIntentForChangingServiceFee({ + const intent = delegationFactory.createTransactionForChangingServiceFee({ sender: sender, delegationContract: delegationContract, serviceFee: serviceFee @@ -189,12 +189,12 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for changing delegation cap", async function () { + it("should create draft transaction for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const intent = delegationFactory.createTransactionIntentForModifyingDelegationCap({ + const intent = delegationFactory.createTransactionForModifyingDelegationCap({ sender: sender, delegationContract: delegationContract, delegationCap: delegationCap @@ -207,11 +207,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for setting automatic activation", async function () { + it("should create draft transaction for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingAutomaticActivation({ + const intent = delegationFactory.createTransactionForSettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); @@ -223,11 +223,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for unsetting automatic activation", async function () { + it("should create draft transaction for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForUnsettingAutomaticActivation({ + const intent = delegationFactory.createTransactionForUnsettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); @@ -239,11 +239,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for setting cap check on redelegate rewards", async function () { + it("should create draft transaction for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingCapCheckOnRedelegateRewards({ + const intent = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); @@ -255,11 +255,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for unsetting cap check on redelegate rewards", async function () { + it("should create draft transaction for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForUnsettingCapCheckOnRedelegateRewards({ + const intent = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); @@ -271,11 +271,11 @@ describe("test delegation intents factory", function () { assert.equal(intent.value, 0); }); - it("should create intent for setting metadata", async function () { + it("should create draft transaction for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionIntentForSettingMetadata({ + const intent = delegationFactory.createTransactionForSettingMetadata({ sender: sender, delegationContract: delegationContract, name: "name", diff --git a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts similarity index 83% rename from src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts rename to src/transactionsFactories/delegationTransactionsFactory.ts index 1a8cc5be4..b7d164e19 100644 --- a/src/transactionIntentsFactories/delegationTransactionIntentsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,8 +1,8 @@ import { IAddress } from "../interface"; import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { TransactionIntent } from "../transactionIntent"; -import { TransactionIntentBuilder } from "./transactionIntentBuilder"; +import { DraftTransaction } from "../draftTransaction"; +import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; @@ -24,19 +24,19 @@ interface IValidatorPublicKey { hex(): string; } -export class DelegationTransactionIntentsFactory { +export class DelegationTransactionsFactory { private readonly config: Config; constructor(config: Config) { this.config = config; } - createTransactionIntentForNewDelegationContract(options: { + createTransactionForNewDelegationContract(options: { sender: IAddress, totalDelegationCap: BigNumber.Value, serviceFee: BigNumber.Value, value: BigNumber.Value - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), @@ -45,7 +45,7 @@ export class DelegationTransactionIntentsFactory { const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), @@ -56,12 +56,12 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForAddingNodes(options: { + createTransactionForAddingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[], signedMessages: Uint8Array[] - }): TransactionIntent { + }): DraftTransaction { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } @@ -73,7 +73,7 @@ export class DelegationTransactionIntentsFactory { dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -83,11 +83,11 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForRemovingNodes(options: { + createTransactionForRemovingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): TransactionIntent { + }): DraftTransaction { const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { @@ -96,7 +96,7 @@ export class DelegationTransactionIntentsFactory { const numNodes = options.publicKeys.length; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -106,11 +106,11 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForStakingNodes(options: { + createTransactionForStakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): TransactionIntent { + }): DraftTransaction { let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { @@ -123,7 +123,7 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitDelegationOperations ); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -133,11 +133,11 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnbondingNodes(options: { + createTransactionForUnbondingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): TransactionIntent { + }): DraftTransaction { let dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { @@ -150,7 +150,7 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -160,11 +160,11 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnstakingNodes(options: { + createTransactionForUnstakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): TransactionIntent { + }): DraftTransaction { let dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { @@ -177,7 +177,7 @@ export class DelegationTransactionIntentsFactory { this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -187,11 +187,11 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnjailingNodes(options: { + createTransactionForUnjailingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): TransactionIntent { + }): DraftTransaction { const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { @@ -200,7 +200,7 @@ export class DelegationTransactionIntentsFactory { const numNodes = options.publicKeys.length; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -210,17 +210,17 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForChangingServiceFee(options: { + createTransactionForChangingServiceFee(options: { sender: IAddress, delegationContract: IAddress, serviceFee: BigNumber.Value - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -230,17 +230,17 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForModifyingDelegationCap(options: { + createTransactionForModifyingDelegationCap(options: { sender: IAddress, delegationContract: IAddress, delegationCap: BigNumber.Value - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -250,16 +250,16 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingAutomaticActivation(options: { + createTransactionForSettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setAutomaticActivation", utf8ToHex("true") ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -269,16 +269,16 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnsettingAutomaticActivation(options: { + createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setAutomaticActivation", utf8ToHex("false") ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -288,16 +288,16 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingCapCheckOnRedelegateRewards(options: { + createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -307,16 +307,16 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnsettingCapCheckOnRedelegateRewards(options: { + createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -326,13 +326,13 @@ export class DelegationTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingMetadata(options: { + createTransactionForSettingMetadata(options: { sender: IAddress, delegationContract: IAddress, name: string, website: string, identifier: string - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setMetaData", utf8ToHex(options.name), @@ -340,7 +340,7 @@ export class DelegationTransactionIntentsFactory { utf8ToHex(options.identifier) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, diff --git a/src/transactionIntentsFactories/transactionIntentBuilder.ts b/src/transactionsFactories/draftTransactionBuilder.ts similarity index 92% rename from src/transactionIntentsFactories/transactionIntentBuilder.ts rename to src/transactionsFactories/draftTransactionBuilder.ts index 000760173..8fee4d77e 100644 --- a/src/transactionIntentsFactories/transactionIntentBuilder.ts +++ b/src/transactionsFactories/draftTransactionBuilder.ts @@ -2,14 +2,14 @@ import { BigNumber } from "bignumber.js"; import { IAddress, ITransactionPayload } from "../interface"; import { ARGUMENTS_SEPARATOR } from "../constants"; import { TransactionPayload } from "../transactionPayload"; -import { TransactionIntent } from "../transactionIntent"; +import { DraftTransaction } from "../draftTransaction"; interface Config { minGasLimit: BigNumber.Value; gasLimitPerByte: BigNumber.Value; } -export class TransactionIntentBuilder { +export class DraftTransactionBuilder { private config: Config; private sender: IAddress; private receiver: IAddress; @@ -51,11 +51,11 @@ export class TransactionIntentBuilder { return new TransactionPayload(data); } - build(): TransactionIntent { + build(): DraftTransaction { const data = this.buildTransactionPayload() const gasLimit = this.computeGasLimit(data); - return new TransactionIntent({ + return new DraftTransaction({ sender: this.sender.bech32(), receiver: this.receiver.bech32(), gasLimit: gasLimit, diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionIntentsFactory.spec.ts similarity index 100% rename from src/transactionIntentsFactories/smartContractTransactionIntentsFactory.spec.ts rename to src/transactionsFactories/smartContractTransactionIntentsFactory.spec.ts diff --git a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionsFactories/smartContractTransactionIntentsFactory.ts similarity index 97% rename from src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts rename to src/transactionsFactories/smartContractTransactionIntentsFactory.ts index 82e69e7c7..907efc9b5 100644 --- a/src/transactionIntentsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionIntentsFactory.ts @@ -1,13 +1,13 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; -import { TransactionIntent } from "../transactionIntent"; +import { DraftTransaction } from "../draftTransaction"; import { AbiRegistry, ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err } from "../errors"; import { Address } from "../address"; -import { TransactionIntentBuilder } from "./transactionIntentBuilder"; +import { TransactionIntentBuilder } from "./draftTransactionBuilder"; interface Config { chainID: string; diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts similarity index 100% rename from src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.spec.ts rename to src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts diff --git a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts similarity index 99% rename from src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts rename to src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts index 5c6032027..527014bd1 100644 --- a/src/transactionIntentsFactories/tokenManagementTransactionIntentsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts @@ -1,6 +1,6 @@ import BigNumber from "bignumber.js"; -import { TransactionIntent } from "../transactionIntent"; -import { TransactionIntentBuilder } from "./transactionIntentBuilder"; +import { DraftTransaction } from "../draftTransaction"; +import { TransactionIntentBuilder } from "./draftTransactionBuilder"; import { IAddress } from "../interface"; import { utf8ToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; diff --git a/src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts b/src/transactionsFactories/transactionIntentsFactoryConfig.ts similarity index 100% rename from src/transactionIntentsFactories/transactionIntentsFactoryConfig.ts rename to src/transactionsFactories/transactionIntentsFactoryConfig.ts From 9e9b482b7eb1b88807f04cea5544f1c1d0c903a6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 16 Oct 2023 17:26:08 +0300 Subject: [PATCH 025/275] update smart contract transaction --- src/smartcontracts/smartContract.ts | 4 +-- ... smartContractTransactionsFactory.spec.ts} | 32 +++++++++---------- ...ts => smartContractTransactionsFactory.ts} | 24 +++++++------- 3 files changed, 30 insertions(+), 30 deletions(-) rename src/transactionsFactories/{smartContractTransactionIntentsFactory.spec.ts => smartContractTransactionsFactory.spec.ts} (83%) rename src/transactionsFactories/{smartContractTransactionIntentsFactory.ts => smartContractTransactionsFactory.ts} (88%) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 0b6d7124f..75d1d8733 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -14,8 +14,8 @@ import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; import { ArwenVirtualMachine, ContractCallPayloadBuilder, ContractUpgradePayloadBuilder } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; -import { SmartContractTransactionIntentsFactory } from "../transactionIntentsFactories/smartContractTransactionIntentsFactory"; -import { TransactionIntentsFactoryConfig } from "../transactionIntentsFactories/transactionIntentsFactoryConfig"; +import { SmartContractTransactionIntentsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TransactionIntentsFactoryConfig } from "../transactionsFactories/transactionIntentsFactoryConfig"; import { TransactionPayload } from "../transactionPayload"; const createKeccakHash = require("keccak"); diff --git a/src/transactionsFactories/smartContractTransactionIntentsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts similarity index 83% rename from src/transactionsFactories/smartContractTransactionIntentsFactory.spec.ts rename to src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 8f21e42ae..036e039f0 100644 --- a/src/transactionsFactories/smartContractTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -1,5 +1,5 @@ import { assert, expect } from "chai"; -import { SmartContractTransactionIntentsFactory } from "./smartContractTransactionIntentsFactory"; +import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; import { Address } from "../address"; import { Code } from "../smartcontracts/code"; import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; @@ -9,22 +9,22 @@ import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; -describe("test smart contract intents factory", function () { +describe("test smart contract transactions factory", function () { const config = new TransactionIntentsFactoryConfig("D"); - let factory: SmartContractTransactionIntentsFactory; - let abiAwareFactory: SmartContractTransactionIntentsFactory; + let factory: SmartContractTransactionsFactory; + let abiAwareFactory: SmartContractTransactionsFactory; let adderByteCode: Code; let abiRegistry: AbiRegistry; before(async function () { - factory = new SmartContractTransactionIntentsFactory({ + factory = new SmartContractTransactionsFactory({ config: config }); adderByteCode = await loadContractCode("src/testdata/adder.wasm"); abiRegistry = await loadAbiRegistry("src/testdata/adder.abi.json"); - abiAwareFactory = new SmartContractTransactionIntentsFactory({ + abiAwareFactory = new SmartContractTransactionsFactory({ config: config, abi: abiRegistry }, @@ -36,7 +36,7 @@ describe("test smart contract intents factory", function () { const gasLimit = 6000000; const args = [0]; - assert.throws(() => factory.createTransactionIntentForDeploy({ + assert.throws(() => factory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -44,18 +44,18 @@ describe("test smart contract intents factory", function () { }), Err, "Can't convert args to TypedValues"); }); - it("should create intent for deploy", async function () { + it("should create draft transaction for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = factory.createTransactionIntentForDeploy({ + const deployIntent = factory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionIntentForDeploy({ + const abiDeployIntent = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -73,21 +73,21 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should create intent for execute", async function () { + it("should create draft transaction for execute", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; const gasLimit = 6000000; const args = [new U32Value(7)]; - const deployIntent = factory.createTransactionIntentForExecute({ + const deployIntent = factory.createTransactionForExecute({ sender: sender, contractAddress: contract, functionName: func, gasLimit: gasLimit, args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionIntentForExecute({ + const abiDeployIntent = abiAwareFactory.createTransactionForExecute({ sender: sender, contractAddress: contract, functionName: func, @@ -107,13 +107,13 @@ describe("test smart contract intents factory", function () { assert.deepEqual(deployIntent, abiDeployIntent); }); - it("should create intent for upgrade", async function () { + it("should create draft transaction for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = factory.createTransactionIntentForUpgrade({ + const deployIntent = factory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -121,7 +121,7 @@ describe("test smart contract intents factory", function () { args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionIntentForUpgrade({ + const abiDeployIntent = abiAwareFactory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), diff --git a/src/transactionsFactories/smartContractTransactionIntentsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts similarity index 88% rename from src/transactionsFactories/smartContractTransactionIntentsFactory.ts rename to src/transactionsFactories/smartContractTransactionsFactory.ts index 907efc9b5..422075562 100644 --- a/src/transactionsFactories/smartContractTransactionIntentsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -1,13 +1,13 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { DraftTransaction } from "../draftTransaction"; -import { AbiRegistry, ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; +import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err } from "../errors"; import { Address } from "../address"; -import { TransactionIntentBuilder } from "./draftTransactionBuilder"; +import { DraftTransactionBuilder } from "./draftTransactionBuilder"; interface Config { chainID: string; @@ -22,7 +22,7 @@ interface Abi { } -export class SmartContractTransactionIntentsFactory { +export class SmartContractTransactionsFactory { private readonly config: Config; private readonly abiRegistry?: Abi; @@ -37,7 +37,7 @@ export class SmartContractTransactionIntentsFactory { this.abiRegistry = abi; } - createTransactionIntentForDeploy(options: { + createTransactionForDeploy(options: { sender: IAddress, bytecode: Uint8Array, gasLimit: BigNumber.Value, @@ -46,7 +46,7 @@ export class SmartContractTransactionIntentsFactory { isReadable?: boolean, isPayable?: boolean, isPayableBySmartContract?: boolean - }): TransactionIntent { + }): DraftTransaction { const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; @@ -64,7 +64,7 @@ export class SmartContractTransactionIntentsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), @@ -74,21 +74,21 @@ export class SmartContractTransactionIntentsFactory { }).build(); } - createTransactionIntentForExecute(options: { + createTransactionForExecute(options: { sender: IAddress, contractAddress: IAddress, functionName: string, gasLimit: BigNumber.Value, args?: any[] } - ): TransactionIntent { + ): DraftTransaction { const args = options.args || []; let parts: string[] = [options.functionName]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName)); parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.contractAddress, @@ -98,7 +98,7 @@ export class SmartContractTransactionIntentsFactory { }).build(); } - createTransactionIntentForUpgrade(options: { + createTransactionForUpgrade(options: { sender: IAddress, contract: IAddress, bytecode: Uint8Array, @@ -109,7 +109,7 @@ export class SmartContractTransactionIntentsFactory { isPayable?: boolean, isPayableBySmartContract?: boolean } - ): TransactionIntent { + ): DraftTransaction { const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; @@ -127,7 +127,7 @@ export class SmartContractTransactionIntentsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) parts = parts.concat(preparedArgs); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.contract, From c8bf42dc8b50c1ad7c087a577f6c7d02d34060cc Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 12:02:15 +0300 Subject: [PATCH 026/275] update transaction factories --- src/smartcontracts/smartContract.ts | 22 +-- .../delegationTransactionsFactory.spec.ts | 6 +- .../delegationTransactionsFactory.ts | 4 +- .../draftTransactionBuilder.ts | 8 +- .../smartContractTransactionsFactory.spec.ts | 4 +- .../smartContractTransactionsFactory.ts | 12 +- ...anagementTransactionIntentsFactory.spec.ts | 43 ++--- ... => tokenManagementTransactionsFactory.ts} | 164 +++++++++--------- ...Config.ts => transactionsFactoryConfig.ts} | 2 +- 9 files changed, 138 insertions(+), 127 deletions(-) rename src/transactionsFactories/{tokenManagementTransactionIntentsFactory.ts => tokenManagementTransactionsFactory.ts} (81%) rename src/transactionsFactories/{transactionIntentsFactoryConfig.ts => transactionsFactoryConfig.ts} (98%) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 75d1d8733..c569de2d8 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -14,8 +14,8 @@ import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; import { ArwenVirtualMachine, ContractCallPayloadBuilder, ContractUpgradePayloadBuilder } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; -import { SmartContractTransactionIntentsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; -import { TransactionIntentsFactoryConfig } from "../transactionsFactories/transactionIntentsFactoryConfig"; +import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { TransactionPayload } from "../transactionPayload"; const createKeccakHash = require("keccak"); @@ -115,8 +115,8 @@ export class SmartContract implements ISmartContract { deploy({ deployer, code, codeMetadata, initArguments, value, gasLimit, gasPrice, chainID }: DeployArguments): Transaction { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); - const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionIntentsFactory({ + const config = new TransactionsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -124,7 +124,7 @@ export class SmartContract implements ISmartContract { const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const intent = scIntentFactory.createTransactionIntentForDeploy({ + const intent = scIntentFactory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: gasLimit.valueOf(), @@ -177,8 +177,8 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); - const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionIntentsFactory({ + const config = new TransactionsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -186,7 +186,7 @@ export class SmartContract implements ISmartContract { const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const intent = scIntentFactory.createTransactionIntentForUpgrade({ + const intent = scIntentFactory.createTransactionForUpgrade({ sender: caller, contract: this.getAddress(), bytecode: bytecode, @@ -217,8 +217,8 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); - const config = new TransactionIntentsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionIntentsFactory({ + const config = new TransactionsFactoryConfig(chainID.valueOf()); + const scIntentFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -226,7 +226,7 @@ export class SmartContract implements ISmartContract { args = args || []; value = value || 0; - const intent = scIntentFactory.createTransactionIntentForExecute({ + const intent = scIntentFactory.createTransactionForExecute({ sender: caller, contractAddress: receiver ? receiver : this.getAddress(), functionName: func.toString(), diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 8ebd661c8..721f87e7c 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -4,10 +4,10 @@ import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { assert } from "chai"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { ValidatorPublicKey } from "@multiversx/sdk-wallet-next"; -import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; +import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { - const config = new TransactionIntentsFactoryConfig("D"); + const config = new TransactionsFactoryConfig("D"); const delegationFactory = new DelegationTransactionsFactory(config); it("should create draft transaction for new delegation contract", async function () { @@ -20,7 +20,7 @@ describe("test delegation transactions factory", function () { sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, - value: value + amount: value }); assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index b7d164e19..fe7133a01 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -35,7 +35,7 @@ export class DelegationTransactionsFactory { sender: IAddress, totalDelegationCap: BigNumber.Value, serviceFee: BigNumber.Value, - value: BigNumber.Value + amount: BigNumber.Value }): DraftTransaction { const dataParts = [ "createNewDelegationContract", @@ -52,7 +52,7 @@ export class DelegationTransactionsFactory { dataParts: dataParts, gasLimit: executionGasLimit, addDataMovementGas: true, - value: options.value + amount: options.amount }).build(); } diff --git a/src/transactionsFactories/draftTransactionBuilder.ts b/src/transactionsFactories/draftTransactionBuilder.ts index 8fee4d77e..99d57c5a1 100644 --- a/src/transactionsFactories/draftTransactionBuilder.ts +++ b/src/transactionsFactories/draftTransactionBuilder.ts @@ -16,7 +16,7 @@ export class DraftTransactionBuilder { private dataParts: string[]; private providedGasLimit: BigNumber; private addDataMovementGas: boolean; - private value?: BigNumber.Value; + private amount?: BigNumber.Value; constructor(options: { config: Config, @@ -25,7 +25,7 @@ export class DraftTransactionBuilder { dataParts: string[], gasLimit: BigNumber.Value, addDataMovementGas: boolean, - value?: BigNumber.Value + amount?: BigNumber.Value }) { this.config = options.config; this.sender = options.sender; @@ -33,7 +33,7 @@ export class DraftTransactionBuilder { this.dataParts = options.dataParts; this.providedGasLimit = new BigNumber(options.gasLimit); this.addDataMovementGas = options.addDataMovementGas; - this.value = options.value; + this.amount = options.amount; } private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { @@ -59,7 +59,7 @@ export class DraftTransactionBuilder { sender: this.sender.bech32(), receiver: this.receiver.bech32(), gasLimit: gasLimit, - value: this.value || 0, + value: this.amount || 0, data: data.valueOf() }) } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 036e039f0..a10d9e6ff 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -7,10 +7,10 @@ import { U32Value } from "../smartcontracts"; import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; -import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; +import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test smart contract transactions factory", function () { - const config = new TransactionIntentsFactoryConfig("D"); + const config = new TransactionsFactoryConfig("D"); let factory: SmartContractTransactionsFactory; let abiAwareFactory: SmartContractTransactionsFactory; let adderByteCode: Code; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 422075562..b358fc0b8 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -42,11 +42,14 @@ export class SmartContractTransactionsFactory { bytecode: Uint8Array, gasLimit: BigNumber.Value, args?: any[], + nativeTransferAmount?: BigNumber.Value, isUpgradeable?: boolean, isReadable?: boolean, isPayable?: boolean, isPayableBySmartContract?: boolean }): DraftTransaction { + const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; @@ -70,7 +73,8 @@ export class SmartContractTransactionsFactory { receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), dataParts: parts, gasLimit: options.gasLimit, - addDataMovementGas: false + addDataMovementGas: false, + amount: nativeTransferAmount }).build(); } @@ -104,12 +108,15 @@ export class SmartContractTransactionsFactory { bytecode: Uint8Array, gasLimit: BigNumber.Value, args?: any[], + nativeTransferAmount?: BigNumber.Value, isUpgradeable?: boolean, isReadable?: boolean, isPayable?: boolean, isPayableBySmartContract?: boolean } ): DraftTransaction { + const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; @@ -133,7 +140,8 @@ export class SmartContractTransactionsFactory { receiver: options.contract, dataParts: parts, gasLimit: options.gasLimit, - addDataMovementGas: false + addDataMovementGas: false, + amount: nativeTransferAmount }).build(); } diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index b6fa00a1b..5c54f5588 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -1,23 +1,23 @@ import { assert } from "chai"; import { loadTestWallets, TestWallet } from "../testutils"; -import { TokenManagementTransactionIntentsFactory } from "./tokenManagementTransactionIntentsFactory"; -import { TransactionIntentsFactoryConfig } from "./transactionIntentsFactoryConfig"; +import { TokenManagementTransactionsFactory } from "./tokenManagementTransactionsFactory"; +import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import BigNumber from "bignumber.js"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; -describe("test token management transaction intents factory", () => { +describe("test token management transactions factory", () => { let frank: TestWallet, grace: TestWallet; - let factory: TokenManagementTransactionIntentsFactory; - let config: TransactionIntentsFactoryConfig; + let factory: TokenManagementTransactionsFactory; + let config: TransactionsFactoryConfig; before(async function () { ({ frank, grace } = await loadTestWallets()); - config = new TransactionIntentsFactoryConfig("T"); - factory = new TokenManagementTransactionIntentsFactory(config); + config = new TransactionsFactoryConfig("T"); + factory = new TokenManagementTransactionsFactory(config); }); - it("should create transaction intent for registering and setting roles", () => { - const intent = factory.createTransactionIntentForRegisteringAndSettingRoles({ + it("should create draft transaction for registering and setting roles", () => { + const intent = factory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", tokenTicker: "TEST", @@ -32,8 +32,8 @@ describe("test token management transaction intents factory", () => { assert.deepEqual(intent.gasLimit, new BigNumber("60125000")); }); - it("should create transaction intent for issuing fungible token", () => { - const intent = factory.createTransactionIntentForIssuingFungible({ + it("should create draft transaction for issuing fungible token", () => { + const intent = factory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -42,6 +42,7 @@ describe("test token management transaction intents factory", () => { canFreeze: true, canWipe: true, canPause: true, + canTransferNFTCreateRole: false, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true @@ -53,8 +54,8 @@ describe("test token management transaction intents factory", () => { assert.deepEqual(intent.value, config.issueCost); }); - it("should create transaction intent for issuing semi-fungible token", () => { - const intent = factory.createTransactionIntentForIssuingSemiFungible({ + it("should create draft transaction for issuing semi-fungible token", () => { + const intent = factory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -73,8 +74,8 @@ describe("test token management transaction intents factory", () => { assert.deepEqual(intent.value, config.issueCost); }); - it("should create transaction intent for issuing non-fungible token", () => { - const intent = factory.createTransactionIntentForIssuingNonFungible({ + it("should create draft transaction for issuing non-fungible token", () => { + const intent = factory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -93,8 +94,8 @@ describe("test token management transaction intents factory", () => { assert.deepEqual(intent.value, config.issueCost); }); - it("should create transaction intent for registering metaEsdt", () => { - const intent = factory.createTransactionIntentForRegisteringMetaESDT({ + it("should create draft transaction for registering metaEsdt", () => { + const intent = factory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -114,8 +115,8 @@ describe("test token management transaction intents factory", () => { assert.deepEqual(intent.value, config.issueCost); }); - it("should create transaction intent for setting spcial role on non-fungible token", () => { - const intent = factory.createTransactionIntentForSettingSpecialRoleOnNonFungibleToken({ + it("should create draft transaction for setting spcial role on non-fungible token", () => { + const intent = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, tokenIdentifier: "FRANK-11ce3e", @@ -132,8 +133,8 @@ describe("test token management transaction intents factory", () => { assert.equal(intent.value, 0); }); - it("should create transaction intent for creating nft", () => { - const intent = factory.createTransactionIntentForCreatingNFT({ + it("should create draft transaction for creating nft", () => { + const intent = factory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts similarity index 81% rename from src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts rename to src/transactionsFactories/tokenManagementTransactionsFactory.ts index 527014bd1..1dc1709e1 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,6 +1,6 @@ import BigNumber from "bignumber.js"; import { DraftTransaction } from "../draftTransaction"; -import { TransactionIntentBuilder } from "./draftTransactionBuilder"; +import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { IAddress } from "../interface"; import { utf8ToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; @@ -29,7 +29,7 @@ interface Config { type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; -export class TokenManagementTransactionIntentsFactory { +export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly trueAsHex: string; @@ -38,7 +38,7 @@ export class TokenManagementTransactionIntentsFactory { this.trueAsHex = utf8ToHex("true"); } - createTransactionIntentForIssuingFungible(options: { + createTransactionForIssuingFungible(options: { sender: IAddress, tokenName: string, tokenTicker: string, @@ -47,10 +47,11 @@ export class TokenManagementTransactionIntentsFactory { canFreeze: boolean, canWipe: boolean, canPause: boolean, + canTransferNFTCreateRole: boolean, canChangeOwner: boolean, canUpgrade: boolean, canAddSpecialRoles: boolean - }): TransactionIntent { + }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -62,23 +63,24 @@ export class TokenManagementTransactionIntentsFactory { ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), + ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), - ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], + ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - value: this.config.issueCost + amount: this.config.issueCost }).build(); } - createTransactionIntentForIssuingSemiFungible(options: { + createTransactionForIssuingSemiFungible(options: { sender: IAddress; tokenName: string; tokenTicker: string; @@ -89,7 +91,7 @@ export class TokenManagementTransactionIntentsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionIntent { + }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -101,22 +103,22 @@ export class TokenManagementTransactionIntentsFactory { ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), - ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], + ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - value: this.config.issueCost + amount: this.config.issueCost }).build(); } - createTransactionIntentForIssuingNonFungible(options: { + createTransactionForIssuingNonFungible(options: { sender: IAddress; tokenName: string; tokenTicker: string; @@ -127,7 +129,7 @@ export class TokenManagementTransactionIntentsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionIntent { + }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -139,22 +141,22 @@ export class TokenManagementTransactionIntentsFactory { ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), - ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], + ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - value: this.config.issueCost + amount: this.config.issueCost }).build(); } - createTransactionIntentForRegisteringMetaESDT(options: { + createTransactionForRegisteringMetaESDT(options: { sender: IAddress; tokenName: string; tokenTicker: string; @@ -166,7 +168,7 @@ export class TokenManagementTransactionIntentsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionIntent { + }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -183,24 +185,24 @@ export class TokenManagementTransactionIntentsFactory { ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - value: this.config.issueCost + amount: this.config.issueCost }).build(); } - createTransactionIntentForRegisteringAndSettingRoles(options: { + createTransactionForRegisteringAndSettingRoles(options: { sender: IAddress; tokenName: string; tokenTicker: string; tokenType: RegisterAndSetAllRolesTokenType; numDecimals: BigNumber.Value; - }): TransactionIntent { + }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -211,27 +213,27 @@ export class TokenManagementTransactionIntentsFactory { bigIntToHex(options.numDecimals) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - value: this.config.issueCost + amount: this.config.issueCost }).build(); } - createTransactionIntentForSettingBurnRoleGlobally(options: { + createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress, tokenIdentifier: string - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -241,16 +243,16 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnsettingBurnRoleGlobally(options: { + createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress, tokenIdentifier: string - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -260,13 +262,13 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingSpecialRoleOnFungibleToken(options: { + createTransactionForSettingSpecialRoleOnFungibleToken(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; addRoleLocalMint: boolean; addRoleLocalBurn: boolean; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -275,7 +277,7 @@ export class TokenManagementTransactionIntentsFactory { ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -285,7 +287,7 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingSpecialRoleOnSemiFungibleToken(options: { + createTransactionForSettingSpecialRoleOnSemiFungibleToken(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; @@ -293,7 +295,7 @@ export class TokenManagementTransactionIntentsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -304,7 +306,7 @@ export class TokenManagementTransactionIntentsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -314,7 +316,7 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForSettingSpecialRoleOnMetaESDT(options: { + createTransactionForSettingSpecialRoleOnMetaESDT(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; @@ -322,11 +324,11 @@ export class TokenManagementTransactionIntentsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): TransactionIntent { - return this.createTransactionIntentForSettingSpecialRoleOnSemiFungibleToken(options); + }): DraftTransaction { + return this.createTransactionForSettingSpecialRoleOnSemiFungibleToken(options); } - createTransactionIntentForSettingSpecialRoleOnNonFungibleToken(options: { + createTransactionForSettingSpecialRoleOnNonFungibleToken(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; @@ -335,7 +337,7 @@ export class TokenManagementTransactionIntentsFactory { addRoleNFTUpdateAttributes: boolean; addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -347,7 +349,7 @@ export class TokenManagementTransactionIntentsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -357,7 +359,7 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForCreatingNFT(options: { + createTransactionForCreatingNFT(options: { sender: IAddress; tokenIdentifier: string; initialQuantity: BigNumber.Value; @@ -366,7 +368,7 @@ export class TokenManagementTransactionIntentsFactory { hash: string; attributes: Uint8Array; uris: string[]; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), @@ -382,7 +384,7 @@ export class TokenManagementTransactionIntentsFactory { const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -392,16 +394,16 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForPausing(options: { + createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "pause", utf8ToHex(options.tokenIdentifier) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -411,16 +413,16 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnpausing(options: { + createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "unPause", utf8ToHex(options.tokenIdentifier) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -430,18 +432,18 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForFreezing(options: { + createTransactionForFreezing(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -451,18 +453,18 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForUnfreezing(options: { + createTransactionForUnfreezing(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -472,18 +474,18 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForWiping(options: { + createTransactionForWiping(options: { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -493,18 +495,18 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForLocalMint(options: { + createTransactionForLocalMint(options: { sender: IAddress; tokenIdentifier: string; supplyToMint: BigNumber.Value; - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -514,18 +516,18 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForLocalBurning(options: { + createTransactionForLocalBurning(options: { sender: IAddress; tokenIdentifier: string; - supplyToMint: BigNumber.Value; - }): TransactionIntent { + supplyToBurn: BigNumber.Value; + }): DraftTransaction { const dataParts = [ "ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.supplyToMint), + bigIntToHex(options.supplyToBurn), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -535,12 +537,12 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForUpdatingAttributes(options: { + createTransactionForUpdatingAttributes(options: { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; attributes: Uint8Array - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), @@ -548,7 +550,7 @@ export class TokenManagementTransactionIntentsFactory { byteArrayToHex(options.attributes), ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -558,12 +560,12 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForAddingQuantity(options: { + createTransactionForAddingQuantity(options: { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), @@ -571,7 +573,7 @@ export class TokenManagementTransactionIntentsFactory { bigIntToHex(options.quantityToAdd) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -581,12 +583,12 @@ export class TokenManagementTransactionIntentsFactory { }).build(); } - createTransactionIntentForBurningQuantity(options: { + createTransactionForBurningQuantity(options: { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value - }): TransactionIntent { + }): DraftTransaction { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), @@ -594,7 +596,7 @@ export class TokenManagementTransactionIntentsFactory { bigIntToHex(options.quantityToBurn) ]; - return new TransactionIntentBuilder({ + return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, diff --git a/src/transactionsFactories/transactionIntentsFactoryConfig.ts b/src/transactionsFactories/transactionsFactoryConfig.ts similarity index 98% rename from src/transactionsFactories/transactionIntentsFactoryConfig.ts rename to src/transactionsFactories/transactionsFactoryConfig.ts index d8d1c9c94..b3dca70f2 100644 --- a/src/transactionsFactories/transactionIntentsFactoryConfig.ts +++ b/src/transactionsFactories/transactionsFactoryConfig.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { DEFAULT_HRP } from "../constants"; -export class TransactionIntentsFactoryConfig { +export class TransactionsFactoryConfig { chainID: string; addressHrp: string; minGasLimit: BigNumber.Value; From 01ce4848fc21732f085babe99f9c7d62e83c8125 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 12:49:54 +0300 Subject: [PATCH 027/275] add new method to create Transaction from DraftTransaction --- src/transaction.spec.ts | 19 +++++++++++++++++++ src/transaction.ts | 15 +++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 52dd1f75b..1598133ee 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -6,6 +6,7 @@ import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +import { DraftTransaction } from "./draftTransaction"; describe("test transaction construction", async () => { @@ -17,6 +18,24 @@ describe("test transaction construction", async () => { wallets = await loadTestWallets(); }); + it.only("create transaction from draft transaction", async () => { + const draftTransaction = new DraftTransaction({ + sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + gasLimit: 56000, + value: "1000000000000000000", + data: Buffer.from("test") + }); + + const transaction = Transaction.fromDraft(draftTransaction); + assert.deepEqual(transaction.getSender(), Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")); + assert.deepEqual(transaction.getReceiver(), Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx")); + assert.equal(transaction.getGasLimit().valueOf(), 56000); + assert.equal(transaction.getValue().toString(), "1000000000000000000"); + assert.equal(transaction.getData().toString(), "test"); + assert.equal(transaction.getChainID().valueOf(), ""); + }); + it("with no data, no value", async () => { let transaction = new Transaction({ nonce: 89, diff --git a/src/transaction.ts b/src/transaction.ts index 092aae7df..01b947b2d 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -11,6 +11,7 @@ import { ProtoSerializer } from "./proto"; import { Signature } from "./signature"; import { TransactionPayload } from "./transactionPayload"; import { guardNotEmpty } from "./utils"; +import { DraftTransaction } from "./draftTransaction"; const createTransactionHasher = require("blake2b"); const TRANSACTION_HASH_LENGTH = 32; @@ -152,6 +153,20 @@ export class Transaction { this.hash = TransactionHash.empty(); } + /** + * Creates a new Transaction object from a DraftTransaction. + */ + static fromDraft(draft: DraftTransaction): Transaction { + return new Transaction({ + sender: Address.fromBech32(draft.sender), + receiver: Address.fromBech32(draft.receiver), + gasLimit: new BigNumber(draft.gasLimit).toNumber(), + chainID: "", + value: draft.value ?? 0, + data: draft.data ? new TransactionPayload(Buffer.from(draft.data)) : new TransactionPayload() + }) + } + getNonce(): INonce { return this.nonce; } From 55176ad68124428ca3cedb9bffe22a06e6bcac5e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 14:42:59 +0300 Subject: [PATCH 028/275] add Token, TokenTransfer and TokenComputer --- src/errors.ts | 6 +++++ src/tokens.ts | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/tokens.ts diff --git a/src/errors.ts b/src/errors.ts index 80d052dbe..185d21466 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -331,3 +331,9 @@ export class ErrIsCompletedFieldIsMissingOnTransaction extends Err { super("The transaction watcher requires the `isCompleted` property to be defined on the transaction object. Perhaps you've used the sdk-network-provider's `ProxyNetworkProvider.getTransaction()` and in that case you should also pass `withProcessStatus=true`.") } } + +export class ErrInvalidTokenIdentifier extends Err { + public constructor(message: string) { + super(message); + } +} diff --git a/src/tokens.ts b/src/tokens.ts new file mode 100644 index 000000000..9d1f6f1f8 --- /dev/null +++ b/src/tokens.ts @@ -0,0 +1,70 @@ +import BigNumber from "bignumber.js"; +import { ErrInvalidTokenIdentifier } from "./errors"; + +export class Token { + identifier: string; + nonce: BigNumber.Value; + + constructor(identifier: string, nonce: BigNumber.Value) { + this.identifier = identifier; + this.nonce = nonce; + } +} + +export class TokenTransfer { + token: Token; + amount: BigNumber.Value + + constructor(token: Token, amount: BigNumber.Value) { + this.token = token; + this.amount = amount; + } +} + +export class TokenComputer { + constructor() { } + + isFungible(token: Token): boolean { + return token.nonce === 0; + } + + extractNonceFromExtendedIdentifier(identifier: string): number { + const parts = identifier.split("-"); + + this.checkIfExtendedIdentifierWasProvided(parts); + this.checkLengthOfRandomSequence(parts[1]); + + const hexNonce = Buffer.from(parts[2], 'hex'); + return decodeUnsignedNumber(hexNonce); + } + + extractIdentifierFromExtendedIdentifier(identifier: string): string { + const parts = identifier.split("-"); + + this.checkIfExtendedIdentifierWasProvided(parts); + this.checkLengthOfRandomSequence(parts[1]); + + return parts[0] + "-" + parts[1]; + } + + private checkIfExtendedIdentifierWasProvided(tokenParts: string[]): void { + const EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3; + + if (tokenParts.length !== EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { + throw new ErrInvalidTokenIdentifier("You have not provided the extended identifier"); + } + } + + private checkLengthOfRandomSequence(randomSequence: string): void { + const TOKEN_RANDOM_SEQUENCE_LENGTH = 6; + + if (randomSequence.length !== TOKEN_RANDOM_SEQUENCE_LENGTH) { + throw new ErrInvalidTokenIdentifier("The identifier is not valid. The random sequence does not have the right length"); + } + } +} + +function decodeUnsignedNumber(arg: Buffer): number { + return arg.readUIntBE(0, arg.length); +} + From 10601a2f05544b0194a1b0d4ac0a098e3d0c71fd Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 15:19:41 +0300 Subject: [PATCH 029/275] add unit tests for TransactionComputer --- src/tokens.spec.ts | 26 ++++++++++++++++++++++++++ src/transaction.spec.ts | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/tokens.spec.ts diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts new file mode 100644 index 000000000..f5c4ddf63 --- /dev/null +++ b/src/tokens.spec.ts @@ -0,0 +1,26 @@ +import { Token, TokenTransfer, TokenComputer } from "./tokens"; +import { assert } from "chai"; + +describe("test token computer", async () => { + const tokenComputer = new TokenComputer(); + + it("should test if token is fungible", async () => { + const fungibleToken = new Token("TEST-123456", 0); + const nonFungibleToken = new Token("NFT-987654", 7); + + assert.equal(tokenComputer.isFungible(fungibleToken), true); + assert.equal(tokenComputer.isFungible(nonFungibleToken), false); + }); + + it("should extract nonce from extended identifier", async () => { + const extendedIdentifier = "TEST-123456-0a"; + const nonce = tokenComputer.extractNonceFromExtendedIdentifier(extendedIdentifier); + assert.equal(nonce, 10); + }) + + it("should extract identifier from extended identifier", async () => { + const extendedIdentifier = "TEST-123456-0a"; + const identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(extendedIdentifier); + assert.equal(identifier, "TEST-123456"); + }) +}); diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 1598133ee..8d6358527 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -18,7 +18,7 @@ describe("test transaction construction", async () => { wallets = await loadTestWallets(); }); - it.only("create transaction from draft transaction", async () => { + it("create transaction from draft transaction", async () => { const draftTransaction = new DraftTransaction({ sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", From 28d91df443411c24faf8faea997e185e7850ae2c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 15:21:36 +0300 Subject: [PATCH 030/275] remove only from test --- src/transaction.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 1598133ee..8d6358527 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -18,7 +18,7 @@ describe("test transaction construction", async () => { wallets = await loadTestWallets(); }); - it.only("create transaction from draft transaction", async () => { + it("create transaction from draft transaction", async () => { const draftTransaction = new DraftTransaction({ sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", From c0c1daee7040433715a5312abe7b248639f51a8f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 16:01:07 +0300 Subject: [PATCH 031/275] add method parameters --- src/errors.ts | 6 ++++++ .../smartContractTransactionsFactory.ts | 17 +++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index 185d21466..12282114f 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -337,3 +337,9 @@ export class ErrInvalidTokenIdentifier extends Err { super(message); } } + +export class ErrBadUsage extends Err { + public constructor(message: string) { + super(message); + } +} diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index b358fc0b8..409b3bf79 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -5,9 +5,10 @@ import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } fro import { byteArrayToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; -import { Err } from "../errors"; +import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; +import { TokenTransfer } from "../tokenTransfer"; interface Config { chainID: string; @@ -83,9 +84,14 @@ export class SmartContractTransactionsFactory { contractAddress: IAddress, functionName: string, gasLimit: BigNumber.Value, - args?: any[] - } - ): DraftTransaction { + args?: any[], + nativeTokenTransfer?: BigNumber.Value, + tokenTransfers?: TokenTransfer[] + }): DraftTransaction { + if (options.nativeTokenTransfer && options.tokenTransfers?.length) { + throw new ErrBadUsage("Can't send both native token and ESDT/NFT tokens"); + } + const args = options.args || []; let parts: string[] = [options.functionName]; @@ -113,8 +119,7 @@ export class SmartContractTransactionsFactory { isReadable?: boolean, isPayable?: boolean, isPayableBySmartContract?: boolean - } - ): DraftTransaction { + }): DraftTransaction { const nativeTransferAmount = options.nativeTransferAmount ?? 0; const isUpgradeable = options.isUpgradeable ?? true; From ebf9063c745acc29740a5f1f6098b6cd9e1f2424 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 17 Oct 2023 17:19:26 +0300 Subject: [PATCH 032/275] fixes after review --- src/smartcontracts/interaction.spec.ts | 14 +- src/smartcontracts/smartContract.ts | 58 +++--- .../delegationTransactionsFactory.spec.ts | 174 +++++++++--------- .../smartContractTransactionsFactory.spec.ts | 54 +++--- ...anagementTransactionIntentsFactory.spec.ts | 86 ++++----- 5 files changed, 190 insertions(+), 196 deletions(-) diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 2fb119d16..9c43dae9f 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -33,6 +33,7 @@ describe("test smart contract interactor", function () { let interaction = new Interaction(contract, dummyFunction, []); let transaction = interaction + .withSender(alice.address) .withNonce(7) .withValue(TokenTransfer.egldFromAmount(1)) .withGasLimit(20000000) @@ -63,6 +64,7 @@ describe("test smart contract interactor", function () { // ESDT, single let transaction = new Interaction(contract, dummyFunction, []) + .withSender(alice) .withSingleESDTTransfer(TokenFoo(10)) .buildTransaction(); @@ -180,7 +182,7 @@ describe("test smart contract interactor", function () { assert.isTrue(queryCode.equals(ReturnCode.Ok)); // Execute, do not wait for execution - let transaction = interaction.withNonce(0).buildTransaction(); + let transaction = interaction.withSender(alice.address).withNonce(0).buildTransaction(); transaction.setSender(alice.address); await alice.signer.sign(transaction); await provider.sendTransaction(transaction); @@ -235,7 +237,7 @@ describe("test smart contract interactor", function () { assert.deepEqual(counterValue!.valueOf(), new BigNumber(7)); - let incrementTransaction = incrementInteraction.withNonce(14).buildTransaction(); + let incrementTransaction = incrementInteraction.withSender(alice.address).withNonce(14).buildTransaction(); await alice.signer.sign(incrementTransaction); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@08"); let { bundle: { firstValue: valueAfterIncrement } } = await controller.execute(incrementInteraction, incrementTransaction); @@ -243,7 +245,7 @@ describe("test smart contract interactor", function () { // Decrement three times (simulate three parallel broadcasts). Wait for execution of the latter (third transaction). Return fake "5". // Decrement #1 - let decrementTransaction = decrementInteraction.withNonce(15).buildTransaction(); + let decrementTransaction = decrementInteraction.withSender(alice.address).withNonce(15).buildTransaction(); await alice.signer.sign(decrementTransaction); await provider.sendTransaction(decrementTransaction); // Decrement #2 @@ -292,7 +294,7 @@ describe("test smart contract interactor", function () { ); // start() - let startTransaction = startInteraction.withNonce(14).buildTransaction(); + let startTransaction = startInteraction.withSender(alice.address).withNonce(14).buildTransaction(); await alice.signer.sign(startTransaction); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b"); let { bundle: { returnCode: startReturnCode, values: startReturnValues } } = await controller.execute(startInteraction, startTransaction); @@ -302,7 +304,7 @@ describe("test smart contract interactor", function () { assert.lengthOf(startReturnValues, 0); // status() (this is a view function, but for the sake of the test, we'll execute it) - let statusTransaction = statusInteraction.withNonce(15).buildTransaction(); + let statusTransaction = statusInteraction.withSender(alice.address).withNonce(15).buildTransaction(); await alice.signer.sign(statusTransaction); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@01"); let { bundle: { returnCode: statusReturnCode, values: statusReturnValues, firstValue: statusFirstValue } } = await controller.execute(statusInteraction, statusTransaction); @@ -313,7 +315,7 @@ describe("test smart contract interactor", function () { assert.deepEqual(statusFirstValue!.valueOf(), { name: "Running", fields: [] }); // lotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) - let getLotteryInfoTransaction = getLotteryInfoInteraction.withNonce(15).buildTransaction(); + let getLotteryInfoTransaction = getLotteryInfoInteraction.withSender(alice.address).withNonce(15).buildTransaction(); await alice.signer.sign(getLotteryInfoTransaction); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@0000000b6c75636b792d746f6b656e000000010100000000000000005fc2b9dbffffffff00000001640000000a140ec80fa7ee88000000"); let { bundle: { returnCode: infoReturnCode, values: infoReturnValues, firstValue: infoFirstValue } } = await controller.execute(getLotteryInfoInteraction, getLotteryInfoTransaction); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index c569de2d8..58005cbd2 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -17,6 +17,7 @@ import { EndpointDefinition, TypedValue } from "./typesystem"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { TransactionPayload } from "../transactionPayload"; +import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; const createKeccakHash = require("keccak"); interface IAbi { @@ -116,7 +117,7 @@ export class SmartContract implements ISmartContract { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionsFactory({ + const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -124,7 +125,7 @@ export class SmartContract implements ISmartContract { const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const intent = scIntentFactory.createTransactionForDeploy({ + const draftTx = scDraftTransactionFactory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: gasLimit.valueOf(), @@ -135,15 +136,12 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }); - return new Transaction({ - receiver: Address.fromBech32(intent.receiver), - sender: Address.fromBech32(intent.sender), - value: value, - gasLimit: new BigNumber(intent.gasLimit).toNumber(), - gasPrice: gasPrice, - data: new TransactionPayload(Buffer.from(intent.data!)), - chainID: chainID - }); + let transaction = Transaction.fromDraft(draftTx); + transaction.setChainID(chainID); + transaction.setValue(value ?? 0); + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + + return transaction; } private getMetadataPropertiesAsObject(codeMetadata?: ICodeMetadata): { @@ -178,7 +176,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionsFactory({ + const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -186,7 +184,7 @@ export class SmartContract implements ISmartContract { const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const intent = scIntentFactory.createTransactionForUpgrade({ + const draftTx = scDraftTransactionFactory.createTransactionForUpgrade({ sender: caller, contract: this.getAddress(), bytecode: bytecode, @@ -198,15 +196,12 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }) - return new Transaction({ - sender: Address.fromBech32(intent.sender), - receiver: Address.fromBech32(intent.receiver), - value: value, - gasLimit: new BigNumber(intent.gasLimit).toNumber(), - gasPrice: gasPrice, - data: new TransactionPayload(Buffer.from(intent.data!)), - chainID: chainID - }); + let transaction = Transaction.fromDraft(draftTx); + transaction.setChainID(chainID); + transaction.setValue(value ?? 0); + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + + return transaction; } /** @@ -218,7 +213,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scIntentFactory = new SmartContractTransactionsFactory({ + const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi }); @@ -226,7 +221,7 @@ export class SmartContract implements ISmartContract { args = args || []; value = value || 0; - const intent = scIntentFactory.createTransactionForExecute({ + const draftTx = scDraftTransactionFactory.createTransactionForExecute({ sender: caller, contractAddress: receiver ? receiver : this.getAddress(), functionName: func.toString(), @@ -234,15 +229,12 @@ export class SmartContract implements ISmartContract { args: args }) - return new Transaction({ - sender: caller, - receiver: Address.fromBech32(intent.receiver), - value: value, - gasLimit: new BigNumber(intent.gasLimit).toNumber(), - gasPrice: gasPrice, - data: new TransactionPayload(Buffer.from(intent.data!)), - chainID: chainID - }); + let transaction = Transaction.fromDraft(draftTx); + transaction.setChainID(chainID); + transaction.setValue(value); + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + + return transaction; } createQuery({ func, args, value, caller }: QueryArguments): Query { diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 721f87e7c..1afc908aa 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -16,19 +16,19 @@ describe("test delegation transactions factory", function () { const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); - const intent = delegationFactory.createTransactionForNewDelegationContract({ + const draft = delegationFactory.createTransactionForNewDelegationContract({ sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, amount: value }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, DELEGATION_MANAGER_SC_ADDRESS); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); - assert.equal(intent.gasLimit.valueOf(), 60126500); - assert.equal(intent.value, value); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, DELEGATION_MANAGER_SC_ADDRESS); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); + assert.equal(draft.gasLimit.valueOf(), 60126500); + assert.equal(draft.value, value); }); it("should create draft transaction for adding nodes", async function () { @@ -40,18 +40,18 @@ describe("test delegation transactions factory", function () { getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") } - const intent = delegationFactory.createTransactionForAddingNodes({ + const draft = delegationFactory.createTransactionForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], signedMessages: [mockMessage.getSignature()] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); + assert.equal(draft.value, 0); }); it("should create draft transaction for removing nodes", async function () { @@ -64,17 +64,17 @@ describe("test delegation transactions factory", function () { } }; - const intent = delegationFactory.createTransactionForRemovingNodes({ + const draft = delegationFactory.createTransactionForRemovingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("removeNodes@61626261")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("removeNodes@61626261")); + assert.equal(draft.value, 0); }); it("should create draft transaction for staking nodes", async function () { @@ -87,17 +87,17 @@ describe("test delegation transactions factory", function () { } }; - const intent = delegationFactory.createTransactionForStakingNodes({ + const draft = delegationFactory.createTransactionForStakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("stakeNodes@61626261")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("stakeNodes@61626261")); + assert.equal(draft.value, 0); }); it("should create draft transaction for unbonding nodes", async function () { @@ -110,18 +110,18 @@ describe("test delegation transactions factory", function () { } }; - const intent = delegationFactory.createTransactionForUnbondingNodes({ + const draft = delegationFactory.createTransactionForUnbondingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unBondNodes@61626261")); - assert.equal(intent.value, 0); - assert.equal(intent.gasLimit.valueOf(), 12080000); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("unBondNodes@61626261")); + assert.equal(draft.value, 0); + assert.equal(draft.gasLimit.valueOf(), 12080000); }); it("should create draft transaction for unstaking nodes", async function () { @@ -134,18 +134,18 @@ describe("test delegation transactions factory", function () { } }; - const intent = delegationFactory.createTransactionForUnstakingNodes({ + const draft = delegationFactory.createTransactionForUnstakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unStakeNodes@61626261")); - assert.equal(intent.value, 0); - assert.equal(intent.gasLimit.valueOf(), 12081500); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("unStakeNodes@61626261")); + assert.equal(draft.value, 0); + assert.equal(draft.gasLimit.valueOf(), 12081500); }); it("should create draft transaction for unjailing nodes", async function () { @@ -158,17 +158,17 @@ describe("test delegation transactions factory", function () { } }; - const intent = delegationFactory.createTransactionForUnjailingNodes({ + const draft = delegationFactory.createTransactionForUnjailingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("unJailNodes@61626261")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("unJailNodes@61626261")); + assert.equal(draft.value, 0); }); it("should create draft transaction for changing service fee", async function () { @@ -176,17 +176,17 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const intent = delegationFactory.createTransactionForChangingServiceFee({ + const draft = delegationFactory.createTransactionForChangingServiceFee({ sender: sender, delegationContract: delegationContract, serviceFee: serviceFee }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("changeServiceFee@0a")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("changeServiceFee@0a")); + assert.equal(draft.value, 0); }); it("should create draft transaction for changing delegation cap", async function () { @@ -194,88 +194,88 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const intent = delegationFactory.createTransactionForModifyingDelegationCap({ + const draft = delegationFactory.createTransactionForModifyingDelegationCap({ sender: sender, delegationContract: delegationContract, delegationCap: delegationCap }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); + assert.equal(draft.value, 0); }); it("should create draft transaction for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionForSettingAutomaticActivation({ + const draft = delegationFactory.createTransactionForSettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("setAutomaticActivation@74727565")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("setAutomaticActivation@74727565")); + assert.equal(draft.value, 0); }); it("should create draft transaction for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionForUnsettingAutomaticActivation({ + const draft = delegationFactory.createTransactionForUnsettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("setAutomaticActivation@66616c7365")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("setAutomaticActivation@66616c7365")); + assert.equal(draft.value, 0); }); it("should create draft transaction for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ + const draft = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); + assert.equal(draft.value, 0); }); it("should create draft transaction for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ + const draft = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); + assert.equal(draft.value, 0); }); it("should create draft transaction for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const intent = delegationFactory.createTransactionForSettingMetadata({ + const draft = delegationFactory.createTransactionForSettingMetadata({ sender: sender, delegationContract: delegationContract, name: "name", @@ -283,10 +283,10 @@ describe("test delegation transactions factory", function () { identifier: "identifier" }); - assert.equal(intent.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(intent.data); - assert.deepEqual(intent.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); - assert.equal(intent.value, 0); + assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(draft.data); + assert.deepEqual(draft.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); + assert.equal(draft.value, 0); }); }); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index a10d9e6ff..874845fff 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -49,28 +49,28 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = factory.createTransactionForDeploy({ + const deployDraft = factory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionForDeploy({ + const abiDeployDraft = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args }); - assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(deployIntent.receiver, CONTRACT_DEPLOY_ADDRESS); - assert.isDefined(deployIntent.data); - expect(deployIntent.data!.length).to.be.greaterThan(0); + assert.equal(deployDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(deployDraft.receiver, CONTRACT_DEPLOY_ADDRESS); + assert.isDefined(deployDraft.data); + expect(deployDraft.data!.length).to.be.greaterThan(0); - assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); - assert.equal(deployIntent.value, 0); + assert.equal(deployDraft.gasLimit.valueOf(), gasLimit); + assert.equal(deployDraft.value, 0); - assert.deepEqual(deployIntent, abiDeployIntent); + assert.deepEqual(deployDraft, abiDeployDraft); }); it("should create draft transaction for execute", async function () { @@ -80,14 +80,14 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const deployIntent = factory.createTransactionForExecute({ + const executeDraft = factory.createTransactionForExecute({ sender: sender, contractAddress: contract, functionName: func, gasLimit: gasLimit, args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionForExecute({ + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, contractAddress: contract, functionName: func, @@ -95,16 +95,16 @@ describe("test smart contract transactions factory", function () { args: args }); - assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isDefined(deployIntent.data); - assert.deepEqual(deployIntent.data, Buffer.from("add@07")); + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); - assert.equal(deployIntent.value, 0); + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value, 0); - assert.deepEqual(deployIntent, abiDeployIntent); + assert.deepEqual(executeDraft, abiExecuteDraft); }); it("should create draft transaction for upgrade", async function () { @@ -113,7 +113,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployIntent = factory.createTransactionForUpgrade({ + const upgradeDraft = factory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -121,7 +121,7 @@ describe("test smart contract transactions factory", function () { args: args }); - const abiDeployIntent = abiAwareFactory.createTransactionForUpgrade({ + const abiUpgradeDraft = abiAwareFactory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -129,14 +129,14 @@ describe("test smart contract transactions factory", function () { args: args }); - assert.equal(deployIntent.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(deployIntent.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isDefined(deployIntent.data); - assert.isTrue(Buffer.from(deployIntent.data!).toString().startsWith("upgradeContract@")); + assert.equal(upgradeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(upgradeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.isDefined(upgradeDraft.data); + assert.isTrue(Buffer.from(upgradeDraft.data!).toString().startsWith("upgradeContract@")); - assert.equal(deployIntent.gasLimit.valueOf(), gasLimit); - assert.equal(deployIntent.value, 0); + assert.equal(upgradeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(upgradeDraft.value, 0); - assert.deepEqual(deployIntent, abiDeployIntent); + assert.deepEqual(upgradeDraft, abiUpgradeDraft); }); }); diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 5c54f5588..01b495068 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -16,8 +16,8 @@ describe("test token management transactions factory", () => { factory = new TokenManagementTransactionsFactory(config); }); - it("should create draft transaction for registering and setting roles", () => { - const intent = factory.createTransactionForRegisteringAndSettingRoles({ + it("should create draft transaction for registering and setting roles", () => { + const draft = factory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", tokenTicker: "TEST", @@ -25,15 +25,15 @@ describe("test token management transactions factory", () => { numDecimals: 2 }); - assert.deepEqual(intent.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); - assert.deepEqual(intent.value, config.issueCost); - assert.deepEqual(intent.gasLimit, new BigNumber("60125000")); + assert.deepEqual(draft.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); + assert.deepEqual(draft.value, config.issueCost); + assert.deepEqual(draft.gasLimit, new BigNumber("60125000")); }); - it("should create draft transaction for issuing fungible token", () => { - const intent = factory.createTransactionForIssuingFungible({ + it("should create draft transaction for issuing fungible token", () => { + const draft = factory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -48,14 +48,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: true }); - assert.deepEqual(intent.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(intent.value, config.issueCost); + assert.deepEqual(draft.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(draft.value, config.issueCost); }); - it("should create draft transaction for issuing semi-fungible token", () => { - const intent = factory.createTransactionForIssuingSemiFungible({ + it("should create draft transaction for issuing semi-fungible token", () => { + const draft = factory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -68,14 +68,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: true }); - assert.deepEqual(intent.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(intent.value, config.issueCost); + assert.deepEqual(draft.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(draft.value, config.issueCost); }); - it("should create draft transaction for issuing non-fungible token", () => { - const intent = factory.createTransactionForIssuingNonFungible({ + it("should create draft transaction for issuing non-fungible token", () => { + const draft = factory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -88,14 +88,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: true }); - assert.deepEqual(intent.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(intent.value, config.issueCost); + assert.deepEqual(draft.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(draft.value, config.issueCost); }); - it("should create draft transaction for registering metaEsdt", () => { - const intent = factory.createTransactionForRegisteringMetaESDT({ + it("should create draft transaction for registering metaEsdt", () => { + const draft = factory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -109,14 +109,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: true }); - assert.deepEqual(intent.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(intent.value, config.issueCost); + assert.deepEqual(draft.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(draft.value, config.issueCost); }); - it("should create draft transaction for setting spcial role on non-fungible token", () => { - const intent = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ + it("should create draft transaction for setting spcial role on non-fungible token", () => { + const draft = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, tokenIdentifier: "FRANK-11ce3e", @@ -127,14 +127,14 @@ describe("test token management transactions factory", () => { addRoleESDTTransferRole: false }); - assert.deepEqual(intent.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); - assert.equal(intent.sender, frank.address.toString()); - assert.equal(intent.receiver, ESDT_CONTRACT_ADDRESS); - assert.equal(intent.value, 0); + assert.deepEqual(draft.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); + assert.equal(draft.sender, frank.address.toString()); + assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); + assert.equal(draft.value, 0); }); - it("should create draft transaction for creating nft", () => { - const intent = factory.createTransactionForCreatingNFT({ + it("should create draft transaction for creating nft", () => { + const draft = factory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, @@ -145,9 +145,9 @@ describe("test token management transactions factory", () => { uris: ["a", "b"] }); - assert.deepEqual(intent.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); - assert.equal(intent.sender, grace.address.toString()); - assert.equal(intent.receiver, grace.address.toString()); - assert.equal(intent.value, 0); + assert.deepEqual(draft.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); + assert.equal(draft.sender, grace.address.toString()); + assert.equal(draft.receiver, grace.address.toString()); + assert.equal(draft.value, 0); }); }); From 41538accbedfc172c404a5831210c3e761fd4c82 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 23 Oct 2023 10:58:07 +0300 Subject: [PATCH 033/275] default value for draft transaction properties --- src/draftTransaction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/draftTransaction.ts b/src/draftTransaction.ts index 5470c44e8..f1554af79 100644 --- a/src/draftTransaction.ts +++ b/src/draftTransaction.ts @@ -17,7 +17,7 @@ export class DraftTransaction { this.sender = options.sender; this.receiver = options.receiver; this.gasLimit = options.gasLimit; - this.value = options.value; - this.data = options.data; + this.value = options.value ?? 0; + this.data = options.data ?? new Uint8Array(); } } From 6cf25b0f0ee68305097216d6980478b67578d1df Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 23 Oct 2023 16:57:22 +0300 Subject: [PATCH 034/275] fixes --- src/draftTransaction.ts | 4 ++-- src/smartcontracts/smartContract.ts | 6 +++--- src/transaction.spec.ts | 4 ++++ src/transaction.ts | 8 ++++---- .../tokenManagementTransactionsFactory.ts | 14 +++++++------- src/utils.codec.ts | 4 ++++ 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/draftTransaction.ts b/src/draftTransaction.ts index f1554af79..25dcfc0d5 100644 --- a/src/draftTransaction.ts +++ b/src/draftTransaction.ts @@ -4,8 +4,8 @@ export class DraftTransaction { public sender: string; public receiver: string; public gasLimit: BigNumber.Value; - public value?: BigNumber.Value; - public data?: Uint8Array; + public value: BigNumber.Value; + public data: Uint8Array; public constructor(options: { sender: string, diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 58005cbd2..b5908d2cb 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -136,7 +136,7 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }); - let transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromDraft(draftTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -196,7 +196,7 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }) - let transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromDraft(draftTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -229,7 +229,7 @@ export class SmartContract implements ISmartContract { args: args }) - let transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromDraft(draftTx); transaction.setChainID(chainID); transaction.setValue(value); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 8d6358527..dbb8ac9e5 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -7,6 +7,7 @@ import { TokenTransfer } from "./tokenTransfer"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { DraftTransaction } from "./draftTransaction"; +import { TRANSACTION_MIN_GAS_PRICE } from "./constants"; describe("test transaction construction", async () => { @@ -34,6 +35,9 @@ describe("test transaction construction", async () => { assert.equal(transaction.getValue().toString(), "1000000000000000000"); assert.equal(transaction.getData().toString(), "test"); assert.equal(transaction.getChainID().valueOf(), ""); + assert.equal(transaction.getNonce().valueOf(), 0); + assert.equal(transaction.getGasPrice().valueOf(), TRANSACTION_MIN_GAS_PRICE); + assert.deepEqual(transaction.getSignature(), Buffer.from([])); }); it("with no data, no value", async () => { diff --git a/src/transaction.ts b/src/transaction.ts index 01b947b2d..4f7b483fc 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -154,16 +154,16 @@ export class Transaction { } /** - * Creates a new Transaction object from a DraftTransaction. - */ + * Creates a new Transaction object from a DraftTransaction. + */ static fromDraft(draft: DraftTransaction): Transaction { return new Transaction({ sender: Address.fromBech32(draft.sender), receiver: Address.fromBech32(draft.receiver), gasLimit: new BigNumber(draft.gasLimit).toNumber(), chainID: "", - value: draft.value ?? 0, - data: draft.data ? new TransactionPayload(Buffer.from(draft.data)) : new TransactionPayload() + value: draft.value, + data: new TransactionPayload(Buffer.from(draft.data)) }) } diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 1dc1709e1..1cb05cf88 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -2,7 +2,7 @@ import BigNumber from "bignumber.js"; import { DraftTransaction } from "../draftTransaction"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { IAddress } from "../interface"; -import { utf8ToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; +import { utf8ToHex, boolToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { Address } from "../address"; import { Logger } from "../logger"; @@ -65,8 +65,8 @@ export class TokenManagementTransactionsFactory { ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], - ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] + ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], + ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] ]; return new DraftTransactionBuilder({ @@ -103,8 +103,8 @@ export class TokenManagementTransactionsFactory { ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], - ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] + ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], + ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] ]; return new DraftTransactionBuilder({ @@ -141,8 +141,8 @@ export class TokenManagementTransactionsFactory { ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), utf8ToHex(String(options.canUpgrade).toLowerCase())], - ...[utf8ToHex("canAddSpecialRoles"), utf8ToHex(String(options.canAddSpecialRoles).toLowerCase())] + ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], + ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] ]; return new DraftTransactionBuilder({ diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 6288b99e6..6d3264121 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -29,6 +29,10 @@ export function utf8ToHex(value: string) { return zeroPadStringIfOddLength(hex); } +export function boolToHex(value: boolean) { + return utf8ToHex(value.toString()); +} + export function byteArrayToHex(byteArray: Uint8Array): string { const hexString = Buffer.from(byteArray).toString("hex"); return zeroPadStringIfOddLength(hexString); From f5820aa6059ae313f3d6c9d6f4e2ac133b603bf0 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 24 Oct 2023 14:48:49 +0300 Subject: [PATCH 035/275] add transfer and execute --- src/smartcontracts/smartContract.ts | 5 +- src/tokens.ts | 9 + .../smartContractTransactionsFactory.spec.ts | 204 +++++++++++++++++- .../smartContractTransactionsFactory.ts | 50 +++-- .../tokenTransfersDataBuilder.ts | 38 ++++ 5 files changed, 288 insertions(+), 18 deletions(-) create mode 100644 src/transactionsFactories/tokenTransfersDataBuilder.ts diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index b5908d2cb..ac4038227 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -12,11 +12,10 @@ import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; -import { ArwenVirtualMachine, ContractCallPayloadBuilder, ContractUpgradePayloadBuilder } from "./transactionPayloadBuilders"; +import { ArwenVirtualMachine } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; -import { TransactionPayload } from "../transactionPayload"; import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; const createKeccakHash = require("keccak"); @@ -223,7 +222,7 @@ export class SmartContract implements ISmartContract { const draftTx = scDraftTransactionFactory.createTransactionForExecute({ sender: caller, - contractAddress: receiver ? receiver : this.getAddress(), + contract: receiver ? receiver : this.getAddress(), functionName: func.toString(), gasLimit: gasLimit.valueOf(), args: args diff --git a/src/tokens.ts b/src/tokens.ts index 9d1f6f1f8..3308ec933 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -47,6 +47,15 @@ export class TokenComputer { return parts[0] + "-" + parts[1]; } + ensureIdentifierHasCorrectStructure(identifier: string): string { + const isExtendedIdentifier = identifier.split("-").length === 3 ? true : false; + if (!isExtendedIdentifier) { + return identifier; + } + + return this.extractIdentifierFromExtendedIdentifier(identifier); + } + private checkIfExtendedIdentifierWasProvided(tokenParts: string[]): void { const EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 874845fff..92a9ed4e2 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -8,6 +8,8 @@ import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; +import BigNumber from "bignumber.js"; +import { Token, TokenTransfer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -73,7 +75,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(deployDraft, abiDeployDraft); }); - it("should create draft transaction for execute", async function () { + it("should create draft transaction for execute without transfer", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -82,14 +84,14 @@ describe("test smart contract transactions factory", function () { const executeDraft = factory.createTransactionForExecute({ sender: sender, - contractAddress: contract, + contract: contract, functionName: func, gasLimit: gasLimit, args: args }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, - contractAddress: contract, + contract: contract, functionName: func, gasLimit: gasLimit, args: args @@ -107,6 +109,202 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeDraft, abiExecuteDraft); }); + it("should create draft transaction for execute and transfer native token", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + const egldAmount = new BigNumber("1000000000000000000"); + + const executeDraft = factory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + nativeTransferAmount: egldAmount + }); + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + nativeTransferAmount: egldAmount + }); + + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("add@07")); + + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value.valueOf(), "1000000000000000000"); + + assert.deepEqual(executeDraft, abiExecuteDraft); + }); + + it("should create draft transaction for execute and transfer single esdt", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + const token = new Token("FOO-6ce17b", 0); + const transfer = new TokenTransfer(token, 10); + + const executeDraft = factory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [transfer] + }); + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [transfer] + }); + + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); + + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value.valueOf(), "0"); + + assert.deepEqual(executeDraft, abiExecuteDraft); + }); + + it("should create draft transaction for execute and transfer multiple esdts", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + + const fooToken = new Token("FOO-6ce17b", 0); + const fooTransfer = new TokenTransfer(fooToken, 10); + const barToken = new Token("BAR-5bc08f", 0); + const barTransfer = new TokenTransfer(barToken, 3140); + + const executeDraft = factory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [fooTransfer, barTransfer] + }); + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [fooTransfer, barTransfer] + }); + + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07")); + + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value.valueOf(), "0"); + + assert.deepEqual(executeDraft, abiExecuteDraft); + }); + + it("should create draft transaction for execute and transfer single nft", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + + const token = new Token("NFT-123456", 1); + const transfer = new TokenTransfer(token, 1); + + const executeDraft = factory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [transfer] + }); + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [transfer] + }); + + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07")); + + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value.valueOf(), "0"); + + assert.deepEqual(executeDraft, abiExecuteDraft); + }); + + it("should create draft transaction for execute and transfer multiple nfts", async function () { + const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + const func = "add"; + const gasLimit = 6000000; + const args = [new U32Value(7)]; + + const firstToken = new Token("NFT-123456", 1); + const firstTransfer = new TokenTransfer(firstToken, 1); + const secondToken = new Token("NFT-123456", 42); + const secondTransfer = new TokenTransfer(secondToken, 1); + + const executeDraft = factory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [firstTransfer, secondTransfer] + }); + const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + sender: sender, + contract: contract, + functionName: func, + gasLimit: gasLimit, + args: args, + tokenTransfers: [firstTransfer, secondTransfer] + }); + + assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + + assert.isDefined(executeDraft.data); + assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07")); + + assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); + assert.equal(executeDraft.value.valueOf(), "0"); + + assert.deepEqual(executeDraft, abiExecuteDraft); + }); + it("should create draft transaction for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 409b3bf79..f1b61cc86 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -2,13 +2,14 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { DraftTransaction } from "../draftTransaction"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; -import { byteArrayToHex } from "../utils.codec"; +import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; -import { TokenTransfer } from "../tokenTransfer"; +import { TokenComputer, TokenTransfer } from "../tokens"; +import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; interface Config { chainID: string; @@ -26,6 +27,7 @@ interface Abi { export class SmartContractTransactionsFactory { private readonly config: Config; private readonly abiRegistry?: Abi; + private readonly dataArgsBuilder: TokenTransfersDataBuilder; constructor({ config, @@ -36,6 +38,7 @@ export class SmartContractTransactionsFactory { }) { this.config = config; this.abiRegistry = abi; + this.dataArgsBuilder = new TokenTransfersDataBuilder(); } createTransactionForDeploy(options: { @@ -81,30 +84,53 @@ export class SmartContractTransactionsFactory { createTransactionForExecute(options: { sender: IAddress, - contractAddress: IAddress, + contract: IAddress, functionName: string, gasLimit: BigNumber.Value, args?: any[], - nativeTokenTransfer?: BigNumber.Value, + nativeTransferAmount?: BigNumber.Value, tokenTransfers?: TokenTransfer[] }): DraftTransaction { - if (options.nativeTokenTransfer && options.tokenTransfers?.length) { + const args = options.args || []; + const tokenTransfer = options.tokenTransfers || []; + const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const numberOfTokens = tokenTransfer.length; + + if (nativeTransferAmount && numberOfTokens) { throw new ErrBadUsage("Can't send both native token and ESDT/NFT tokens"); } - const args = options.args || []; - let parts: string[] = [options.functionName]; + let receiver = options.contract; + const tokenComputer = new TokenComputer(); + let transferArgs: string[] = []; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName)); - parts = parts.concat(preparedArgs); + if (numberOfTokens === 1) { + const transfer = tokenTransfer[0]; + + if (tokenComputer.isFungible(transfer.token)) { + transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); + } + else { + transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + receiver = options.sender; + } + } + else if (numberOfTokens > 1) { + transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, tokenTransfer) + receiver = options.sender; + } + + transferArgs.push(transferArgs.length ? utf8ToHex(options.functionName) : options.functionName); + transferArgs = transferArgs.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); return new DraftTransactionBuilder({ config: this.config, sender: options.sender, - receiver: options.contractAddress, - dataParts: parts, + receiver: receiver, + dataParts: transferArgs, gasLimit: options.gasLimit, - addDataMovementGas: false + addDataMovementGas: false, + amount: nativeTransferAmount }).build(); } diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts new file mode 100644 index 000000000..ec730f521 --- /dev/null +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -0,0 +1,38 @@ +import { IAddress } from "../interface"; +import { TokenTransfer, TokenComputer } from "../tokens"; +import { numberToPaddedHex, utf8ToHex, addressToHex } from "../utils.codec"; + +export class TokenTransfersDataBuilder { + private tokenComputer: TokenComputer; + + constructor() { + this.tokenComputer = new TokenComputer(); + } + + buildArgsForESDTTransfer(transfer: TokenTransfer): string[] { + let args = ["ESDTTransfer"]; + args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); + return args; + } + + buildArgsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { + let args = ["ESDTNFTTransfer"]; + + const token = transfer.token; + const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(token.identifier); + + args.push(...[utf8ToHex(identifier), numberToPaddedHex(token.nonce), numberToPaddedHex(transfer.amount), addressToHex(receiver)]); + return args; + } + + buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { + let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; + + for (let transfer of transfers) { + const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(transfer.token.identifier); + args.push(...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)]); + } + + return args; + } +} From fccb77ac7f2c8a8b88ded902742cf3266fc97e80 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 24 Oct 2023 16:53:29 +0300 Subject: [PATCH 036/275] transfer transactions factory --- .../transactionsFactoryConfig.ts | 8 ++ .../transferTransactionsFactory.spec.ts | 97 +++++++++++++++++++ .../transferTransactionsFactory.ts | 89 +++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 src/transactionsFactories/transferTransactionsFactory.spec.ts create mode 100644 src/transactionsFactories/transferTransactionsFactory.ts diff --git a/src/transactionsFactories/transactionsFactoryConfig.ts b/src/transactionsFactories/transactionsFactoryConfig.ts index b3dca70f2..c07276701 100644 --- a/src/transactionsFactories/transactionsFactoryConfig.ts +++ b/src/transactionsFactories/transactionsFactoryConfig.ts @@ -27,6 +27,9 @@ export class TransactionsFactoryConfig { gasLimitDelegationOperations: BigNumber.Value; additionalGasLimitPerValidatorNode: BigNumber.Value; additionalGasLimitForDelegationOperations: BigNumber.Value; + gasLimitESDTTransfer: BigNumber.Value; + gasLimitESDTNFTTransfer: BigNumber.Value; + gasLimitMultiESDTNFTTransfer: BigNumber.Value; constructor(chainId: string) { // General-purpose configuration @@ -59,5 +62,10 @@ export class TransactionsFactoryConfig { this.gasLimitDelegationOperations = new BigNumber(1000000); this.additionalGasLimitPerValidatorNode = new BigNumber(6000000); this.additionalGasLimitForDelegationOperations = new BigNumber(10000000); + + // Configuration for token transfers + this.gasLimitESDTTransfer = new BigNumber(200000); + this.gasLimitESDTNFTTransfer = new BigNumber(200000); + this.gasLimitMultiESDTNFTTransfer = new BigNumber(200000); } } diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts new file mode 100644 index 000000000..542b9656f --- /dev/null +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -0,0 +1,97 @@ +import { assert } from "chai"; +import { Address } from "../address"; +import { Token, TokenTransfer } from "../tokens"; +import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; +import { TransferTransactionsFactory } from "./transferTransactionsFactory"; + +describe("test transfer transcations factory", function () { + const config = new TransactionsFactoryConfig("D"); + const factory = new TransferTransactionsFactory(config); + + const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); + + it("should create draft transaction for native token transfer without data", async () => { + const transaction = factory.createTransactionForNativeTokenTransfer({ + sender: alice, + receiver: bob, + nativeAmount: "1000000000000000000" + }); + + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.gasLimit.valueOf(), "50000"); + assert.deepEqual(transaction.data, new Uint8Array()); + }); + + it("should create draft transaction for native token transfer with data", async () => { + const transaction = factory.createTransactionForNativeTokenTransfer({ + sender: alice, + receiver: bob, + nativeAmount: "1000000000000000000", + data: "test data" + }); + + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.gasLimit.valueOf(), "63500"); + assert.deepEqual(transaction.data, Buffer.from("test data")); + }); + + it("should create draft transaction for esdt transfer", async () => { + const fooToken = new Token("FOO-123456", 0); + const transfer = new TokenTransfer(fooToken, 1000000); + + const transaction = factory.createTransactionForESDTTokenTransfer({ + sender: alice, + receiver: bob, + tokenTransfers: [transfer] + }); + + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "410000"); + assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); + }); + + it("should create draft transaction for nft transfer", async () => { + const nft = new Token("NFT-123456", 10); + const transfer = new TokenTransfer(nft, 1); + + const transaction = factory.createTransactionForESDTTokenTransfer({ + sender: alice, + receiver: bob, + tokenTransfers: [transfer] + }); + + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, alice.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "1210500"); + assert.deepEqual(transaction.data.toString(), "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8"); + }); + + it("should create draft transaction for multiple nft transfers", async () => { + const firstNft = new Token("NFT-123456", 10); + const firstTransfer = new TokenTransfer(firstNft, 1); + + const secondNft = new Token("TEST-987654", 1); + const secondTransfer = new TokenTransfer(secondNft, 1); + + const transaction = factory.createTransactionForESDTTokenTransfer({ + sender: alice, + receiver: bob, + tokenTransfers: [firstTransfer, secondTransfer] + }); + + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, alice.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "1466000"); + assert.deepEqual(transaction.data.toString(), "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01"); + }); + +}); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts new file mode 100644 index 000000000..0e792ec02 --- /dev/null +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -0,0 +1,89 @@ +import BigNumber from "bignumber.js"; +import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; +import { IAddress } from "../interface"; +import { DraftTransaction } from "../draftTransaction"; +import { DraftTransactionBuilder } from "./draftTransactionBuilder"; +import { TokenComputer, TokenTransfer } from "../tokens"; + +const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; +const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; + +interface IConfig { + chainID: string + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; + gasLimitESDTTransfer: BigNumber.Value; + gasLimitESDTNFTTransfer: BigNumber.Value; + gasLimitMultiESDTNFTTransfer: BigNumber.Value; +} + +export class TransferTransactionsFactory { + private readonly config: IConfig; + private readonly dataArgsBuilder: TokenTransfersDataBuilder; + + constructor(config: IConfig) { + this.config = config; + this.dataArgsBuilder = new TokenTransfersDataBuilder(); + } + + createTransactionForNativeTokenTransfer(options: { + sender: IAddress, + receiver: IAddress, + nativeAmount: BigNumber.Value, + data?: string + }): DraftTransaction { + const data = options.data || ""; + return new DraftTransactionBuilder({ + config: this.config, + sender: options.sender, + receiver: options.receiver, + dataParts: [data], + gasLimit: 0, + addDataMovementGas: true, + amount: options.nativeAmount + }).build(); + } + + createTransactionForESDTTokenTransfer(options: { + sender: IAddress, + receiver: IAddress, + tokenTransfers: TokenTransfer[] + }): DraftTransaction { + const numberOfTransfers = options.tokenTransfers.length; + let receiver = options.receiver; + + let transferArgs: string[] = []; + let extraGasForTransfer = new BigNumber(0); + const tokenComputer = new TokenComputer(); + + if (numberOfTransfers === 1) { + const transfer = options.tokenTransfers[0]; + + if (tokenComputer.isFungible(transfer.token)) { + transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER)); + } + else { + transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + receiver = options.sender; + } + } + else if (numberOfTransfers > 1) { + transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); + extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + .multipliedBy(new BigNumber(numberOfTransfers)) + .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + receiver = options.sender; + } + + return new DraftTransactionBuilder({ + config: this.config, + sender: options.sender, + receiver: receiver, + dataParts: transferArgs, + gasLimit: extraGasForTransfer, + addDataMovementGas: true + }).build(); + } +} From 8571d1a53b13c7bd2f448bf3bc7395b8fce39a0b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 25 Oct 2023 23:43:30 +0300 Subject: [PATCH 037/275] first part of fixes after review --- src/errors.ts | 9 ++++ src/smartcontracts/smartContract.ts | 4 +- .../transactionPayloadBuilders.ts | 7 +++- src/tokens.spec.ts | 12 +++++- src/tokens.ts | 41 +++++++++++++------ .../smartContractTransactionsFactory.spec.ts | 24 +---------- .../smartContractTransactionsFactory.ts | 2 +- .../tokenTransfersDataBuilder.ts | 4 +- 8 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index 12282114f..53d83bc6e 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -326,18 +326,27 @@ export class ErrGasLimitShouldBe0ForInnerTransaction extends Err { } } +/** + * Signals that the `isCompleted` property is missing on the transaction obect and is needed for the Transaction Watcher + */ export class ErrIsCompletedFieldIsMissingOnTransaction extends Err { public constructor() { super("The transaction watcher requires the `isCompleted` property to be defined on the transaction object. Perhaps you've used the sdk-network-provider's `ProxyNetworkProvider.getTransaction()` and in that case you should also pass `withProcessStatus=true`.") } } +/** + * Signals that the provided token identifier is not valid + */ export class ErrInvalidTokenIdentifier extends Err { public constructor(message: string) { super(message); } } +/** + * Signals a generic bad usage error + */ export class ErrBadUsage extends Err { public constructor(message: string) { super(message); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index ac4038227..5bf0a93f8 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -12,7 +12,7 @@ import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; -import { ArwenVirtualMachine } from "./transactionPayloadBuilders"; +import { WasmVirtualMachine } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; @@ -273,7 +273,7 @@ export class SmartContract implements ISmartContract { let bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); let hash = createKeccakHash("keccak256").update(bytesToHash).digest(); - let vmTypeBytes = Buffer.from(ArwenVirtualMachine, "hex"); + let vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); let addressBytes = Buffer.concat([ initialPadding, vmTypeBytes, diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index f1bf9b377..fb8034637 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -5,7 +5,12 @@ import { ArgSerializer } from "./argSerializer"; import { ICode, ICodeMetadata, IContractFunction } from "./interface"; import { TypedValue } from "./typesystem"; + +/** + * @deprecated This constant should not be used. It should be replaced with "WasmVirtualMachine" + */ export const ArwenVirtualMachine = "0500"; +export const WasmVirtualMachine = "0500"; /** * A builder for {@link TransactionPayload} objects, to be used for Smart Contract deployment transactions. @@ -55,7 +60,7 @@ export class ContractDeployPayloadBuilder { let code = this.code!.toString(); let codeMetadata = this.codeMetadata.toString(); - let data = `${code}@${ArwenVirtualMachine}@${codeMetadata}`; + let data = `${code}@${WasmVirtualMachine}@${codeMetadata}`; data = appendArgumentsToString(data, this.arguments); return new TransactionPayload(data); diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index f5c4ddf63..70fd083c5 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -14,13 +14,21 @@ describe("test token computer", async () => { it("should extract nonce from extended identifier", async () => { const extendedIdentifier = "TEST-123456-0a"; - const nonce = tokenComputer.extractNonceFromExtendedIdentifier(extendedIdentifier); + let nonce = tokenComputer.extractNonceFromExtendedIdentifier(extendedIdentifier); assert.equal(nonce, 10); + + const fungibleTokenIdentifier = "FNG-123456"; + nonce = tokenComputer.extractNonceFromExtendedIdentifier(fungibleTokenIdentifier); + assert.equal(nonce, 0); }) it("should extract identifier from extended identifier", async () => { const extendedIdentifier = "TEST-123456-0a"; - const identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(extendedIdentifier); + let identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(extendedIdentifier); assert.equal(identifier, "TEST-123456"); + + const fungibleTokenIdentifier = "FNG-123456"; + identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(fungibleTokenIdentifier); + assert.equal(identifier, "FNG-123456"); }) }); diff --git a/src/tokens.ts b/src/tokens.ts index 3308ec933..12e45bc2a 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -34,6 +34,11 @@ export class TokenComputer { this.checkIfExtendedIdentifierWasProvided(parts); this.checkLengthOfRandomSequence(parts[1]); + // in case the identifier of a fungible token is provided + if (parts.length == 2) { + return 0; + } + const hexNonce = Buffer.from(parts[2], 'hex'); return decodeUnsignedNumber(hexNonce); } @@ -42,25 +47,20 @@ export class TokenComputer { const parts = identifier.split("-"); this.checkIfExtendedIdentifierWasProvided(parts); + this.ensureTokenTickerValidity(parts[0]); this.checkLengthOfRandomSequence(parts[1]); return parts[0] + "-" + parts[1]; } - ensureIdentifierHasCorrectStructure(identifier: string): string { - const isExtendedIdentifier = identifier.split("-").length === 3 ? true : false; - if (!isExtendedIdentifier) { - return identifier; - } - - return this.extractIdentifierFromExtendedIdentifier(identifier); - } - private checkIfExtendedIdentifierWasProvided(tokenParts: string[]): void { - const EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3; + // this is for the identifiers of fungible tokens + const MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 2 + // this is for the identifiers of nft, sft and meta-esdt + const MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3 - if (tokenParts.length !== EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { - throw new ErrInvalidTokenIdentifier("You have not provided the extended identifier"); + if (tokenParts.length < MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED || tokenParts.length > MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { + throw new ErrInvalidTokenIdentifier("Invalid extended token identifier provided"); } } @@ -71,6 +71,23 @@ export class TokenComputer { throw new ErrInvalidTokenIdentifier("The identifier is not valid. The random sequence does not have the right length"); } } + + private ensureTokenTickerValidity(ticker: string) { + const MIN_TICKER_LENGTH = 3; + const MAX_TICKER_LENGTH = 10; + + if (ticker.length < MIN_TICKER_LENGTH || ticker.length > MAX_TICKER_LENGTH) { + throw new ErrInvalidTokenIdentifier(`The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters`); + } + + if (!ticker.match(/^[a-zA-Z0-9]+$/)) { + throw new ErrInvalidTokenIdentifier("The token ticker should only contain alphanumeric characters"); + } + + if (!(ticker == ticker.toUpperCase())) { + throw new ErrInvalidTokenIdentifier("The token ticker should be upper case"); + } + } } function decodeUnsignedNumber(arg: Buffer): number { diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 92a9ed4e2..5aac0b24f 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -66,9 +66,7 @@ describe("test smart contract transactions factory", function () { assert.equal(deployDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployDraft.receiver, CONTRACT_DEPLOY_ADDRESS); - assert.isDefined(deployDraft.data); - expect(deployDraft.data!.length).to.be.greaterThan(0); - + expect(deployDraft.data.length).to.be.greaterThan(0); assert.equal(deployDraft.gasLimit.valueOf(), gasLimit); assert.equal(deployDraft.value, 0); @@ -99,10 +97,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value, 0); @@ -136,10 +131,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "1000000000000000000"); @@ -174,10 +166,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -215,10 +204,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -254,10 +240,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -295,10 +278,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -329,9 +309,7 @@ describe("test smart contract transactions factory", function () { assert.equal(upgradeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(upgradeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isDefined(upgradeDraft.data); assert.isTrue(Buffer.from(upgradeDraft.data!).toString().startsWith("upgradeContract@")); - assert.equal(upgradeDraft.gasLimit.valueOf(), gasLimit); assert.equal(upgradeDraft.value, 0); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index f1b61cc86..123961d17 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -97,7 +97,7 @@ export class SmartContractTransactionsFactory { const numberOfTokens = tokenTransfer.length; if (nativeTransferAmount && numberOfTokens) { - throw new ErrBadUsage("Can't send both native token and ESDT/NFT tokens"); + throw new ErrBadUsage("Can't send both native token and custom tokens(ESDT/NFT)"); } let receiver = options.contract; diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index ec730f521..05c7b23e8 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -19,7 +19,7 @@ export class TokenTransfersDataBuilder { let args = ["ESDTNFTTransfer"]; const token = transfer.token; - const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(token.identifier); + const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(token.identifier); args.push(...[utf8ToHex(identifier), numberToPaddedHex(token.nonce), numberToPaddedHex(transfer.amount), addressToHex(receiver)]); return args; @@ -29,7 +29,7 @@ export class TokenTransfersDataBuilder { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { - const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(transfer.token.identifier); + const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); args.push(...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)]); } From 6915aac35d5e248d67d19609be458c1acaeb0735 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 25 Oct 2023 23:43:30 +0300 Subject: [PATCH 038/275] first part of fixes after review --- src/errors.ts | 9 ++++ src/smartcontracts/smartContract.ts | 4 +- .../transactionPayloadBuilders.ts | 7 +++- src/tokens.spec.ts | 12 +++++- src/tokens.ts | 41 +++++++++++++------ .../smartContractTransactionsFactory.spec.ts | 24 +---------- .../smartContractTransactionsFactory.ts | 2 +- .../tokenTransfersDataBuilder.ts | 4 +- 8 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index 12282114f..53d83bc6e 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -326,18 +326,27 @@ export class ErrGasLimitShouldBe0ForInnerTransaction extends Err { } } +/** + * Signals that the `isCompleted` property is missing on the transaction obect and is needed for the Transaction Watcher + */ export class ErrIsCompletedFieldIsMissingOnTransaction extends Err { public constructor() { super("The transaction watcher requires the `isCompleted` property to be defined on the transaction object. Perhaps you've used the sdk-network-provider's `ProxyNetworkProvider.getTransaction()` and in that case you should also pass `withProcessStatus=true`.") } } +/** + * Signals that the provided token identifier is not valid + */ export class ErrInvalidTokenIdentifier extends Err { public constructor(message: string) { super(message); } } +/** + * Signals a generic bad usage error + */ export class ErrBadUsage extends Err { public constructor(message: string) { super(message); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index ac4038227..5bf0a93f8 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -12,7 +12,7 @@ import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; -import { ArwenVirtualMachine } from "./transactionPayloadBuilders"; +import { WasmVirtualMachine } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; @@ -273,7 +273,7 @@ export class SmartContract implements ISmartContract { let bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); let hash = createKeccakHash("keccak256").update(bytesToHash).digest(); - let vmTypeBytes = Buffer.from(ArwenVirtualMachine, "hex"); + let vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); let addressBytes = Buffer.concat([ initialPadding, vmTypeBytes, diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index f1bf9b377..fb8034637 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -5,7 +5,12 @@ import { ArgSerializer } from "./argSerializer"; import { ICode, ICodeMetadata, IContractFunction } from "./interface"; import { TypedValue } from "./typesystem"; + +/** + * @deprecated This constant should not be used. It should be replaced with "WasmVirtualMachine" + */ export const ArwenVirtualMachine = "0500"; +export const WasmVirtualMachine = "0500"; /** * A builder for {@link TransactionPayload} objects, to be used for Smart Contract deployment transactions. @@ -55,7 +60,7 @@ export class ContractDeployPayloadBuilder { let code = this.code!.toString(); let codeMetadata = this.codeMetadata.toString(); - let data = `${code}@${ArwenVirtualMachine}@${codeMetadata}`; + let data = `${code}@${WasmVirtualMachine}@${codeMetadata}`; data = appendArgumentsToString(data, this.arguments); return new TransactionPayload(data); diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index f5c4ddf63..70fd083c5 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -14,13 +14,21 @@ describe("test token computer", async () => { it("should extract nonce from extended identifier", async () => { const extendedIdentifier = "TEST-123456-0a"; - const nonce = tokenComputer.extractNonceFromExtendedIdentifier(extendedIdentifier); + let nonce = tokenComputer.extractNonceFromExtendedIdentifier(extendedIdentifier); assert.equal(nonce, 10); + + const fungibleTokenIdentifier = "FNG-123456"; + nonce = tokenComputer.extractNonceFromExtendedIdentifier(fungibleTokenIdentifier); + assert.equal(nonce, 0); }) it("should extract identifier from extended identifier", async () => { const extendedIdentifier = "TEST-123456-0a"; - const identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(extendedIdentifier); + let identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(extendedIdentifier); assert.equal(identifier, "TEST-123456"); + + const fungibleTokenIdentifier = "FNG-123456"; + identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(fungibleTokenIdentifier); + assert.equal(identifier, "FNG-123456"); }) }); diff --git a/src/tokens.ts b/src/tokens.ts index 3308ec933..12e45bc2a 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -34,6 +34,11 @@ export class TokenComputer { this.checkIfExtendedIdentifierWasProvided(parts); this.checkLengthOfRandomSequence(parts[1]); + // in case the identifier of a fungible token is provided + if (parts.length == 2) { + return 0; + } + const hexNonce = Buffer.from(parts[2], 'hex'); return decodeUnsignedNumber(hexNonce); } @@ -42,25 +47,20 @@ export class TokenComputer { const parts = identifier.split("-"); this.checkIfExtendedIdentifierWasProvided(parts); + this.ensureTokenTickerValidity(parts[0]); this.checkLengthOfRandomSequence(parts[1]); return parts[0] + "-" + parts[1]; } - ensureIdentifierHasCorrectStructure(identifier: string): string { - const isExtendedIdentifier = identifier.split("-").length === 3 ? true : false; - if (!isExtendedIdentifier) { - return identifier; - } - - return this.extractIdentifierFromExtendedIdentifier(identifier); - } - private checkIfExtendedIdentifierWasProvided(tokenParts: string[]): void { - const EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3; + // this is for the identifiers of fungible tokens + const MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 2 + // this is for the identifiers of nft, sft and meta-esdt + const MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3 - if (tokenParts.length !== EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { - throw new ErrInvalidTokenIdentifier("You have not provided the extended identifier"); + if (tokenParts.length < MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED || tokenParts.length > MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { + throw new ErrInvalidTokenIdentifier("Invalid extended token identifier provided"); } } @@ -71,6 +71,23 @@ export class TokenComputer { throw new ErrInvalidTokenIdentifier("The identifier is not valid. The random sequence does not have the right length"); } } + + private ensureTokenTickerValidity(ticker: string) { + const MIN_TICKER_LENGTH = 3; + const MAX_TICKER_LENGTH = 10; + + if (ticker.length < MIN_TICKER_LENGTH || ticker.length > MAX_TICKER_LENGTH) { + throw new ErrInvalidTokenIdentifier(`The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters`); + } + + if (!ticker.match(/^[a-zA-Z0-9]+$/)) { + throw new ErrInvalidTokenIdentifier("The token ticker should only contain alphanumeric characters"); + } + + if (!(ticker == ticker.toUpperCase())) { + throw new ErrInvalidTokenIdentifier("The token ticker should be upper case"); + } + } } function decodeUnsignedNumber(arg: Buffer): number { diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 92a9ed4e2..5aac0b24f 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -66,9 +66,7 @@ describe("test smart contract transactions factory", function () { assert.equal(deployDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(deployDraft.receiver, CONTRACT_DEPLOY_ADDRESS); - assert.isDefined(deployDraft.data); - expect(deployDraft.data!.length).to.be.greaterThan(0); - + expect(deployDraft.data.length).to.be.greaterThan(0); assert.equal(deployDraft.gasLimit.valueOf(), gasLimit); assert.equal(deployDraft.value, 0); @@ -99,10 +97,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value, 0); @@ -136,10 +131,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "1000000000000000000"); @@ -174,10 +166,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -215,10 +204,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -254,10 +240,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -295,10 +278,7 @@ describe("test smart contract transactions factory", function () { assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - - assert.isDefined(executeDraft.data); assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -329,9 +309,7 @@ describe("test smart contract transactions factory", function () { assert.equal(upgradeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(upgradeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isDefined(upgradeDraft.data); assert.isTrue(Buffer.from(upgradeDraft.data!).toString().startsWith("upgradeContract@")); - assert.equal(upgradeDraft.gasLimit.valueOf(), gasLimit); assert.equal(upgradeDraft.value, 0); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index f1b61cc86..123961d17 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -97,7 +97,7 @@ export class SmartContractTransactionsFactory { const numberOfTokens = tokenTransfer.length; if (nativeTransferAmount && numberOfTokens) { - throw new ErrBadUsage("Can't send both native token and ESDT/NFT tokens"); + throw new ErrBadUsage("Can't send both native token and custom tokens(ESDT/NFT)"); } let receiver = options.contract; diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index ec730f521..05c7b23e8 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -19,7 +19,7 @@ export class TokenTransfersDataBuilder { let args = ["ESDTNFTTransfer"]; const token = transfer.token; - const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(token.identifier); + const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(token.identifier); args.push(...[utf8ToHex(identifier), numberToPaddedHex(token.nonce), numberToPaddedHex(transfer.amount), addressToHex(receiver)]); return args; @@ -29,7 +29,7 @@ export class TokenTransfersDataBuilder { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { - const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(transfer.token.identifier); + const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); args.push(...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)]); } From 87dd27808815d818ee239b65e8ccb5385b590096 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 11:54:53 +0300 Subject: [PATCH 039/275] fixes after review --- src/smartcontracts/smartContract.ts | 10 +- .../transactionPayloadBuilders.ts | 4 +- src/tokens.spec.ts | 6 +- src/tokens.ts | 38 +++--- .../smartContractTransactionsFactory.spec.ts | 98 +++++++++------ .../smartContractTransactionsFactory.ts | 118 ++++++++---------- .../tokenTransfersDataBuilder.ts | 21 +++- 7 files changed, 161 insertions(+), 134 deletions(-) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 5bf0a93f8..09ba8858d 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -17,6 +17,7 @@ import { EndpointDefinition, TypedValue } from "./typesystem"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; +import { TokenComputer } from "../tokens"; const createKeccakHash = require("keccak"); interface IAbi { @@ -118,7 +119,8 @@ export class SmartContract implements ISmartContract { const config = new TransactionsFactoryConfig(chainID.valueOf()); const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, - abi: this.abi + abi: this.abi, + tokenComputer: new TokenComputer() }); const bytecode = Buffer.from(code.toString(), 'hex'); @@ -177,7 +179,8 @@ export class SmartContract implements ISmartContract { const config = new TransactionsFactoryConfig(chainID.valueOf()); const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, - abi: this.abi + abi: this.abi, + tokenComputer: new TokenComputer() }); const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); @@ -214,7 +217,8 @@ export class SmartContract implements ISmartContract { const config = new TransactionsFactoryConfig(chainID.valueOf()); const scDraftTransactionFactory = new SmartContractTransactionsFactory({ config: config, - abi: this.abi + abi: this.abi, + tokenComputer: new TokenComputer() }); args = args || []; diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index fb8034637..38bd2b02d 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -1,13 +1,11 @@ - import { TransactionPayload } from "../transactionPayload"; import { guardValueIsSet } from "../utils"; import { ArgSerializer } from "./argSerializer"; import { ICode, ICodeMetadata, IContractFunction } from "./interface"; import { TypedValue } from "./typesystem"; - /** - * @deprecated This constant should not be used. It should be replaced with "WasmVirtualMachine" + * @deprecated This constant should not be used. Use {@link WasmVirtualMachine} instead. */ export const ArwenVirtualMachine = "0500"; export const WasmVirtualMachine = "0500"; diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index 70fd083c5..9fd54cd4a 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -1,4 +1,4 @@ -import { Token, TokenTransfer, TokenComputer } from "./tokens"; +import { Token, TokenComputer } from "./tokens"; import { assert } from "chai"; describe("test token computer", async () => { @@ -20,7 +20,7 @@ describe("test token computer", async () => { const fungibleTokenIdentifier = "FNG-123456"; nonce = tokenComputer.extractNonceFromExtendedIdentifier(fungibleTokenIdentifier); assert.equal(nonce, 0); - }) + }); it("should extract identifier from extended identifier", async () => { const extendedIdentifier = "TEST-123456-0a"; @@ -30,5 +30,5 @@ describe("test token computer", async () => { const fungibleTokenIdentifier = "FNG-123456"; identifier = tokenComputer.extractIdentifierFromExtendedIdentifier(fungibleTokenIdentifier); assert.equal(identifier, "FNG-123456"); - }) + }); }); diff --git a/src/tokens.ts b/src/tokens.ts index 12e45bc2a..dd769992f 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -11,18 +11,20 @@ export class Token { } } -export class TokenTransfer { - token: Token; - amount: BigNumber.Value - - constructor(token: Token, amount: BigNumber.Value) { - this.token = token; - this.amount = amount; +export namespace NewTokenTransfer { + export class TokenTransfer { + token: Token; + amount: BigNumber.Value; + + constructor(token: Token, amount: BigNumber.Value) { + this.token = token; + this.amount = amount; + } } } export class TokenComputer { - constructor() { } + constructor() {} isFungible(token: Token): boolean { return token.nonce === 0; @@ -39,7 +41,7 @@ export class TokenComputer { return 0; } - const hexNonce = Buffer.from(parts[2], 'hex'); + const hexNonce = Buffer.from(parts[2], "hex"); return decodeUnsignedNumber(hexNonce); } @@ -55,11 +57,14 @@ export class TokenComputer { private checkIfExtendedIdentifierWasProvided(tokenParts: string[]): void { // this is for the identifiers of fungible tokens - const MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 2 + const MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 2; // this is for the identifiers of nft, sft and meta-esdt - const MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3 + const MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED = 3; - if (tokenParts.length < MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED || tokenParts.length > MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED) { + if ( + tokenParts.length < MIN_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED || + tokenParts.length > MAX_EXTENDED_IDENTIFIER_LENGTH_IF_SPLITTED + ) { throw new ErrInvalidTokenIdentifier("Invalid extended token identifier provided"); } } @@ -68,7 +73,9 @@ export class TokenComputer { const TOKEN_RANDOM_SEQUENCE_LENGTH = 6; if (randomSequence.length !== TOKEN_RANDOM_SEQUENCE_LENGTH) { - throw new ErrInvalidTokenIdentifier("The identifier is not valid. The random sequence does not have the right length"); + throw new ErrInvalidTokenIdentifier( + "The identifier is not valid. The random sequence does not have the right length" + ); } } @@ -77,7 +84,9 @@ export class TokenComputer { const MAX_TICKER_LENGTH = 10; if (ticker.length < MIN_TICKER_LENGTH || ticker.length > MAX_TICKER_LENGTH) { - throw new ErrInvalidTokenIdentifier(`The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters`); + throw new ErrInvalidTokenIdentifier( + `The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters` + ); } if (!ticker.match(/^[a-zA-Z0-9]+$/)) { @@ -93,4 +102,3 @@ export class TokenComputer { function decodeUnsignedNumber(arg: Buffer): number { return arg.readUIntBE(0, arg.length); } - diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 5aac0b24f..d18190728 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -9,7 +9,7 @@ import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import BigNumber from "bignumber.js"; -import { Token, TokenTransfer } from "../tokens"; +import { Token, NewTokenTransfer, TokenComputer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -20,7 +20,8 @@ describe("test smart contract transactions factory", function () { before(async function () { factory = new SmartContractTransactionsFactory({ - config: config + config: config, + tokenComputer: new TokenComputer(), }); adderByteCode = await loadContractCode("src/testdata/adder.wasm"); @@ -28,9 +29,9 @@ describe("test smart contract transactions factory", function () { abiAwareFactory = new SmartContractTransactionsFactory({ config: config, - abi: abiRegistry - }, - ); + abi: abiRegistry, + tokenComputer: new TokenComputer(), + }); }); it("should throw error when args are not of type 'TypedValue'", async function () { @@ -38,12 +39,17 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [0]; - assert.throws(() => factory.createTransactionForDeploy({ - sender: sender, - bytecode: adderByteCode.valueOf(), - gasLimit: gasLimit, - args: args - }), Err, "Can't convert args to TypedValues"); + assert.throws( + () => + factory.createTransactionForDeploy({ + sender: sender, + bytecode: adderByteCode.valueOf(), + gasLimit: gasLimit, + args: args, + }), + Err, + "Can't convert args to TypedValues" + ); }); it("should create draft transaction for deploy", async function () { @@ -55,13 +61,13 @@ describe("test smart contract transactions factory", function () { sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args + args: args, }); const abiDeployDraft = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args + args: args, }); assert.equal(deployDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -85,14 +91,14 @@ describe("test smart contract transactions factory", function () { contract: contract, functionName: func, gasLimit: gasLimit, - args: args + args: args, }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, gasLimit: gasLimit, - args: args + args: args, }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -109,7 +115,6 @@ describe("test smart contract transactions factory", function () { const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; const gasLimit = 6000000; - const args = [new U32Value(7)]; const egldAmount = new BigNumber("1000000000000000000"); const executeDraft = factory.createTransactionForExecute({ @@ -117,16 +122,16 @@ describe("test smart contract transactions factory", function () { contract: contract, functionName: func, gasLimit: gasLimit, - args: args, - nativeTransferAmount: egldAmount + args: [new U32Value(7)], + nativeTransferAmount: egldAmount, }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, gasLimit: gasLimit, - args: args, - nativeTransferAmount: egldAmount + args: [7], + nativeTransferAmount: egldAmount, }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -145,7 +150,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; const token = new Token("FOO-6ce17b", 0); - const transfer = new TokenTransfer(token, 10); + const transfer = new NewTokenTransfer.TokenTransfer(token, 10); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -153,7 +158,7 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, @@ -161,7 +166,7 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -181,9 +186,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const fooToken = new Token("FOO-6ce17b", 0); - const fooTransfer = new TokenTransfer(fooToken, 10); + const fooTransfer = new NewTokenTransfer.TokenTransfer(fooToken, 10); const barToken = new Token("BAR-5bc08f", 0); - const barTransfer = new TokenTransfer(barToken, 3140); + const barTransfer = new NewTokenTransfer.TokenTransfer(barToken, 3140); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -191,7 +196,7 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [fooTransfer, barTransfer] + tokenTransfers: [fooTransfer, barTransfer], }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, @@ -199,12 +204,17 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [fooTransfer, barTransfer] + tokenTransfers: [fooTransfer, barTransfer], }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07")); + assert.deepEqual( + executeDraft.data, + Buffer.from( + "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07" + ) + ); assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -219,7 +229,7 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const token = new Token("NFT-123456", 1); - const transfer = new TokenTransfer(token, 1); + const transfer = new NewTokenTransfer.TokenTransfer(token, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -227,7 +237,7 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, @@ -235,12 +245,17 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.deepEqual(executeDraft.data, Buffer.from("ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07")); + assert.deepEqual( + executeDraft.data, + Buffer.from( + "ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07" + ) + ); assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -255,9 +270,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const firstToken = new Token("NFT-123456", 1); - const firstTransfer = new TokenTransfer(firstToken, 1); + const firstTransfer = new NewTokenTransfer.TokenTransfer(firstToken, 1); const secondToken = new Token("NFT-123456", 42); - const secondTransfer = new TokenTransfer(secondToken, 1); + const secondTransfer = new NewTokenTransfer.TokenTransfer(secondToken, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -265,7 +280,7 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [firstTransfer, secondTransfer] + tokenTransfers: [firstTransfer, secondTransfer], }); const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ sender: sender, @@ -273,12 +288,17 @@ describe("test smart contract transactions factory", function () { functionName: func, gasLimit: gasLimit, args: args, - tokenTransfers: [firstTransfer, secondTransfer] + tokenTransfers: [firstTransfer, secondTransfer], }); assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.deepEqual(executeDraft.data, Buffer.from("MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07")); + assert.deepEqual( + executeDraft.data, + Buffer.from( + "MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07" + ) + ); assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); assert.equal(executeDraft.value.valueOf(), "0"); @@ -296,7 +316,7 @@ describe("test smart contract transactions factory", function () { contract: contract, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args + args: args, }); const abiUpgradeDraft = abiAwareFactory.createTransactionForUpgrade({ @@ -304,7 +324,7 @@ describe("test smart contract transactions factory", function () { contract: contract, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args + args: args, }); assert.equal(upgradeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 123961d17..aa311d8d0 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -8,7 +8,7 @@ import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; -import { TokenComputer, TokenTransfer } from "../tokens"; +import { Token, NewTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; interface Config { @@ -23,34 +23,33 @@ interface Abi { getEndpoint(name: string | ContractFunction): EndpointDefinition; } +interface TokenComputer { + isFungible(token: Token): boolean; +} export class SmartContractTransactionsFactory { private readonly config: Config; private readonly abiRegistry?: Abi; + private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - constructor({ - config, - abi - }: { - config: Config; - abi?: Abi; - }) { + constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { this.config = config; this.abiRegistry = abi; + this.tokenComputer = tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } createTransactionForDeploy(options: { - sender: IAddress, - bytecode: Uint8Array, - gasLimit: BigNumber.Value, - args?: any[], - nativeTransferAmount?: BigNumber.Value, - isUpgradeable?: boolean, - isReadable?: boolean, - isPayable?: boolean, - isPayableBySmartContract?: boolean + sender: IAddress; + bytecode: Uint8Array; + gasLimit: BigNumber.Value; + args?: any[]; + nativeTransferAmount?: BigNumber.Value; + isUpgradeable?: boolean; + isReadable?: boolean; + isPayable?: boolean; + isPayableBySmartContract?: boolean; }): DraftTransaction { const nativeTransferAmount = options.nativeTransferAmount ?? 0; @@ -62,13 +61,9 @@ export class SmartContractTransactionsFactory { const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - let parts = [ - byteArrayToHex(options.bytecode), - byteArrayToHex(VM_TYPE_WASM_VM), - metadata.toString() - ]; + let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); return new DraftTransactionBuilder({ @@ -78,18 +73,18 @@ export class SmartContractTransactionsFactory { dataParts: parts, gasLimit: options.gasLimit, addDataMovementGas: false, - amount: nativeTransferAmount + amount: nativeTransferAmount, }).build(); } createTransactionForExecute(options: { - sender: IAddress, - contract: IAddress, - functionName: string, - gasLimit: BigNumber.Value, - args?: any[], - nativeTransferAmount?: BigNumber.Value, - tokenTransfers?: TokenTransfer[] + sender: IAddress; + contract: IAddress; + functionName: string; + gasLimit: BigNumber.Value; + args?: any[]; + nativeTransferAmount?: BigNumber.Value; + tokenTransfers?: NewTokenTransfer.TokenTransfer[]; }): DraftTransaction { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; @@ -97,54 +92,51 @@ export class SmartContractTransactionsFactory { const numberOfTokens = tokenTransfer.length; if (nativeTransferAmount && numberOfTokens) { - throw new ErrBadUsage("Can't send both native token and custom tokens(ESDT/NFT)"); + throw new ErrBadUsage("Can't send both native tokens and custom tokens(ESDT/NFT)"); } let receiver = options.contract; - const tokenComputer = new TokenComputer(); - let transferArgs: string[] = []; + let dataParts: string[] = []; if (numberOfTokens === 1) { const transfer = tokenTransfer[0]; - if (tokenComputer.isFungible(transfer.token)) { - transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - } - else { - transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + if (this.tokenComputer.isFungible(transfer.token)) { + dataParts = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); + } else { + dataParts = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); receiver = options.sender; } - } - else if (numberOfTokens > 1) { - transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, tokenTransfer) + } else if (numberOfTokens > 1) { + dataParts = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, tokenTransfer); receiver = options.sender; } - transferArgs.push(transferArgs.length ? utf8ToHex(options.functionName) : options.functionName); - transferArgs = transferArgs.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); + dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); + dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); return new DraftTransactionBuilder({ config: this.config, sender: options.sender, receiver: receiver, - dataParts: transferArgs, + dataParts: dataParts, gasLimit: options.gasLimit, addDataMovementGas: false, - amount: nativeTransferAmount + amount: nativeTransferAmount, }).build(); } createTransactionForUpgrade(options: { - sender: IAddress, - contract: IAddress, - bytecode: Uint8Array, - gasLimit: BigNumber.Value, - args?: any[], - nativeTransferAmount?: BigNumber.Value, - isUpgradeable?: boolean, - isReadable?: boolean, - isPayable?: boolean, - isPayableBySmartContract?: boolean + sender: IAddress; + contract: IAddress; + bytecode: Uint8Array; + gasLimit: BigNumber.Value; + args?: any[]; + nativeTransferAmount?: BigNumber.Value; + isUpgradeable?: boolean; + isReadable?: boolean; + isPayable?: boolean; + isPayableBySmartContract?: boolean; }): DraftTransaction { const nativeTransferAmount = options.nativeTransferAmount ?? 0; @@ -156,13 +148,9 @@ export class SmartContractTransactionsFactory { const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - let parts = [ - "upgradeContract", - byteArrayToHex(options.bytecode), - metadata.toString() - ]; + let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition) + const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); return new DraftTransactionBuilder({ @@ -172,13 +160,13 @@ export class SmartContractTransactionsFactory { dataParts: parts, gasLimit: options.gasLimit, addDataMovementGas: false, - amount: nativeTransferAmount + amount: nativeTransferAmount, }).build(); } private argsToDataParts(args: any[], endpoint?: EndpointDefinition): string[] { if (endpoint) { - const typedArgs = NativeSerializer.nativeToTypedValues(args, endpoint) + const typedArgs = NativeSerializer.nativeToTypedValues(args, endpoint); return new ArgSerializer().valuesToStrings(typedArgs); } @@ -191,7 +179,7 @@ export class SmartContractTransactionsFactory { private areArgsOfTypedValue(args: any[]): boolean { for (const arg of args) { - if (!(arg.belongsToTypesystem)) { + if (!arg.belongsToTypesystem) { return false; } } diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 05c7b23e8..96cf382d8 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,5 +1,5 @@ import { IAddress } from "../interface"; -import { TokenTransfer, TokenComputer } from "../tokens"; +import { NewTokenTransfer, TokenComputer } from "../tokens"; import { numberToPaddedHex, utf8ToHex, addressToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { @@ -9,28 +9,37 @@ export class TokenTransfersDataBuilder { this.tokenComputer = new TokenComputer(); } - buildArgsForESDTTransfer(transfer: TokenTransfer): string[] { + buildArgsForESDTTransfer(transfer: NewTokenTransfer.TokenTransfer): string[] { let args = ["ESDTTransfer"]; args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); return args; } - buildArgsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { + buildArgsForSingleESDTNFTTransfer(transfer: NewTokenTransfer.TokenTransfer, receiver: IAddress) { let args = ["ESDTNFTTransfer"]; const token = transfer.token; const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(token.identifier); - args.push(...[utf8ToHex(identifier), numberToPaddedHex(token.nonce), numberToPaddedHex(transfer.amount), addressToHex(receiver)]); + args.push( + ...[ + utf8ToHex(identifier), + numberToPaddedHex(token.nonce), + numberToPaddedHex(transfer.amount), + addressToHex(receiver), + ] + ); return args; } - buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { + buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NewTokenTransfer.TokenTransfer[]) { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); - args.push(...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)]); + args.push( + ...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)] + ); } return args; From 5e5d1f2eec2571633bf76053929d3ce253e3c7b6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 13:28:30 +0300 Subject: [PATCH 040/275] renaming --- src/tokens.ts | 2 +- .../smartContractTransactionsFactory.spec.ts | 14 +++++++------- .../smartContractTransactionsFactory.ts | 4 ++-- .../tokenTransfersDataBuilder.ts | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tokens.ts b/src/tokens.ts index dd769992f..07ef014f2 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -11,7 +11,7 @@ export class Token { } } -export namespace NewTokenTransfer { +export namespace NextTokenTransfer { export class TokenTransfer { token: Token; amount: BigNumber.Value; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index d18190728..02affd278 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -9,7 +9,7 @@ import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import BigNumber from "bignumber.js"; -import { Token, NewTokenTransfer, TokenComputer } from "../tokens"; +import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -150,7 +150,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; const token = new Token("FOO-6ce17b", 0); - const transfer = new NewTokenTransfer.TokenTransfer(token, 10); + const transfer = new NextTokenTransfer.TokenTransfer(token, 10); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -186,9 +186,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const fooToken = new Token("FOO-6ce17b", 0); - const fooTransfer = new NewTokenTransfer.TokenTransfer(fooToken, 10); + const fooTransfer = new NextTokenTransfer.TokenTransfer(fooToken, 10); const barToken = new Token("BAR-5bc08f", 0); - const barTransfer = new NewTokenTransfer.TokenTransfer(barToken, 3140); + const barTransfer = new NextTokenTransfer.TokenTransfer(barToken, 3140); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -229,7 +229,7 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const token = new Token("NFT-123456", 1); - const transfer = new NewTokenTransfer.TokenTransfer(token, 1); + const transfer = new NextTokenTransfer.TokenTransfer(token, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -270,9 +270,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const firstToken = new Token("NFT-123456", 1); - const firstTransfer = new NewTokenTransfer.TokenTransfer(firstToken, 1); + const firstTransfer = new NextTokenTransfer.TokenTransfer(firstToken, 1); const secondToken = new Token("NFT-123456", 42); - const secondTransfer = new NewTokenTransfer.TokenTransfer(secondToken, 1); + const secondTransfer = new NextTokenTransfer.TokenTransfer(secondToken, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index aa311d8d0..638cd7834 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -8,7 +8,7 @@ import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; -import { Token, NewTokenTransfer } from "../tokens"; +import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; interface Config { @@ -84,7 +84,7 @@ export class SmartContractTransactionsFactory { gasLimit: BigNumber.Value; args?: any[]; nativeTransferAmount?: BigNumber.Value; - tokenTransfers?: NewTokenTransfer.TokenTransfer[]; + tokenTransfers?: NextTokenTransfer.TokenTransfer[]; }): DraftTransaction { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 96cf382d8..9f9bd19e6 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,5 +1,5 @@ import { IAddress } from "../interface"; -import { NewTokenTransfer, TokenComputer } from "../tokens"; +import { NextTokenTransfer, TokenComputer } from "../tokens"; import { numberToPaddedHex, utf8ToHex, addressToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { @@ -9,13 +9,13 @@ export class TokenTransfersDataBuilder { this.tokenComputer = new TokenComputer(); } - buildArgsForESDTTransfer(transfer: NewTokenTransfer.TokenTransfer): string[] { + buildArgsForESDTTransfer(transfer: NextTokenTransfer.TokenTransfer): string[] { let args = ["ESDTTransfer"]; args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); return args; } - buildArgsForSingleESDTNFTTransfer(transfer: NewTokenTransfer.TokenTransfer, receiver: IAddress) { + buildArgsForSingleESDTNFTTransfer(transfer: NextTokenTransfer.TokenTransfer, receiver: IAddress) { let args = ["ESDTNFTTransfer"]; const token = transfer.token; @@ -32,7 +32,7 @@ export class TokenTransfersDataBuilder { return args; } - buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NewTokenTransfer.TokenTransfer[]) { + buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NextTokenTransfer.TokenTransfer[]) { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { From 28330ab12cf5f1623aed1e5d91d38dad78676d28 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 14:07:29 +0300 Subject: [PATCH 041/275] remove namespace and renamed the class --- src/tokens.ts | 16 +++++++--------- .../smartContractTransactionsFactory.spec.ts | 12 ++++++------ .../smartContractTransactionsFactory.ts | 2 +- .../tokenTransfersDataBuilder.ts | 6 +++--- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/tokens.ts b/src/tokens.ts index 07ef014f2..ddc0981ab 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -11,15 +11,13 @@ export class Token { } } -export namespace NextTokenTransfer { - export class TokenTransfer { - token: Token; - amount: BigNumber.Value; - - constructor(token: Token, amount: BigNumber.Value) { - this.token = token; - this.amount = amount; - } +export class NextTokenTransfer { + token: Token; + amount: BigNumber.Value; + + constructor(token: Token, amount: BigNumber.Value) { + this.token = token; + this.amount = amount; } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 02affd278..c690ce3df 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -150,7 +150,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; const token = new Token("FOO-6ce17b", 0); - const transfer = new NextTokenTransfer.TokenTransfer(token, 10); + const transfer = new NextTokenTransfer(token, 10); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -186,9 +186,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const fooToken = new Token("FOO-6ce17b", 0); - const fooTransfer = new NextTokenTransfer.TokenTransfer(fooToken, 10); + const fooTransfer = new NextTokenTransfer(fooToken, 10); const barToken = new Token("BAR-5bc08f", 0); - const barTransfer = new NextTokenTransfer.TokenTransfer(barToken, 3140); + const barTransfer = new NextTokenTransfer(barToken, 3140); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -229,7 +229,7 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const token = new Token("NFT-123456", 1); - const transfer = new NextTokenTransfer.TokenTransfer(token, 1); + const transfer = new NextTokenTransfer(token, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, @@ -270,9 +270,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const firstToken = new Token("NFT-123456", 1); - const firstTransfer = new NextTokenTransfer.TokenTransfer(firstToken, 1); + const firstTransfer = new NextTokenTransfer(firstToken, 1); const secondToken = new Token("NFT-123456", 42); - const secondTransfer = new NextTokenTransfer.TokenTransfer(secondToken, 1); + const secondTransfer = new NextTokenTransfer(secondToken, 1); const executeDraft = factory.createTransactionForExecute({ sender: sender, diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 638cd7834..143913adf 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -84,7 +84,7 @@ export class SmartContractTransactionsFactory { gasLimit: BigNumber.Value; args?: any[]; nativeTransferAmount?: BigNumber.Value; - tokenTransfers?: NextTokenTransfer.TokenTransfer[]; + tokenTransfers?: NextTokenTransfer[]; }): DraftTransaction { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 9f9bd19e6..512cd2eb8 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -9,13 +9,13 @@ export class TokenTransfersDataBuilder { this.tokenComputer = new TokenComputer(); } - buildArgsForESDTTransfer(transfer: NextTokenTransfer.TokenTransfer): string[] { + buildArgsForESDTTransfer(transfer: NextTokenTransfer): string[] { let args = ["ESDTTransfer"]; args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); return args; } - buildArgsForSingleESDTNFTTransfer(transfer: NextTokenTransfer.TokenTransfer, receiver: IAddress) { + buildArgsForSingleESDTNFTTransfer(transfer: NextTokenTransfer, receiver: IAddress) { let args = ["ESDTNFTTransfer"]; const token = transfer.token; @@ -32,7 +32,7 @@ export class TokenTransfersDataBuilder { return args; } - buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NextTokenTransfer.TokenTransfer[]) { + buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NextTokenTransfer[]) { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { From baa017daae52575d6467faa6630e7cb78b5a191c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 14:47:15 +0300 Subject: [PATCH 042/275] small merge fix & formatting --- .../tokenTransfersDataBuilder.ts | 2 +- .../transferTransactionsFactory.spec.ts | 31 +++++++++------- .../transferTransactionsFactory.ts | 36 ++++++++++--------- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 028d463ba..512cd2eb8 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -36,7 +36,7 @@ export class TokenTransfersDataBuilder { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { - const identifier = this.tokenComputer.ensureIdentifierHasCorrectStructure(transfer.token.identifier); + const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); args.push( ...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)] ); diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 542b9656f..8f8e3cac0 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -1,6 +1,6 @@ import { assert } from "chai"; import { Address } from "../address"; -import { Token, TokenTransfer } from "../tokens"; +import { Token, NextTokenTransfer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transferTransactionsFactory"; @@ -15,7 +15,7 @@ describe("test transfer transcations factory", function () { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, - nativeAmount: "1000000000000000000" + nativeAmount: "1000000000000000000", }); assert.equal(transaction.sender, alice.bech32()); @@ -30,7 +30,7 @@ describe("test transfer transcations factory", function () { sender: alice, receiver: bob, nativeAmount: "1000000000000000000", - data: "test data" + data: "test data", }); assert.equal(transaction.sender, alice.bech32()); @@ -42,12 +42,12 @@ describe("test transfer transcations factory", function () { it("should create draft transaction for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0); - const transfer = new TokenTransfer(fooToken, 1000000); + const transfer = new NextTokenTransfer(fooToken, 1000000); const transaction = factory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); assert.equal(transaction.sender, alice.bech32()); @@ -59,39 +59,44 @@ describe("test transfer transcations factory", function () { it("should create draft transaction for nft transfer", async () => { const nft = new Token("NFT-123456", 10); - const transfer = new TokenTransfer(nft, 1); + const transfer = new NextTokenTransfer(nft, 1); const transaction = factory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, - tokenTransfers: [transfer] + tokenTransfers: [transfer], }); assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, alice.bech32()); assert.equal(transaction.value.valueOf(), "0"); assert.equal(transaction.gasLimit.valueOf(), "1210500"); - assert.deepEqual(transaction.data.toString(), "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8"); + assert.deepEqual( + transaction.data.toString(), + "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8" + ); }); it("should create draft transaction for multiple nft transfers", async () => { const firstNft = new Token("NFT-123456", 10); - const firstTransfer = new TokenTransfer(firstNft, 1); + const firstTransfer = new NextTokenTransfer(firstNft, 1); const secondNft = new Token("TEST-987654", 1); - const secondTransfer = new TokenTransfer(secondNft, 1); + const secondTransfer = new NextTokenTransfer(secondNft, 1); const transaction = factory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, - tokenTransfers: [firstTransfer, secondTransfer] + tokenTransfers: [firstTransfer, secondTransfer], }); assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, alice.bech32()); assert.equal(transaction.value.valueOf(), "0"); assert.equal(transaction.gasLimit.valueOf(), "1466000"); - assert.deepEqual(transaction.data.toString(), "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01"); + assert.deepEqual( + transaction.data.toString(), + "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01" + ); }); - }); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 0e792ec02..9b027c1c5 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -3,13 +3,13 @@ import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { IAddress } from "../interface"; import { DraftTransaction } from "../draftTransaction"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; -import { TokenComputer, TokenTransfer } from "../tokens"; +import { TokenComputer, NextTokenTransfer } from "../tokens"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; interface IConfig { - chainID: string + chainID: string; minGasLimit: BigNumber.Value; gasLimitPerByte: BigNumber.Value; gasLimitESDTTransfer: BigNumber.Value; @@ -27,10 +27,10 @@ export class TransferTransactionsFactory { } createTransactionForNativeTokenTransfer(options: { - sender: IAddress, - receiver: IAddress, - nativeAmount: BigNumber.Value, - data?: string + sender: IAddress; + receiver: IAddress; + nativeAmount: BigNumber.Value; + data?: string; }): DraftTransaction { const data = options.data || ""; return new DraftTransactionBuilder({ @@ -40,14 +40,14 @@ export class TransferTransactionsFactory { dataParts: [data], gasLimit: 0, addDataMovementGas: true, - amount: options.nativeAmount + amount: options.nativeAmount, }).build(); } createTransactionForESDTTokenTransfer(options: { - sender: IAddress, - receiver: IAddress, - tokenTransfers: TokenTransfer[] + sender: IAddress; + receiver: IAddress; + tokenTransfers: NextTokenTransfer[]; }): DraftTransaction { const numberOfTransfers = options.tokenTransfers.length; let receiver = options.receiver; @@ -61,15 +61,17 @@ export class TransferTransactionsFactory { if (tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER)); - } - else { + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) + ); + } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) + ); receiver = options.sender; } - } - else if (numberOfTransfers > 1) { + } else if (numberOfTransfers > 1) { transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) @@ -83,7 +85,7 @@ export class TransferTransactionsFactory { receiver: receiver, dataParts: transferArgs, gasLimit: extraGasForTransfer, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } } From 8951aea2e47a1d483387a39b3d962050cd2b5687 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 15:25:00 +0300 Subject: [PATCH 043/275] add extra check for no transfer and unit test --- .../transferTransactionsFactory.spec.ts | 17 +++++++++++++++++ .../transferTransactionsFactory.ts | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 8f8e3cac0..ce15eb858 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -3,6 +3,7 @@ import { Address } from "../address"; import { Token, NextTokenTransfer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transferTransactionsFactory"; +import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -11,6 +12,22 @@ describe("test transfer transcations factory", function () { const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); + it.only("should throw error, no token transfer provided", async () => { + let transfers: any = []; + + assert.throw( + () => { + factory.createTransactionForESDTTokenTransfer({ + sender: alice, + receiver: bob, + tokenTransfers: transfers, + }); + }, + ErrBadUsage, + "No token transfer has been provided" + ); + }); + it("should create draft transaction for native token transfer without data", async () => { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 9b027c1c5..782a58934 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -4,6 +4,7 @@ import { IAddress } from "../interface"; import { DraftTransaction } from "../draftTransaction"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { TokenComputer, NextTokenTransfer } from "../tokens"; +import { ErrBadUsage } from "../errors"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -56,7 +57,9 @@ export class TransferTransactionsFactory { let extraGasForTransfer = new BigNumber(0); const tokenComputer = new TokenComputer(); - if (numberOfTransfers === 1) { + if (numberOfTransfers == 0) { + throw new ErrBadUsage("No token transfer has been provided"); + } else if (numberOfTransfers == 1) { const transfer = options.tokenTransfers[0]; if (tokenComputer.isFungible(transfer.token)) { @@ -71,7 +74,7 @@ export class TransferTransactionsFactory { ); receiver = options.sender; } - } else if (numberOfTransfers > 1) { + } else { transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) From 167c6201b9c1434237c271de0f11818a103ad282 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 16:14:03 +0300 Subject: [PATCH 044/275] fixes after review --- .../transferTransactionsFactory.spec.ts | 2 +- src/transactionsFactories/transferTransactionsFactory.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index ce15eb858..4f13ee5d4 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -12,7 +12,7 @@ describe("test transfer transcations factory", function () { const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); - it.only("should throw error, no token transfer provided", async () => { + it("should throw error, no token transfer provided", async () => { let transfers: any = []; assert.throw( diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 782a58934..dfef06000 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -57,9 +57,11 @@ export class TransferTransactionsFactory { let extraGasForTransfer = new BigNumber(0); const tokenComputer = new TokenComputer(); - if (numberOfTransfers == 0) { + if (numberOfTransfers === 0) { throw new ErrBadUsage("No token transfer has been provided"); - } else if (numberOfTransfers == 1) { + } + + if (numberOfTransfers === 1) { const transfer = options.tokenTransfers[0]; if (tokenComputer.isFungible(transfer.token)) { From 2bb7efa3142f02b3d6f125441fcdf55ca6beab4c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 16:35:50 +0300 Subject: [PATCH 045/275] refactoring --- .../transferTransactionsFactory.spec.ts | 4 +- .../transferTransactionsFactory.ts | 71 ++++++++++++------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 4f13ee5d4..1f3b21deb 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -1,13 +1,13 @@ import { assert } from "chai"; import { Address } from "../address"; -import { Token, NextTokenTransfer } from "../tokens"; +import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transferTransactionsFactory"; import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); - const factory = new TransferTransactionsFactory(config); + const factory = new TransferTransactionsFactory(config, new TokenComputer()); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index dfef06000..fbc76c47a 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -3,7 +3,7 @@ import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { IAddress } from "../interface"; import { DraftTransaction } from "../draftTransaction"; import { DraftTransactionBuilder } from "./draftTransactionBuilder"; -import { TokenComputer, NextTokenTransfer } from "../tokens"; +import { NextTokenTransfer, Token } from "../tokens"; import { ErrBadUsage } from "../errors"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; @@ -18,12 +18,18 @@ interface IConfig { gasLimitMultiESDTNFTTransfer: BigNumber.Value; } +interface TokenComputer { + isFungible(token: Token): boolean; +} + export class TransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; + private readonly tokenComputer: TokenComputer; - constructor(config: IConfig) { + constructor(config: IConfig, tokenComputer: TokenComputer) { this.config = config; + this.tokenComputer = tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } @@ -51,36 +57,53 @@ export class TransferTransactionsFactory { tokenTransfers: NextTokenTransfer[]; }): DraftTransaction { const numberOfTransfers = options.tokenTransfers.length; - let receiver = options.receiver; - - let transferArgs: string[] = []; - let extraGasForTransfer = new BigNumber(0); - const tokenComputer = new TokenComputer(); if (numberOfTransfers === 0) { throw new ErrBadUsage("No token transfer has been provided"); } if (numberOfTransfers === 1) { - const transfer = options.tokenTransfers[0]; + return this.createSingleESDTTransferDraft(options); + } + + let receiver = options.receiver; + + const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); + const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + .multipliedBy(new BigNumber(numberOfTransfers)) + .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + receiver = options.sender; + + return new DraftTransactionBuilder({ + config: this.config, + sender: options.sender, + receiver: receiver, + dataParts: transferArgs, + gasLimit: extraGasForTransfer, + addDataMovementGas: true, + }).build(); + } + + private createSingleESDTTransferDraft(options: { + sender: IAddress; + receiver: IAddress; + tokenTransfers: NextTokenTransfer[]; + }): DraftTransaction { + let transferArgs: string[] = []; + const transfer = options.tokenTransfers[0]; + let extraGasForTransfer = new BigNumber(0); + let receiver = options.receiver; - if (tokenComputer.isFungible(transfer.token)) { - transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) - ); - } else { - transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) - ); - receiver = options.sender; - } + if (this.tokenComputer.isFungible(transfer.token)) { + transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) + ); } else { - transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); - extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) - .multipliedBy(new BigNumber(numberOfTransfers)) - .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) + ); receiver = options.sender; } From 10ee598dfe223bce8404ab251c581f095146087c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 26 Oct 2023 16:45:23 +0300 Subject: [PATCH 046/275] remove unnecessary variable --- src/transactionsFactories/transferTransactionsFactory.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index fbc76c47a..588c740e3 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -66,18 +66,19 @@ export class TransferTransactionsFactory { return this.createSingleESDTTransferDraft(options); } - let receiver = options.receiver; + const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + options.receiver, + options.tokenTransfers + ); - const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, options.tokenTransfers); const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); - receiver = options.sender; return new DraftTransactionBuilder({ config: this.config, sender: options.sender, - receiver: receiver, + receiver: options.sender, dataParts: transferArgs, gasLimit: extraGasForTransfer, addDataMovementGas: true, From 0905c6fba35532718545ec76911c763bcf9cdfe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 31 Oct 2023 17:33:32 +0200 Subject: [PATCH 047/275] Alpha release. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff363cb15..0ffb2e381 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.12.0", + "version": "13.0.0-alpha.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.12.0", + "version": "13.0.0-alpha.0", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 74ae6b1a0..407f0c6b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.12.0", + "version": "13.0.0-alpha.0", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 90b8c948b5bbba99d5b7c97b05a14f8b43ba4b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 15 Nov 2023 17:27:04 +0200 Subject: [PATCH 048/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 266b424f5..eb20d865d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.14.0", + "version": "13.0.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.14.0", + "version": "13.0.0-alpha.1", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 03a9351f3..64d6b594c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.14.0", + "version": "13.0.0-alpha.1", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From ad8b733887db562c2ffda828751eebb9e8226b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 15 Nov 2023 18:14:15 +0200 Subject: [PATCH 049/275] Breaking (but small) change: remove some previously deprecated items. --- src/interfaceOfNetwork.ts | 10 -------- src/smartcontracts/interaction.ts | 24 ++++--------------- .../transactionPayloadBuilders.ts | 4 ---- .../tokenOperationsFactory.test.net.spec.ts | 10 -------- src/tokenOperations/tokenOperationsFactory.ts | 10 -------- 5 files changed, 4 insertions(+), 54 deletions(-) diff --git a/src/interfaceOfNetwork.ts b/src/interfaceOfNetwork.ts index 07edeb9e6..942a9b5ff 100644 --- a/src/interfaceOfNetwork.ts +++ b/src/interfaceOfNetwork.ts @@ -66,16 +66,6 @@ export interface ITransactionLogs { events: ITransactionEvent[]; findSingleOrNoneEvent(identifier: string, predicate?: (event: ITransactionEvent) => boolean): ITransactionEvent | undefined; - - /** - * @deprecated Will be removed from the interface (with no replacement). Not used in "sdk-core". - */ - findFirstOrNoneEvent(identifier: string, predicate?: (event: ITransactionEvent) => boolean): ITransactionEvent | undefined; - - /** - * @deprecated Will be removed from the interface (with no replacement). Not used in "sdk-core". - */ - findEvents(identifier: string, predicate?: (event: ITransactionEvent) => boolean): ITransactionEvent[]; } export interface ITransactionEvent { diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index 243a0974d..1b5b71f37 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -150,34 +150,18 @@ export class Interaction { } withSingleESDTNFTTransfer(transfer: ITokenTransfer): Interaction; - /** - * @deprecated do not pass the "sender" parameter. Make sure to call "withSender()", instead. - */ - withSingleESDTNFTTransfer(transfer: ITokenTransfer, sender?: IAddress): Interaction; - withSingleESDTNFTTransfer(transfer: ITokenTransfer, sender?: IAddress): Interaction { + + withSingleESDTNFTTransfer(transfer: ITokenTransfer): Interaction { this.isWithSingleESDTNFTTransfer = true; this.tokenTransfers = new TokenTransfersWithinInteraction([transfer], this); - - if (sender) { - this.sender = sender; - } - return this; } withMultiESDTNFTTransfer(transfers: ITokenTransfer[]): Interaction; - /** - * @deprecated do not pass the "sender" parameter. Make sure to call "withSender()", instead. - */ - withMultiESDTNFTTransfer(transfers: ITokenTransfer[], sender?: IAddress): Interaction; - withMultiESDTNFTTransfer(transfers: ITokenTransfer[], sender?: IAddress): Interaction { + + withMultiESDTNFTTransfer(transfers: ITokenTransfer[]): Interaction { this.isWithMultiESDTNFTTransfer = true; this.tokenTransfers = new TokenTransfersWithinInteraction(transfers, this); - - if (sender) { - this.sender = sender; - } - return this; } diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index d03c50f1a..07e65276a 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -4,10 +4,6 @@ import { ArgSerializer } from "./argSerializer"; import { ICode, ICodeMetadata, IContractFunction } from "./interface"; import { TypedValue } from "./typesystem"; -/** - * @deprecated This constant should not be used. Use {@link WasmVirtualMachine} instead. - */ -export const ArwenVirtualMachine = "0500"; export const WasmVirtualMachine = "0500"; /** diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts index f434fd7f3..54344e4df 100644 --- a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts +++ b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts @@ -135,8 +135,6 @@ describe("test factory on testnet", function () { canFreeze: true, canWipe: true, canPause: true, - canMint: true, - canBurn: true, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true, @@ -184,8 +182,6 @@ describe("test factory on testnet", function () { canFreeze: true, canWipe: true, canPause: true, - canMint: true, - canBurn: true, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true, @@ -253,8 +249,6 @@ describe("test factory on testnet", function () { canFreeze: true, canWipe: true, canPause: true, - canMint: true, - canBurn: true, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true, @@ -312,8 +306,6 @@ describe("test factory on testnet", function () { canFreeze: true, canWipe: true, canPause: true, - canMint: true, - canBurn: true, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true, @@ -381,8 +373,6 @@ describe("test factory on testnet", function () { canFreeze: true, canWipe: true, canPause: true, - canMint: true, - canBurn: true, canChangeOwner: true, canUpgrade: true, canAddSpecialRoles: true, diff --git a/src/tokenOperations/tokenOperationsFactory.ts b/src/tokenOperations/tokenOperationsFactory.ts index b41e85595..dfc02b5d9 100644 --- a/src/tokenOperations/tokenOperationsFactory.ts +++ b/src/tokenOperations/tokenOperationsFactory.ts @@ -48,16 +48,6 @@ interface IIssueFungibleArgs extends IBaseArgs { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - - /** - * @deprecated (not used anymore) - */ - canMint?: boolean; - - /** - * @deprecated (not used anymore) - */ - canBurn?: boolean; } interface IIssueSemiFungibleArgs extends IBaseArgs { From 8498f3e2e28426a759f030ef7982215f04f72056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 28 Nov 2023 18:23:42 +0200 Subject: [PATCH 050/275] Fix after merge. Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- src/smartcontracts/codeMetadata.spec.ts | 2 ++ src/smartcontracts/codeMetadata.ts | 17 +++-------------- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index aab51dfc0..bc8d04880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.15.0", + "version": "v13.0.0-alpha.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.15.0", + "version": "v13.0.0-alpha.2", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 9a87d744c..394d74d22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.15.0", + "version": "v13.0.0-alpha.2", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/smartcontracts/codeMetadata.spec.ts b/src/smartcontracts/codeMetadata.spec.ts index 314d4a954..685d8cf5f 100644 --- a/src/smartcontracts/codeMetadata.spec.ts +++ b/src/smartcontracts/codeMetadata.spec.ts @@ -1,3 +1,5 @@ +import { assert } from "chai"; +import { CodeMetadata } from "./codeMetadata"; describe("CodeMetadata Class Tests", function () { it("should create a default CodeMetadata instance", function () { diff --git a/src/smartcontracts/codeMetadata.ts b/src/smartcontracts/codeMetadata.ts index 611fe0ddb..2133e66e2 100644 --- a/src/smartcontracts/codeMetadata.ts +++ b/src/smartcontracts/codeMetadata.ts @@ -6,6 +6,7 @@ export class CodeMetadata { public readable: boolean; public payable: boolean; public payableBySc: boolean; + private static readonly codeMetadataLength = 2; static ByteZero = { Upgradeable: 1, @@ -35,26 +36,14 @@ export class CodeMetadata { } static fromBytes(bytes: Uint8Array): CodeMetadata { - if (bytes.length !== this.codeMetadataLength) { - return new CodeMetadata(); - } - - const byteZero = bytes[0]; - const byteOne = bytes[1]; - - const upgradeable = (byteZero & ByteZero.Upgradeable) !== 0; - const readable = (byteZero & ByteZero.Readable) !== 0; - const payable = (byteOne & ByteOne.Payable) !== 0; - const payableBySc = (byteOne & ByteOne.PayableBySc) !== 0; - - return new CodeMetadata(upgradeable, readable, payable, payableBySc); + return CodeMetadata.fromBuffer(Buffer.from(bytes)); } /** * Creates a metadata object from a buffer. */ static fromBuffer(buffer: Buffer): CodeMetadata { - if (buffer.length < 2) { + if (buffer.length < this.codeMetadataLength) { throw new Error('Buffer is too short.'); } From de3c1a30ac63a719dd3a51ccb789dcd71d4383d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 29 Nov 2023 12:37:36 +0200 Subject: [PATCH 051/275] Fix unit test. --- src/smartcontracts/nativeSerializer.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smartcontracts/nativeSerializer.spec.ts b/src/smartcontracts/nativeSerializer.spec.ts index f24e82389..2a8cb2333 100644 --- a/src/smartcontracts/nativeSerializer.spec.ts +++ b/src/smartcontracts/nativeSerializer.spec.ts @@ -291,7 +291,7 @@ describe("test native serializer", () => { }, { "type": "tuple>", }, { - "type": "List>>", + "type": "List>", }, { "type": "u64" }], From 7b78bab6edc0b47f90bb430a359e48be85464017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 29 Nov 2023 14:57:50 +0200 Subject: [PATCH 052/275] Adjust some exports (e.g. for transactions factories). --- src/index.ts | 1 + src/transactionsFactories/index.ts | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 src/transactionsFactories/index.ts diff --git a/src/index.ts b/src/index.ts index cb6d00477..545ba1904 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ export * from "./signableMessage"; export * from "./smartcontracts"; export * from "./tokenOperations"; export * from "./tokenTransfer"; +export * from "./tokens"; export * from "./transaction"; export * from "./transactionPayload"; export * from "./transactionWatcher"; diff --git a/src/transactionsFactories/index.ts b/src/transactionsFactories/index.ts new file mode 100644 index 000000000..79cd9a638 --- /dev/null +++ b/src/transactionsFactories/index.ts @@ -0,0 +1,5 @@ +export * from "./delegationTransactionsFactory"; +export * from "./smartContractTransactionsFactory"; +export * from "./tokenManagementTransactionsFactory"; +export * from "./transactionsFactoryConfig"; +export * from "./transferTransactionsFactory"; From 5228b88849b285661ce90fc16c26ef992555c1ef Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 12 Dec 2023 18:19:12 +0200 Subject: [PATCH 053/275] mark old stuff as deprecated --- src/tokenOperations/tokenOperationsFactory.ts | 107 ++++++++---------- .../tokenOperationsFactoryConfig.ts | 7 +- .../transferTransactionsFactory.spec.ts | 4 +- .../transferTransactionsFactory.ts | 2 +- src/transferTransactionsFactory.ts | 39 ++++--- 5 files changed, 80 insertions(+), 79 deletions(-) diff --git a/src/tokenOperations/tokenOperationsFactory.ts b/src/tokenOperations/tokenOperationsFactory.ts index dfc02b5d9..3d93592d7 100644 --- a/src/tokenOperations/tokenOperationsFactory.ts +++ b/src/tokenOperations/tokenOperationsFactory.ts @@ -63,8 +63,7 @@ interface IIssueSemiFungibleArgs extends IBaseArgs { canAddSpecialRoles: boolean; } -interface IIssueNonFungibleArgs extends IIssueSemiFungibleArgs { -} +interface IIssueNonFungibleArgs extends IIssueSemiFungibleArgs {} interface IRegisterMetaESDT extends IIssueSemiFungibleArgs { numDecimals: number; @@ -146,14 +145,14 @@ interface ILocalMintArgs extends IBaseArgs { manager: IAddress; user: IAddress; tokenIdentifier: string; - supplyToMint: BigNumber.Value + supplyToMint: BigNumber.Value; } interface ILocalBurnArgs extends IBaseArgs { manager: IAddress; user: IAddress; tokenIdentifier: string; - supplyToBurn: BigNumber.Value + supplyToBurn: BigNumber.Value; } interface IUpdateAttributesArgs extends IBaseArgs { @@ -167,16 +166,19 @@ interface IAddQuantityArgs extends IBaseArgs { manager: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; - quantityToAdd: BigNumber.Value + quantityToAdd: BigNumber.Value; } interface IBurnQuantityArgs extends IBaseArgs { manager: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; - quantityToBurn: BigNumber.Value + quantityToBurn: BigNumber.Value; } +/** + * @deprecated Use {@link TokenManagementTransactionsFactory} instead. + */ export class TokenOperationsFactory { private readonly config: IConfig; private readonly trueAsHex; @@ -211,7 +213,7 @@ export class TokenOperationsFactory { gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitIssue, - dataParts: parts + dataParts: parts, }); } @@ -248,7 +250,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitIssue, - dataParts: parts + dataParts: parts, }); } @@ -276,7 +278,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitIssue, - dataParts: parts + dataParts: parts, }); } @@ -305,7 +307,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitIssue, - dataParts: parts + dataParts: parts, }); } @@ -317,7 +319,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG utf8ToHex(args.tokenName), utf8ToHex(args.tokenTicker), utf8ToHex(args.tokenType), - bigIntToHex(args.numDecimals) + bigIntToHex(args.numDecimals), ]; return this.createTransaction({ @@ -328,15 +330,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitIssue, - dataParts: parts + dataParts: parts, }); } setBurnRoleGlobally(args: IToggleBurnRoleGloballyArgs): Transaction { - const parts = [ - "setBurnRoleGlobally", - utf8ToHex(args.tokenIdentifier) - ]; + const parts = ["setBurnRoleGlobally", utf8ToHex(args.tokenIdentifier)]; return this.createTransaction({ sender: args.manager, @@ -345,15 +344,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally, - dataParts: parts + dataParts: parts, }); } unsetBurnRoleGlobally(args: IToggleBurnRoleGloballyArgs): Transaction { - const parts = [ - "unsetBurnRoleGlobally", - utf8ToHex(args.tokenIdentifier) - ]; + const parts = ["unsetBurnRoleGlobally", utf8ToHex(args.tokenIdentifier)]; return this.createTransaction({ sender: args.manager, @@ -362,7 +358,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitToggleBurnRoleGlobally, - dataParts: parts + dataParts: parts, }); } @@ -382,7 +378,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitSetSpecialRole, - dataParts: parts + dataParts: parts, }); } @@ -404,7 +400,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitSetSpecialRole, - dataParts: parts + dataParts: parts, }); } @@ -431,7 +427,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitSetSpecialRole, - dataParts: parts + dataParts: parts, }); } @@ -458,15 +454,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTNFTCreate.valueOf() + storageGasLimit.valueOf(), - dataParts: parts + dataParts: parts, }); } pause(args: IPausingArgs): Transaction { - const parts = [ - "pause", - utf8ToHex(args.tokenIdentifier) - ]; + const parts = ["pause", utf8ToHex(args.tokenIdentifier)]; return this.createTransaction({ sender: args.manager, @@ -475,15 +468,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitPausing, - dataParts: parts + dataParts: parts, }); } unpause(args: IPausingArgs): Transaction { - const parts = [ - "unPause", - utf8ToHex(args.tokenIdentifier) - ]; + const parts = ["unPause", utf8ToHex(args.tokenIdentifier)]; return this.createTransaction({ sender: args.manager, @@ -492,16 +482,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitPausing, - dataParts: parts + dataParts: parts, }); } freeze(args: IFreezingArgs): Transaction { - const parts = [ - "freeze", - utf8ToHex(args.tokenIdentifier), - addressToHex(args.user) - ]; + const parts = ["freeze", utf8ToHex(args.tokenIdentifier), addressToHex(args.user)]; return this.createTransaction({ sender: args.manager, @@ -510,7 +496,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitFreezing, - dataParts: parts + dataParts: parts, }); } @@ -528,7 +514,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitFreezing, - dataParts: parts + dataParts: parts, }); } @@ -546,7 +532,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitWiping, - dataParts: parts + dataParts: parts, }); } @@ -564,16 +550,12 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTLocalMint, - dataParts: parts + dataParts: parts, }); } localBurn(args: ILocalBurnArgs): Transaction { - const parts = [ - "ESDTLocalBurn", - utf8ToHex(args.tokenIdentifier), - bigIntToHex(args.supplyToBurn), - ]; + const parts = ["ESDTLocalBurn", utf8ToHex(args.tokenIdentifier), bigIntToHex(args.supplyToBurn)]; return this.createTransaction({ sender: args.manager, @@ -582,7 +564,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTLocalBurn, - dataParts: parts + dataParts: parts, }); } @@ -601,7 +583,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTNFTUpdateAttributes, - dataParts: parts + dataParts: parts, }); } @@ -610,7 +592,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG "ESDTNFTAddQuantity", utf8ToHex(args.tokenIdentifier), bigIntToHex(args.tokenNonce), - bigIntToHex(args.quantityToAdd) + bigIntToHex(args.quantityToAdd), ]; return this.createTransaction({ @@ -620,7 +602,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTNFTAddQuantity, - dataParts: parts + dataParts: parts, }); } @@ -629,7 +611,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG "ESDTNFTBurn", utf8ToHex(args.tokenIdentifier), bigIntToHex(args.tokenNonce), - bigIntToHex(args.quantityToBurn) + bigIntToHex(args.quantityToBurn), ]; return this.createTransaction({ @@ -639,11 +621,20 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG gasPrice: args.gasPrice, gasLimitHint: args.gasLimit, executionGasLimit: this.config.gasLimitESDTNFTBurn, - dataParts: parts + dataParts: parts, }); } - private createTransaction({ sender, receiver, nonce, value, gasPrice, gasLimitHint, executionGasLimit, dataParts }: { + private createTransaction({ + sender, + receiver, + nonce, + value, + gasPrice, + gasLimitHint, + executionGasLimit, + dataParts, + }: { sender: IAddress; receiver: IAddress; nonce?: INonce; @@ -668,7 +659,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG value: value || 0, data: payload, version: version, - options: options + options: options, }); } diff --git a/src/tokenOperations/tokenOperationsFactoryConfig.ts b/src/tokenOperations/tokenOperationsFactoryConfig.ts index ef9731bf0..e1ebb54dd 100644 --- a/src/tokenOperations/tokenOperationsFactoryConfig.ts +++ b/src/tokenOperations/tokenOperationsFactoryConfig.ts @@ -2,6 +2,9 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; import { IAddress, IChainID, IGasLimit, IGasPrice } from "../interface"; +/** + * @deprecated Use {@link TransactionsFactoryConfig} instead. + */ export class TokenOperationsFactoryConfig { chainID: IChainID; minGasPrice: IGasPrice = 1000000000; @@ -21,7 +24,9 @@ export class TokenOperationsFactoryConfig { gasLimitESDTNFTBurn: IGasLimit = 1000000; gasLimitStorePerByte: IGasLimit = 50000; issueCost: BigNumber.Value = "50000000000000000"; - esdtContractAddress: IAddress = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); + esdtContractAddress: IAddress = Address.fromBech32( + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + ); constructor(chainID: IChainID) { this.chainID = chainID; diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 1f3b21deb..b4b06da38 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -2,12 +2,12 @@ import { assert } from "chai"; import { Address } from "../address"; import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import { TransferTransactionsFactory } from "./transferTransactionsFactory"; +import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); - const factory = new TransferTransactionsFactory(config, new TokenComputer()); + const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 588c740e3..3f52930ba 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -22,7 +22,7 @@ interface TokenComputer { isFungible(token: Token): boolean; } -export class TransferTransactionsFactory { +export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; private readonly tokenComputer: TokenComputer; diff --git a/src/transferTransactionsFactory.ts b/src/transferTransactionsFactory.ts index 7444bfde5..3e312df95 100644 --- a/src/transferTransactionsFactory.ts +++ b/src/transferTransactionsFactory.ts @@ -11,6 +11,9 @@ interface IGasEstimator { forMultiESDTNFTTransfer(dataLength: number, numTransfers: number): number; } +/** + * @deprecated Use {@link NextTransferTransactionsFactory} instead. + */ export class TransferTransactionsFactory { private readonly gasEstimator; @@ -39,12 +42,12 @@ export class TransferTransactionsFactory { gasPrice: args.gasPrice, gasLimit: args.gasLimit || estimatedGasLimit, data: args.data, - chainID: args.chainID + chainID: args.chainID, }); } createESDTTransfer(args: { - tokenTransfer: ITokenTransfer, + tokenTransfer: ITokenTransfer; nonce?: INonce; receiver: IAddress; sender: IAddress; @@ -71,12 +74,12 @@ export class TransferTransactionsFactory { gasPrice: args.gasPrice, gasLimit: args.gasLimit || estimatedGasLimit, data: transactionPayload, - chainID: args.chainID + chainID: args.chainID, }); } createESDTNFTTransfer(args: { - tokenTransfer: ITokenTransfer, + tokenTransfer: ITokenTransfer; nonce?: INonce; destination: IAddress; sender: IAddress; @@ -92,7 +95,7 @@ export class TransferTransactionsFactory { // The transferred quantity new BigUIntValue(args.tokenTransfer.valueOf()), // The destination address - new AddressValue(args.destination) + new AddressValue(args.destination), ]); const data = `ESDTNFTTransfer@${argumentsString}`; @@ -107,12 +110,12 @@ export class TransferTransactionsFactory { gasPrice: args.gasPrice, gasLimit: args.gasLimit || estimatedGasLimit, data: transactionPayload, - chainID: args.chainID + chainID: args.chainID, }); } createMultiESDTNFTTransfer(args: { - tokenTransfers: ITokenTransfer[], + tokenTransfers: ITokenTransfer[]; nonce?: INonce; destination: IAddress; sender: IAddress; @@ -124,18 +127,20 @@ export class TransferTransactionsFactory { // The destination address new AddressValue(args.destination), // Number of tokens - new U16Value(args.tokenTransfers.length) + new U16Value(args.tokenTransfers.length), ]; for (const payment of args.tokenTransfers) { - parts.push(...[ - // The token identifier - BytesValue.fromUTF8(payment.tokenIdentifier), - // The nonce of the token - new U64Value(payment.nonce), - // The transfered quantity - new BigUIntValue(payment.valueOf()) - ]); + parts.push( + ...[ + // The token identifier + BytesValue.fromUTF8(payment.tokenIdentifier), + // The nonce of the token + new U64Value(payment.nonce), + // The transfered quantity + new BigUIntValue(payment.valueOf()), + ] + ); } const { argumentsString } = new ArgSerializer().valuesToString(parts); @@ -151,7 +156,7 @@ export class TransferTransactionsFactory { gasPrice: args.gasPrice, gasLimit: args.gasLimit || estimatedGasLimit, data: transactionPayload, - chainID: args.chainID + chainID: args.chainID, }); } } From 4ad55635efeea2c51666faaad9f5eb08a82d0a2a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Dec 2023 12:37:43 +0200 Subject: [PATCH 054/275] fix flags for creating token operations transactions --- ...anagementTransactionIntentsFactory.spec.ts | 25 +- .../tokenManagementTransactionsFactory.ts | 263 +++++++++--------- 2 files changed, 138 insertions(+), 150 deletions(-) diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 01b495068..4ef3502ed 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -42,13 +42,12 @@ describe("test token management transactions factory", () => { canFreeze: true, canWipe: true, canPause: true, - canTransferNFTCreateRole: false, canChangeOwner: true, - canUpgrade: true, - canAddSpecialRoles: true + canUpgrade: false, + canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.deepEqual(draft.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); assert.equal(draft.sender, frank.address.toString()); assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); assert.deepEqual(draft.value, config.issueCost); @@ -64,11 +63,11 @@ describe("test token management transactions factory", () => { canPause: true, canTransferNFTCreateRole: true, canChangeOwner: true, - canUpgrade: true, - canAddSpecialRoles: true + canUpgrade: false, + canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.deepEqual(draft.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); assert.equal(draft.sender, frank.address.toString()); assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); assert.deepEqual(draft.value, config.issueCost); @@ -84,11 +83,11 @@ describe("test token management transactions factory", () => { canPause: true, canTransferNFTCreateRole: true, canChangeOwner: true, - canUpgrade: true, - canAddSpecialRoles: true + canUpgrade: false, + canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.deepEqual(draft.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); assert.equal(draft.sender, frank.address.toString()); assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); assert.deepEqual(draft.value, config.issueCost); @@ -105,11 +104,11 @@ describe("test token management transactions factory", () => { canPause: true, canTransferNFTCreateRole: true, canChangeOwner: true, - canUpgrade: true, - canAddSpecialRoles: true + canUpgrade: false, + canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@74727565@63616e4164645370656369616c526f6c6573@74727565")); + assert.deepEqual(draft.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); assert.equal(draft.sender, frank.address.toString()); assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); assert.deepEqual(draft.value, config.issueCost); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 1cb05cf88..13c957512 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -8,23 +8,23 @@ import { Address } from "../address"; import { Logger } from "../logger"; interface Config { - chainID: string - minGasLimit: BigNumber.Value - gasLimitPerByte: BigNumber.Value - gasLimitIssue: BigNumber.Value - gasLimitToggleBurnRoleGlobally: BigNumber.Value - gasLimitEsdtLocalMint: BigNumber.Value - gasLimitEsdtLocalBurn: BigNumber.Value - gasLimitSetSpecialRole: BigNumber.Value - gasLimitPausing: BigNumber.Value - gasLimitFreezing: BigNumber.Value - gasLimitWiping: BigNumber.Value - gasLimitEsdtNftCreate: BigNumber.Value - gasLimitEsdtNftUpdateAttributes: BigNumber.Value - gasLimitEsdtNftAddQuantity: BigNumber.Value - gasLimitEsdtNftBurn: BigNumber.Value - gasLimitStorePerByte: BigNumber.Value - issueCost: BigNumber.Value + chainID: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; + gasLimitIssue: BigNumber.Value; + gasLimitToggleBurnRoleGlobally: BigNumber.Value; + gasLimitEsdtLocalMint: BigNumber.Value; + gasLimitEsdtLocalBurn: BigNumber.Value; + gasLimitSetSpecialRole: BigNumber.Value; + gasLimitPausing: BigNumber.Value; + gasLimitFreezing: BigNumber.Value; + gasLimitWiping: BigNumber.Value; + gasLimitEsdtNftCreate: BigNumber.Value; + gasLimitEsdtNftUpdateAttributes: BigNumber.Value; + gasLimitEsdtNftAddQuantity: BigNumber.Value; + gasLimitEsdtNftBurn: BigNumber.Value; + gasLimitStorePerByte: BigNumber.Value; + issueCost: BigNumber.Value; } type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; @@ -32,25 +32,26 @@ type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly trueAsHex: string; + private readonly falseAsHex: string; constructor(config: Config) { this.config = config; this.trueAsHex = utf8ToHex("true"); + this.falseAsHex = utf8ToHex("false"); } createTransactionForIssuingFungible(options: { - sender: IAddress, - tokenName: string, - tokenTicker: string, - initialSupply: BigNumber.Value, - numDecimals: BigNumber.Value, - canFreeze: boolean, - canWipe: boolean, - canPause: boolean, - canTransferNFTCreateRole: boolean, - canChangeOwner: boolean, - canUpgrade: boolean, - canAddSpecialRoles: boolean + sender: IAddress; + tokenName: string; + tokenTicker: string; + initialSupply: BigNumber.Value; + numDecimals: BigNumber.Value; + canFreeze: boolean; + canWipe: boolean; + canPause: boolean; + canChangeOwner: boolean; + canUpgrade: boolean; + canAddSpecialRoles: boolean; }): DraftTransaction { this.notifyAboutUnsettingBurnRoleGlobally(); @@ -60,13 +61,18 @@ export class TokenManagementTransactionsFactory { utf8ToHex(options.tokenTicker), bigIntToHex(options.initialSupply), bigIntToHex(options.numDecimals), - ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), - ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), - ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), - ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), - ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], - ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] + utf8ToHex("canFreeze"), + options.canFreeze ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canWipe"), + options.canWipe ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canPause"), + options.canPause ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canChangeOwner"), + options.canChangeOwner ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canUpgrade"), + options.canUpgrade ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canAddSpecialRoles"), + options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return new DraftTransactionBuilder({ @@ -76,7 +82,7 @@ export class TokenManagementTransactionsFactory { dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - amount: this.config.issueCost + amount: this.config.issueCost, }).build(); } @@ -98,13 +104,20 @@ export class TokenManagementTransactionsFactory { "issueSemiFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), - ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), - ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), - ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), - ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], - ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] + utf8ToHex("canFreeze"), + options.canFreeze ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canWipe"), + options.canWipe ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canPause"), + options.canPause ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canTransferNFTCreateRole"), + options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canChangeOwner"), + options.canChangeOwner ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canUpgrade"), + options.canUpgrade ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canAddSpecialRoles"), + options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return new DraftTransactionBuilder({ @@ -114,7 +127,7 @@ export class TokenManagementTransactionsFactory { dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - amount: this.config.issueCost + amount: this.config.issueCost, }).build(); } @@ -136,13 +149,20 @@ export class TokenManagementTransactionsFactory { "issueNonFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), - ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), - ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), - ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), - ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...[utf8ToHex("canUpgrade"), boolToHex(options.canUpgrade)], - ...[utf8ToHex("canAddSpecialRoles"), boolToHex(options.canAddSpecialRoles)] + utf8ToHex("canFreeze"), + options.canFreeze ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canWipe"), + options.canWipe ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canPause"), + options.canPause ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canTransferNFTCreateRole"), + options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canChangeOwner"), + options.canChangeOwner ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canUpgrade"), + options.canUpgrade ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canAddSpecialRoles"), + options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return new DraftTransactionBuilder({ @@ -152,7 +172,7 @@ export class TokenManagementTransactionsFactory { dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - amount: this.config.issueCost + amount: this.config.issueCost, }).build(); } @@ -160,7 +180,7 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenName: string; tokenTicker: string; - numDecimals: BigNumber.Value, + numDecimals: BigNumber.Value; canFreeze: boolean; canWipe: boolean; canPause: boolean; @@ -176,13 +196,20 @@ export class TokenManagementTransactionsFactory { utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), bigIntToHex(options.numDecimals), - ...(options.canFreeze ? [utf8ToHex("canFreeze"), this.trueAsHex] : []), - ...(options.canWipe ? [utf8ToHex("canWipe"), this.trueAsHex] : []), - ...(options.canPause ? [utf8ToHex("canPause"), this.trueAsHex] : []), - ...(options.canTransferNFTCreateRole ? [utf8ToHex("canTransferNFTCreateRole"), this.trueAsHex] : []), - ...(options.canChangeOwner ? [utf8ToHex("canChangeOwner"), this.trueAsHex] : []), - ...(options.canUpgrade ? [utf8ToHex("canUpgrade"), this.trueAsHex] : []), - ...(options.canAddSpecialRoles ? [utf8ToHex("canAddSpecialRoles"), this.trueAsHex] : []), + utf8ToHex("canFreeze"), + options.canFreeze ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canWipe"), + options.canWipe ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canPause"), + options.canPause ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canTransferNFTCreateRole"), + options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canChangeOwner"), + options.canChangeOwner ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canUpgrade"), + options.canUpgrade ? this.trueAsHex : this.falseAsHex, + utf8ToHex("canAddSpecialRoles"), + options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return new DraftTransactionBuilder({ @@ -192,7 +219,7 @@ export class TokenManagementTransactionsFactory { dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - amount: this.config.issueCost + amount: this.config.issueCost, }).build(); } @@ -210,7 +237,7 @@ export class TokenManagementTransactionsFactory { utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), - bigIntToHex(options.numDecimals) + bigIntToHex(options.numDecimals), ]; return new DraftTransactionBuilder({ @@ -220,18 +247,15 @@ export class TokenManagementTransactionsFactory { dataParts: dataParts, gasLimit: this.config.gasLimitIssue, addDataMovementGas: true, - amount: this.config.issueCost + amount: this.config.issueCost, }).build(); } createTransactionForSettingBurnRoleGlobally(options: { - sender: IAddress, - tokenIdentifier: string + sender: IAddress; + tokenIdentifier: string; }): DraftTransaction { - const dataParts = [ - "setBurnRoleGlobally", - utf8ToHex(options.tokenIdentifier) - ]; + const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; return new DraftTransactionBuilder({ config: this.config, @@ -239,18 +263,15 @@ export class TokenManagementTransactionsFactory { receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitToggleBurnRoleGlobally, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForUnsettingBurnRoleGlobally(options: { - sender: IAddress, - tokenIdentifier: string + sender: IAddress; + tokenIdentifier: string; }): DraftTransaction { - const dataParts = [ - "unsetBurnRoleGlobally", - utf8ToHex(options.tokenIdentifier) - ]; + const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; return new DraftTransactionBuilder({ config: this.config, @@ -283,7 +304,7 @@ export class TokenManagementTransactionsFactory { receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -312,7 +333,7 @@ export class TokenManagementTransactionsFactory { receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -355,7 +376,7 @@ export class TokenManagementTransactionsFactory { receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), dataParts: dataParts, gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -390,18 +411,12 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit), - addDataMovementGas: true + addDataMovementGas: true, }).build(); } - createTransactionForPausing(options: { - sender: IAddress; - tokenIdentifier: string; - }): DraftTransaction { - const dataParts = [ - "pause", - utf8ToHex(options.tokenIdentifier) - ]; + createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): DraftTransaction { + const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; return new DraftTransactionBuilder({ config: this.config, @@ -409,18 +424,12 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitPausing, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } - createTransactionForUnpausing(options: { - sender: IAddress; - tokenIdentifier: string; - }): DraftTransaction { - const dataParts = [ - "unPause", - utf8ToHex(options.tokenIdentifier) - ]; + createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): DraftTransaction { + const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; return new DraftTransactionBuilder({ config: this.config, @@ -428,7 +437,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitPausing, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -437,11 +446,7 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): DraftTransaction { - const dataParts = [ - "freeze", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user) - ]; + const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; return new DraftTransactionBuilder({ config: this.config, @@ -449,7 +454,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitFreezing, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -458,11 +463,7 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): DraftTransaction { - const dataParts = [ - "UnFreeze", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user) - ]; + const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; return new DraftTransactionBuilder({ config: this.config, @@ -470,7 +471,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitFreezing, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -479,11 +480,7 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): DraftTransaction { - const dataParts = [ - "wipe", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user) - ]; + const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; return new DraftTransactionBuilder({ config: this.config, @@ -491,7 +488,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitWiping, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -500,11 +497,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToMint: BigNumber.Value; }): DraftTransaction { - const dataParts = [ - "ESDTLocalMint", - utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.supplyToMint), - ]; + const dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; return new DraftTransactionBuilder({ config: this.config, @@ -512,7 +505,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitEsdtLocalMint, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -521,11 +514,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToBurn: BigNumber.Value; }): DraftTransaction { - const dataParts = [ - "ESDTLocalBurn", - utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.supplyToBurn), - ]; + const dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; return new DraftTransactionBuilder({ config: this.config, @@ -533,7 +522,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitEsdtLocalBurn, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -541,7 +530,7 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; - attributes: Uint8Array + attributes: Uint8Array; }): DraftTransaction { const dataParts = [ "ESDTNFTUpdateAttributes", @@ -556,7 +545,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitEsdtNftUpdateAttributes, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -564,13 +553,13 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; - quantityToAdd: BigNumber.Value + quantityToAdd: BigNumber.Value; }): DraftTransaction { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), - bigIntToHex(options.quantityToAdd) + bigIntToHex(options.quantityToAdd), ]; return new DraftTransactionBuilder({ @@ -579,7 +568,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitEsdtNftAddQuantity, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } @@ -587,13 +576,13 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; tokenNonce: BigNumber.Value; - quantityToBurn: BigNumber.Value + quantityToBurn: BigNumber.Value; }): DraftTransaction { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), - bigIntToHex(options.quantityToBurn) + bigIntToHex(options.quantityToBurn), ]; return new DraftTransactionBuilder({ @@ -602,7 +591,7 @@ export class TokenManagementTransactionsFactory { receiver: options.sender, dataParts: dataParts, gasLimit: this.config.gasLimitEsdtNftBurn, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } From 9c8be3559197f0e0cfedcc260907ac2029687342 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 18 Dec 2023 15:10:58 +0200 Subject: [PATCH 055/275] remove old wallet package dev dependency --- package-lock.json | 79 ++----------------- package.json | 3 +- src/relayedTransactionV1Builder.spec.ts | 16 ++-- src/relayedTransactionV2Builder.spec.ts | 4 +- src/smartcontracts/interaction.spec.ts | 20 ++--- .../smartContract.local.net.spec.ts | 16 ++-- src/smartcontracts/smartContract.spec.ts | 8 +- .../smartContractResults.local.net.spec.ts | 2 +- src/testutils/utils.ts | 2 +- src/testutils/wallets.ts | 5 +- .../tokenOperationsFactory.test.net.spec.ts | 2 +- src/transaction.spec.ts | 20 ++--- .../delegationTransactionsFactory.spec.ts | 2 +- 13 files changed, 56 insertions(+), 123 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc8d04880..db9905f8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,7 @@ }, "devDependencies": { "@multiversx/sdk-network-providers": "2.2.0", - "@multiversx/sdk-wallet": "3.0.0", - "@multiversx/sdk-wallet-next": "npm:@multiversx/sdk-wallet@4.0.0", + "@multiversx/sdk-wallet": "4.2.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", "@types/mocha": "9.1.0", @@ -523,29 +522,9 @@ "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/@multiversx/sdk-wallet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-3.0.0.tgz", - "integrity": "sha512-nDVBtva1mpfutXA8TfUnpdeFqhY9O+deNU3U/Z41yPBcju1trHDC9gcKPyQqcQ3qjG/6LwEXmIm7Dc5fIsvVjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@multiversx/sdk-bls-wasm": "0.3.5", - "bech32": "1.1.4", - "bip39": "3.0.2", - "blake2b": "2.1.3", - "ed25519-hd-key": "1.1.2", - "ed2curve": "0.3.0", - "keccak": "3.0.1", - "scryptsy": "2.1.0", - "tweetnacl": "1.0.3", - "uuid": "8.3.2" - } - }, - "node_modules/@multiversx/sdk-wallet-next": { - "name": "@multiversx/sdk-wallet", - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.0.0.tgz", - "integrity": "sha512-Fskqg9AGgqSIAgN+Ag9Y/DIoZRr4qgB0baVZ1nlXhgaRuM30v1UeW0TAIhuAbXkkMiTOJyLaCeebUDYy1VJgWA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.2.0.tgz", + "integrity": "sha512-EjSb9AnqMcpmDjZ7ebkUpOzpTfxj1plTuVXwZ6AaqJsdpxMfrE2izbPy18+bg5xFlr8V27wYZcW8zOhkBR50BA==", "dev": true, "dependencies": { "@multiversx/sdk-bls-wasm": "0.3.5", @@ -562,20 +541,6 @@ "uuid": "8.3.2" } }, - "node_modules/@multiversx/sdk-wallet-next/node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@multiversx/sdk-wallet/node_modules/keccak": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", @@ -4852,39 +4817,9 @@ } }, "@multiversx/sdk-wallet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-3.0.0.tgz", - "integrity": "sha512-nDVBtva1mpfutXA8TfUnpdeFqhY9O+deNU3U/Z41yPBcju1trHDC9gcKPyQqcQ3qjG/6LwEXmIm7Dc5fIsvVjg==", - "dev": true, - "requires": { - "@multiversx/sdk-bls-wasm": "0.3.5", - "bech32": "1.1.4", - "bip39": "3.0.2", - "blake2b": "2.1.3", - "ed25519-hd-key": "1.1.2", - "ed2curve": "0.3.0", - "keccak": "3.0.1", - "scryptsy": "2.1.0", - "tweetnacl": "1.0.3", - "uuid": "8.3.2" - }, - "dependencies": { - "keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - } - } - }, - "@multiversx/sdk-wallet-next": { - "version": "npm:@multiversx/sdk-wallet@4.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.0.0.tgz", - "integrity": "sha512-Fskqg9AGgqSIAgN+Ag9Y/DIoZRr4qgB0baVZ1nlXhgaRuM30v1UeW0TAIhuAbXkkMiTOJyLaCeebUDYy1VJgWA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.2.0.tgz", + "integrity": "sha512-EjSb9AnqMcpmDjZ7ebkUpOzpTfxj1plTuVXwZ6AaqJsdpxMfrE2izbPy18+bg5xFlr8V27wYZcW8zOhkBR50BA==", "dev": true, "requires": { "@multiversx/sdk-bls-wasm": "0.3.5", diff --git a/package.json b/package.json index 394d74d22..5b98c6475 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,7 @@ }, "devDependencies": { "@multiversx/sdk-network-providers": "2.2.0", - "@multiversx/sdk-wallet": "3.0.0", - "@multiversx/sdk-wallet-next": "npm:@multiversx/sdk-wallet@4.0.0", + "@multiversx/sdk-wallet": "4.2.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", "@types/mocha": "9.1.0", diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index 3d6cb4768..4d19bf9c6 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -61,7 +61,7 @@ describe("test relayed v1 transaction builder", function () { data: new TransactionPayload("getContractConfig"), }); - await bob.signer.sign(innerTx); + innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); const builder = new RelayedTransactionV1Builder(); const relayedTxV1 = builder @@ -71,7 +71,7 @@ describe("test relayed v1 transaction builder", function () { .setRelayerAddress(alice.address) .build(); - await alice.signer.sign(relayedTxV1); + relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2239682b6e6742584f5536776674315464437368534d4b3454446a5a32794f74686336564c576e3478724d5a706248427738677a6c6659596d362b766b505258303764634a562b4745635462616a7049692b5a5a5942773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a317d"); @@ -97,7 +97,7 @@ describe("test relayed v1 transaction builder", function () { chainID: networkConfig.ChainID }); - await carol.signer.sign(innerTx); + innerTx.applySignature(await carol.signer.sign(innerTx.serializeForSigning())); const builder = new RelayedTransactionV1Builder(); const relayedTxV1 = builder @@ -107,7 +107,7 @@ describe("test relayed v1 transaction builder", function () { .setRelayerAddress(frank.address) .build(); - await frank.signer.sign(relayedTxV1); + relayedTxV1.applySignature(await frank.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 715); assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22744d616d736b6f315a574b526663594e4b5673793463797879643335764b754844576a3548706172344167734c2b4a4e585642545a574c754467384867514254476d724a6b49443133637050614c55322f38626644513d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a312c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d"); @@ -134,7 +134,7 @@ describe("test relayed v1 transaction builder", function () { options: TransactionOptions.withOptions({ guarded: true }) }); - await bob.signer.sign(innerTx); + innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); innerTx.applyGuardianSignature(new Signature("c72e08622c86d9b6889fb9f33eed75c6a04a940daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); const builder = new RelayedTransactionV1Builder(); @@ -145,7 +145,7 @@ describe("test relayed v1 transaction builder", function () { .setRelayerAddress(alice.address) .build(); - await alice.signer.sign(relayedTxV1); + relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a227879344959697947326261496e376e7a507531317871424b6c4132714153676c526b7873797131785a417a3839635454697a6237425855305737374a44613679323370434f2f745355383777336358496652746642413d3d227d"); @@ -172,7 +172,7 @@ describe("test relayed v1 transaction builder", function () { options: TransactionOptions.withOptions({ guarded: true }) }); - await bob.signer.sign(innerTx); + innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); innerTx.applyGuardianSignature(new Signature("b12d08732c86d9b6889fb9f33eed65c6a04a960daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); const builder = new RelayedTransactionV1Builder(); @@ -186,7 +186,7 @@ describe("test relayed v1 transaction builder", function () { .setRelayedTransactionGuardian(frank.address) .build(); - await alice.signer.sign(relayedTxV1); + relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); relayedTxV1.applyGuardianSignature(new Signature("d32c08722c86d9b6889fb9f33eed65c6a04a970daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); diff --git a/src/relayedTransactionV2Builder.spec.ts b/src/relayedTransactionV2Builder.spec.ts index 04e206668..b0aabd51e 100644 --- a/src/relayedTransactionV2Builder.spec.ts +++ b/src/relayedTransactionV2Builder.spec.ts @@ -69,7 +69,7 @@ describe("test relayed v2 transaction builder", function () { data: new TransactionPayload("getContractConfig"), }); - await bob.signer.sign(innerTx); + innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); const builder = new RelayedTransactionV2Builder(); const relayedTxV2 = builder @@ -81,7 +81,7 @@ describe("test relayed v2 transaction builder", function () { .build(); relayedTxV2.setSender(alice.address); - await alice.signer.sign(relayedTxV2); + relayedTxV2.applySignature(await alice.signer.sign(relayedTxV2.serializeForSigning())); assert.equal(relayedTxV2.getNonce().valueOf(), 37); assert.equal( diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 9c43dae9f..d53308653 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -184,7 +184,7 @@ describe("test smart contract interactor", function () { // Execute, do not wait for execution let transaction = interaction.withSender(alice.address).withNonce(0).buildTransaction(); transaction.setSender(alice.address); - await alice.signer.sign(transaction); + transaction.applySignature(await alice.signer.sign(transaction.serializeForSigning())); await provider.sendTransaction(transaction); assert.equal(transaction.getNonce().valueOf(), 0); assert.equal(transaction.getData().toString(), "getUltimateAnswer"); @@ -195,7 +195,7 @@ describe("test smart contract interactor", function () { transaction = interaction.withNonce(1).buildTransaction(); transaction.setSender(alice.address); - await alice.signer.sign(transaction); + transaction.applySignature(await alice.signer.sign(transaction.serializeForSigning())); await provider.sendTransaction(transaction); assert.equal(transaction.getNonce().valueOf(), 1); assert.equal( @@ -206,7 +206,7 @@ describe("test smart contract interactor", function () { // Execute, and wait for execution transaction = interaction.withNonce(2).buildTransaction(); transaction.setSender(alice.address); - await alice.signer.sign(transaction); + transaction.applySignature(await alice.signer.sign(transaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@2bs"); let { bundle } = await controller.execute(interaction, transaction); @@ -238,7 +238,7 @@ describe("test smart contract interactor", function () { assert.deepEqual(counterValue!.valueOf(), new BigNumber(7)); let incrementTransaction = incrementInteraction.withSender(alice.address).withNonce(14).buildTransaction(); - await alice.signer.sign(incrementTransaction); + incrementTransaction.applySignature(await alice.signer.sign(incrementTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@08"); let { bundle: { firstValue: valueAfterIncrement } } = await controller.execute(incrementInteraction, incrementTransaction); assert.deepEqual(valueAfterIncrement!.valueOf(), new BigNumber(8)); @@ -246,16 +246,16 @@ describe("test smart contract interactor", function () { // Decrement three times (simulate three parallel broadcasts). Wait for execution of the latter (third transaction). Return fake "5". // Decrement #1 let decrementTransaction = decrementInteraction.withSender(alice.address).withNonce(15).buildTransaction(); - await alice.signer.sign(decrementTransaction); + decrementTransaction.applySignature(await alice.signer.sign(decrementTransaction.serializeForSigning())); await provider.sendTransaction(decrementTransaction); // Decrement #2 decrementTransaction = decrementInteraction.withNonce(16).buildTransaction(); - await alice.signer.sign(decrementTransaction); + decrementTransaction.applySignature(await alice.signer.sign(decrementTransaction.serializeForSigning())); await provider.sendTransaction(decrementTransaction); // Decrement #3 decrementTransaction = decrementInteraction.withNonce(17).buildTransaction(); - await alice.signer.sign(decrementTransaction); + decrementTransaction.applySignature(await alice.signer.sign(decrementTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@05"); let { bundle: { firstValue: valueAfterDecrement } } = await controller.execute(decrementInteraction, decrementTransaction); assert.deepEqual(valueAfterDecrement!.valueOf(), new BigNumber(5)); @@ -295,7 +295,7 @@ describe("test smart contract interactor", function () { // start() let startTransaction = startInteraction.withSender(alice.address).withNonce(14).buildTransaction(); - await alice.signer.sign(startTransaction); + startTransaction.applySignature(await alice.signer.sign(startTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b"); let { bundle: { returnCode: startReturnCode, values: startReturnValues } } = await controller.execute(startInteraction, startTransaction); @@ -305,7 +305,7 @@ describe("test smart contract interactor", function () { // status() (this is a view function, but for the sake of the test, we'll execute it) let statusTransaction = statusInteraction.withSender(alice.address).withNonce(15).buildTransaction(); - await alice.signer.sign(statusTransaction); + statusTransaction.applySignature(await alice.signer.sign(statusTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@01"); let { bundle: { returnCode: statusReturnCode, values: statusReturnValues, firstValue: statusFirstValue } } = await controller.execute(statusInteraction, statusTransaction); @@ -316,7 +316,7 @@ describe("test smart contract interactor", function () { // lotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) let getLotteryInfoTransaction = getLotteryInfoInteraction.withSender(alice.address).withNonce(15).buildTransaction(); - await alice.signer.sign(getLotteryInfoTransaction); + getLotteryInfoTransaction.applySignature(await alice.signer.sign(getLotteryInfoTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@0000000b6c75636b792d746f6b656e000000010100000000000000005fc2b9dbffffffff00000001640000000a140ec80fa7ee88000000"); let { bundle: { returnCode: infoReturnCode, values: infoReturnValues, firstValue: infoFirstValue } } = await controller.execute(getLotteryInfoInteraction, getLotteryInfoTransaction); diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index 075bc7129..0635c076f 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -54,7 +54,7 @@ describe("test on local testnet", function () { caller: alice.address }); transactionIncrement.setNonce(alice.account.nonce); - await alice.signer.sign(transactionIncrement); + transactionIncrement.applySignature(await alice.signer.sign(transactionIncrement.serializeForSigning())); alice.account.incrementNonce(); @@ -78,8 +78,8 @@ describe("test on local testnet", function () { simulateOne.setNonce(alice.account.nonce); simulateTwo.setNonce(alice.account.nonce); - await alice.signer.sign(simulateOne); - await alice.signer.sign(simulateTwo); + simulateOne.applySignature(await alice.signer.sign(simulateOne.serializeForSigning())); + simulateTwo.applySignature(await alice.signer.sign(simulateTwo.serializeForSigning())); // Broadcast & execute await provider.sendTransaction(transactionDeploy); @@ -129,7 +129,7 @@ describe("test on local testnet", function () { caller: alice.address }); transactionIncrementFirst.setNonce(alice.account.nonce); - await alice.signer.sign(transactionIncrementFirst); + transactionIncrementFirst.applySignature(await alice.signer.sign(transactionIncrementFirst.serializeForSigning())); alice.account.incrementNonce(); @@ -141,7 +141,7 @@ describe("test on local testnet", function () { caller: alice.address }); transactionIncrementSecond.setNonce(alice.account.nonce); - await alice.signer.sign(transactionIncrementSecond); + transactionIncrementSecond.applySignature(await alice.signer.sign(transactionIncrementSecond.serializeForSigning())); alice.account.incrementNonce(); @@ -204,8 +204,8 @@ describe("test on local testnet", function () { transactionMintCarol.setNonce(alice.account.nonce); alice.account.incrementNonce(); - await alice.signer.sign(transactionMintBob); - await alice.signer.sign(transactionMintCarol); + transactionMintBob.applySignature(await alice.signer.sign(transactionMintBob.serializeForSigning())); + transactionMintCarol.applySignature(await alice.signer.sign(transactionMintCarol.serializeForSigning())); // Broadcast & execute await provider.sendTransaction(transactionDeploy); @@ -288,7 +288,7 @@ describe("test on local testnet", function () { // Apply nonces and sign the remaining transactions transactionStart.setNonce(alice.account.nonce); - await alice.signer.sign(transactionStart); + transactionStart.applySignature(await alice.signer.sign(transactionStart.serializeForSigning())); // Broadcast & execute await provider.sendTransaction(transactionDeploy); diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 337f7ac18..0cb481044 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -57,7 +57,7 @@ describe("test contract", () => { assert.equal(contract.getAddress().bech32(), "erd1qqqqqqqqqqqqqpgq3ytm9m8dpeud35v3us20vsafp77smqghd8ss4jtm0q"); // Sign the transaction - alice.signer.sign(deployTransaction); + deployTransaction.applySignature(await alice.signer.sign(deployTransaction.serializeForSigning())); // Now let's broadcast the deploy transaction, and wait for its execution. let hash = await provider.sendTransaction(deployTransaction); @@ -109,8 +109,8 @@ describe("test contract", () => { assert.equal(callTransactionTwo.getGasLimit().valueOf(), 1500000); // Sign transactions, broadcast them - alice.signer.sign(callTransactionOne); - alice.signer.sign(callTransactionTwo); + callTransactionOne.applySignature(await alice.signer.sign(callTransactionOne.serializeForSigning())); + callTransactionTwo.applySignature(await alice.signer.sign(callTransactionTwo.serializeForSigning())); let hashOne = await provider.sendTransaction(callTransactionOne); let hashTwo = await provider.sendTransaction(callTransactionTwo); @@ -152,7 +152,7 @@ describe("test contract", () => { assert.equal(deployTransaction.getNonce().valueOf(), 42); // Sign the transaction - alice.signer.sign(deployTransaction); + deployTransaction.applySignature(await alice.signer.sign(deployTransaction.serializeForSigning())); // Now let's broadcast the deploy transaction, and wait for its execution. let hash = await provider.sendTransaction(deployTransaction); diff --git a/src/smartcontracts/smartContractResults.local.net.spec.ts b/src/smartcontracts/smartContractResults.local.net.spec.ts index eeadf13d4..6f0ef8802 100644 --- a/src/smartcontracts/smartContractResults.local.net.spec.ts +++ b/src/smartcontracts/smartContractResults.local.net.spec.ts @@ -50,7 +50,7 @@ describe("fetch transactions from local testnet", function () { }); transactionIncrement.setNonce(alice.account.nonce); - await alice.signer.sign(transactionIncrement); + transactionIncrement.applySignature(await alice.signer.sign(transactionIncrement.serializeForSigning())); alice.account.incrementNonce(); diff --git a/src/testutils/utils.ts b/src/testutils/utils.ts index 876393148..4c59ad5dc 100644 --- a/src/testutils/utils.ts +++ b/src/testutils/utils.ts @@ -34,7 +34,7 @@ export async function prepareDeployment(obj: { transaction.setNonce(nonce); transaction.setSender(deployer.address) contract.setAddress(contractAddress); - await deployer.signer.sign(transaction); + transaction.applySignature(await deployer.signer.sign(transaction.serializeForSigning())); return transaction; } diff --git a/src/testutils/wallets.ts b/src/testutils/wallets.ts index 4ba8c4a43..9e042b550 100644 --- a/src/testutils/wallets.ts +++ b/src/testutils/wallets.ts @@ -1,5 +1,4 @@ import { UserSecretKey, UserSigner } from "@multiversx/sdk-wallet"; -import { UserSigner as UserSignerNext } from "@multiversx/sdk-wallet-next"; import axios from "axios"; import * as fs from "fs"; import * as path from "path"; @@ -73,7 +72,7 @@ export class TestWallet { readonly secretKeyHex: string; readonly secretKey: Buffer; readonly signer: UserSigner; - readonly signerNext: UserSignerNext; + readonly signerNext: UserSigner; readonly keyFileObject: any; readonly pemFileText: any; readonly account: Account; @@ -83,7 +82,7 @@ export class TestWallet { this.secretKeyHex = secretKeyHex; this.secretKey = Buffer.from(secretKeyHex, "hex"); this.signer = new UserSigner(UserSecretKey.fromString(secretKeyHex)); - this.signerNext = new UserSignerNext(UserSecretKey.fromString(secretKeyHex)); + this.signerNext = new UserSigner(UserSecretKey.fromString(secretKeyHex)); this.keyFileObject = keyFileObject; this.pemFileText = pemFileText; this.account = new Account(this.address); diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts index 54344e4df..3e5823440 100644 --- a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts +++ b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts @@ -674,7 +674,7 @@ describe("test factory on testnet", function () { async function processTransaction(wallet: TestWallet, transaction: Transaction, tag: string): Promise { wallet.account.incrementNonce(); - await wallet.signer.sign(transaction); + transaction.applySignature(await wallet.signer.sign(transaction.serializeForSigning())); await provider.sendTransaction(transaction); console.log(`Sent transaction [${tag}]: ${transaction.getHash().hex()}`); diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index dbb8ac9e5..f4c90c09b 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -51,7 +51,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); }); @@ -68,7 +68,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("e47fd437fc17ac9a69f7bf5f85bafa9e7628d851c4f69bd9fedc7e36029708b2e6d168d5cd652ea78beedd06d4440974ca46c403b14071a1a148d4188f6f2c0d", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "95ed9ac933712d7d77721d75eecfc7896873bb0d746417153812132521636872"); }); @@ -86,7 +86,7 @@ describe("test transaction construction", async () => { options: new TransactionOptions(1) }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("c83e69b853a891bf2130c1839362fe2a7a8db327dcc0c9f130497a4f24b0236140b394801bb2e04ce061a6f873cb432bf1bb1e6072e295610904662ac427a30a", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "32fb1681bd532b226b5bdeed61ae62ce9416bf5e92e48caf96253ff72d1670ac"); }); @@ -103,7 +103,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("9074789e0b4f9b2ac24b1fd351a4dd840afcfeb427b0f93e2a2d429c28c65ee9f4c288ca4dbde79de0e5bcf8c1a5d26e1b1c86203faea923e0edefb0b5099b0c", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "af53e0fc86612d5068862716b5169effdf554951ecc89849b0e836eb0b63fa3e"); }); @@ -120,7 +120,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("39938d15812708475dfc8125b5d41dbcea0b2e3e7aabbbfceb6ce4f070de3033676a218b73facd88b1432d7d4accab89c6130b3abe5cc7bbbb5146e61d355b03", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "e4a6048d92409cfe50f12e81218cb92f39966c618979a693b8d16320a06061c1"); }); @@ -138,7 +138,7 @@ describe("test transaction construction", async () => { version: new TransactionVersion(1) }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "6ffa1a75f98aaf336bfb87ef13b9b5a477a017158285d34ee2a503668767e69e"); }); @@ -154,7 +154,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); @@ -173,7 +173,7 @@ describe("test transaction construction", async () => { chainID: "local-testnet" }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); @@ -193,7 +193,7 @@ describe("test transaction construction", async () => { chainID: "T" }); - await wallets.carol.signer.sign(transaction); + transaction.applySignature(await wallets.carol.signer.sign(transaction.serializeForSigning())); assert.equal(transaction.getSignature().toString("hex"), "5966dd6b98fc5ecbcd203fa38fac7059ba5c17683099071883b0ad6697386769321d851388a99cb8b81aab625aa2d7e13621432dbd8ab334c5891cd7c7755200"); assert.equal(transaction.getHash().toString(), "5728fadbc6c1024c4a0d5552eca44e80c182dc9077e58e31d599cf9496c96d1e"); }); @@ -380,7 +380,7 @@ describe("test transaction construction", async () => { version: new TransactionVersion(2), options: TransactionOptions.withOptions({ guarded: true }) }); - await wallets.alice.signer.sign(transaction); + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); transaction.applyGuardianSignature(transaction.getSignature()); assert.isTrue(transaction.isGuardedTransaction()); }); diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 1afc908aa..c45faa798 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -3,7 +3,7 @@ import { Address } from "../address"; import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { assert } from "chai"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; -import { ValidatorPublicKey } from "@multiversx/sdk-wallet-next"; +import { ValidatorPublicKey } from "@multiversx/sdk-wallet"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { From 75bacd61b8d2f26b86d51b2f74afaff39485358e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 18 Dec 2023 17:37:54 +0200 Subject: [PATCH 056/275] fix after review --- src/testutils/wallets.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/testutils/wallets.ts b/src/testutils/wallets.ts index 9e042b550..a77f15357 100644 --- a/src/testutils/wallets.ts +++ b/src/testutils/wallets.ts @@ -72,7 +72,6 @@ export class TestWallet { readonly secretKeyHex: string; readonly secretKey: Buffer; readonly signer: UserSigner; - readonly signerNext: UserSigner; readonly keyFileObject: any; readonly pemFileText: any; readonly account: Account; @@ -82,7 +81,6 @@ export class TestWallet { this.secretKeyHex = secretKeyHex; this.secretKey = Buffer.from(secretKeyHex, "hex"); this.signer = new UserSigner(UserSecretKey.fromString(secretKeyHex)); - this.signerNext = new UserSigner(UserSecretKey.fromString(secretKeyHex)); this.keyFileObject = keyFileObject; this.pemFileText = pemFileText; this.account = new Account(this.address); From 4b59cef6f08b2eedaf21e39f15b120c3f78554f2 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Dec 2023 12:13:56 +0200 Subject: [PATCH 057/275] set default transaction version=2 and fix failing unit tests --- src/constants.ts | 3 +-- src/networkParams.spec.ts | 4 ++-- src/networkParams.ts | 4 ++-- src/proto/serializer.spec.ts | 25 +++++++++++-------- src/relayedTransactionV1Builder.spec.ts | 10 ++++---- src/relayedTransactionV2Builder.spec.ts | 2 +- src/smartcontracts/interaction.spec.ts | 4 ++-- src/testutils/wallets.ts | 2 +- src/transaction.spec.ts | 32 ++++++++++++------------- 9 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index f9350f039..c00f61a35 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,8 +2,7 @@ export const TRANSACTION_MIN_GAS_PRICE = 1000000000; export const TRANSACTION_OPTIONS_DEFAULT = 0; export const TRANSACTION_OPTIONS_TX_HASH_SIGN = 0b0001; export const TRANSACTION_OPTIONS_TX_GUARDED = 0b0010; -export const TRANSACTION_VERSION_DEFAULT = 1; -export const TRANSACTION_VERSION_WITH_OPTIONS = 2; +export const TRANSACTION_VERSION_DEFAULT = 2; export const ESDT_TRANSFER_GAS_LIMIT = 500000; export const ESDT_TRANSFER_FUNCTION_NAME = "ESDTTransfer"; export const ESDTNFT_TRANSFER_FUNCTION_NAME = "ESDTNFTTransfer"; diff --git a/src/networkParams.spec.ts b/src/networkParams.spec.ts index 2932b8167..c217414e3 100644 --- a/src/networkParams.spec.ts +++ b/src/networkParams.spec.ts @@ -1,6 +1,6 @@ import { assert } from "chai"; import { - TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT, TRANSACTION_VERSION_WITH_OPTIONS + TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT } from "./constants"; import { TransactionOptions, TransactionVersion } from "./networkParams"; @@ -17,7 +17,7 @@ describe("test transaction version", () => { const versionWithOptions = TransactionVersion.withTxOptions(); assert.equal(TRANSACTION_VERSION_DEFAULT, versionDefault.valueOf()); - assert.equal(TRANSACTION_VERSION_WITH_OPTIONS, versionWithOptions.valueOf()); + assert.equal(TRANSACTION_VERSION_DEFAULT, versionWithOptions.valueOf()); }); }); diff --git a/src/networkParams.ts b/src/networkParams.ts index 5a26bf08c..24b8b7017 100644 --- a/src/networkParams.ts +++ b/src/networkParams.ts @@ -1,4 +1,4 @@ -import { TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT, TRANSACTION_VERSION_WITH_OPTIONS } from "./constants"; +import { TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT } from "./constants"; import * as errors from "./errors"; export class TransactionVersion { @@ -31,7 +31,7 @@ export class TransactionVersion { * Creates a TransactionVersion object with the VERSION setting for enabling options */ static withTxOptions(): TransactionVersion { - return new TransactionVersion(TRANSACTION_VERSION_WITH_OPTIONS); + return new TransactionVersion(TRANSACTION_VERSION_DEFAULT); } valueOf(): number { diff --git a/src/proto/serializer.spec.ts b/src/proto/serializer.spec.ts index f6da42c58..174f8af2b 100644 --- a/src/proto/serializer.spec.ts +++ b/src/proto/serializer.spec.ts @@ -26,10 +26,11 @@ describe("serialize transactions", () => { chainID: "local-testnet" }); - transaction.applySignature(new Signature("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109")); + const signer = wallets.alice.signer; + transaction.applySignature(await signer.sign(transaction.serializeForSigning())); let buffer = serializer.serializeTransaction(transaction); - assert.equal(buffer.toString("hex"), "0859120200001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340d08603520d6c6f63616c2d746573746e657458016240b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109"); + assert.equal(buffer.toString("hex"), "0859120200001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340d08603520d6c6f63616c2d746573746e6574580262403f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); }); it("with data, no value", async () => { @@ -43,10 +44,11 @@ describe("serialize transactions", () => { chainID: "local-testnet" }); - transaction.applySignature(new Signature("e47fd437fc17ac9a69f7bf5f85bafa9e7628d851c4f69bd9fedc7e36029708b2e6d168d5cd652ea78beedd06d4440974ca46c403b14071a1a148d4188f6f2c0d")); + const signer = wallets.alice.signer; + transaction.applySignature(await signer.sign(transaction.serializeForSigning())); let buffer = serializer.serializeTransaction(transaction); - assert.equal(buffer.toString("hex"), "085a120200001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc034080f1044a0568656c6c6f520d6c6f63616c2d746573746e657458016240e47fd437fc17ac9a69f7bf5f85bafa9e7628d851c4f69bd9fedc7e36029708b2e6d168d5cd652ea78beedd06d4440974ca46c403b14071a1a148d4188f6f2c0d"); + assert.equal(buffer.toString("hex"), "085a120200001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc034080f1044a0568656c6c6f520d6c6f63616c2d746573746e657458026240f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e"); }); it("with data, with value", async () => { @@ -60,10 +62,11 @@ describe("serialize transactions", () => { chainID: "local-testnet" }); - transaction.applySignature(new Signature("9074789e0b4f9b2ac24b1fd351a4dd840afcfeb427b0f93e2a2d429c28c65ee9f4c288ca4dbde79de0e5bcf8c1a5d26e1b1c86203faea923e0edefb0b5099b0c")); + const signer = wallets.alice.signer; + transaction.applySignature(await signer.sign(transaction.serializeForSigning())); let buffer = serializer.serializeTransaction(transaction); - assert.equal(buffer.toString("hex"), "085b1209008ac7230489e800001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340a08d064a0c666f722074686520626f6f6b520d6c6f63616c2d746573746e6574580162409074789e0b4f9b2ac24b1fd351a4dd840afcfeb427b0f93e2a2d429c28c65ee9f4c288ca4dbde79de0e5bcf8c1a5d26e1b1c86203faea923e0edefb0b5099b0c"); + assert.equal(buffer.toString("hex"), "085b1209008ac7230489e800001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340a08d064a0c666f722074686520626f6f6b520d6c6f63616c2d746573746e657458026240b45f22e9f57a6df22670fcc3566723a0711a05ac2547456de59fd222a54940e4a1d99bd414897ccbf5c02a842ad86e638989b7f4d30edd26c99a8cd1eb092304"); }); it("with data, with large value", async () => { @@ -77,10 +80,11 @@ describe("serialize transactions", () => { chainID: "local-testnet" }); - transaction.applySignature(new Signature("39938d15812708475dfc8125b5d41dbcea0b2e3e7aabbbfceb6ce4f070de3033676a218b73facd88b1432d7d4accab89c6130b3abe5cc7bbbb5146e61d355b03")); + const signer = wallets.alice.signer; + transaction.applySignature(await signer.sign(transaction.serializeForSigning())); let buffer = serializer.serializeTransaction(transaction); - assert.equal(buffer.toString("hex"), "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340a08d064a11666f722074686520737061636573686970520d6c6f63616c2d746573746e65745801624039938d15812708475dfc8125b5d41dbcea0b2e3e7aabbbfceb6ce4f070de3033676a218b73facd88b1432d7d4accab89c6130b3abe5cc7bbbb5146e61d355b03"); + assert.equal(buffer.toString("hex"), "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340a08d064a11666f722074686520737061636573686970520d6c6f63616c2d746573746e65745802624001f05aa8cb0614e12a94ab9dcbde5e78370a4e05d23ef25a1fb9d5fcf1cb3b1f33b919cd8dafb1704efb18fa233a8aa0d3344fb6ee9b613a7d7a403786ffbd0a"); }); it("with nonce = 0", async () => { @@ -113,9 +117,10 @@ describe("serialize transactions", () => { chainID: "T" }); - transaction.applySignature(new Signature("5966dd6b98fc5ecbcd203fa38fac7059ba5c17683099071883b0ad6697386769321d851388a99cb8b81aab625aa2d7e13621432dbd8ab334c5891cd7c7755200")) + const signer = wallets.carol.signer; + transaction.applySignature(await signer.sign(transaction.serializeForSigning())); const buffer = serializer.serializeTransaction(transaction); - assert.equal(buffer.toString("hex"), "08cc011209000de0b6b3a76400001a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e12205616c6963652a20b2a11555ce521e4944e09ab17549d85b487dcd26c84b5017a39e31a3670889ba32056361726f6c388094ebdc0340d08603520154580162405966dd6b98fc5ecbcd203fa38fac7059ba5c17683099071883b0ad6697386769321d851388a99cb8b81aab625aa2d7e13621432dbd8ab334c5891cd7c7755200"); + assert.equal(buffer.toString("hex"), "08cc011209000de0b6b3a76400001a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e12205616c6963652a20b2a11555ce521e4944e09ab17549d85b487dcd26c84b5017a39e31a3670889ba32056361726f6c388094ebdc0340d086035201545802624051e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06"); }); }); diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index 4d19bf9c6..265345309 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -74,8 +74,8 @@ describe("test relayed v1 transaction builder", function () { relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); - assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2239682b6e6742584f5536776674315464437368534d4b3454446a5a32794f74686336564c576e3478724d5a706248427738677a6c6659596d362b766b505258303764634a562b4745635462616a7049692b5a5a5942773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a317d"); - assert.equal(relayedTxV1.getSignature().toString("hex"), "c7d2c3b971f44eca676c10624d3c4319f8898af159f003e1e59f446cb75e5a294c9f0758d800e04d3daff11e67d20c4c1f85fd54aad6deb947ef391e6dd09d07"); + assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2272525455544858677a4273496e4f6e454b6b7869642b354e66524d486e33534948314673746f577352434c434b3258514c41614f4e704449346531476173624c5150616130566f364144516d4f2b52446b6f364a43413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a327d"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "128e7cdc14c2b9beee2f3ff7a7fa5d1f5ef31a654a0c92e223c90ab28265fa277d306f23a06536248cf9573e828017004fb639617fade4d68a37524aafca710d"); }); it("should compute relayed v1 transaction (with usernames)", async function () { @@ -110,8 +110,8 @@ describe("test relayed v1 transaction builder", function () { relayedTxV1.applySignature(await frank.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 715); - assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22744d616d736b6f315a574b526663594e4b5673793463797879643335764b754844576a3548706172344167734c2b4a4e585642545a574c754467384867514254476d724a6b49443133637050614c55322f38626644513d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a312c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d"); - assert.equal(relayedTxV1.getSignature().toString("hex"), "0fbab023085551b7c497e5c52f64df802cb518ebaac93f8897e5cca25a8aff447565fa96570f7b547f7c0d0fceb2c7d12bcb5f37fa92c79725d9b2c69039f00d"); + assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a226a33427a6469554144325963517473576c65707663664a6f75657a48573063316b735a424a4d6339573167435450512b6870636759457858326f6f367a4b5654347464314b4b6f79783841526a346e336474576c44413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "3787d640e5a579e7977a4a1bcdd435ad11855632fa4a414a06fbf8355692d1a58d76ef0adbdd6ccd6bd3c329f36bd53c180d4873ec1a6c558e659aeb9ab92d00"); }); it("should compute guarded inner Tx - relayed v1 transaction", async function () { @@ -149,7 +149,7 @@ describe("test relayed v1 transaction builder", function () { assert.equal(relayedTxV1.getNonce().valueOf(), 2627); assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a227879344959697947326261496e376e7a507531317871424b6c4132714153676c526b7873797131785a417a3839635454697a6237425855305737374a44613679323370434f2f745355383777336358496652746642413d3d227d"); - assert.equal(relayedTxV1.getSignature().toString("hex"), "f3db6318406f01ef807f04039e33563f97c2eabc1c8a59b6e412429725f03242cba679c717b734cb06859ef8e14349edf1db5eb1a9b3d36697b922475ae7ea07"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "54a7a3a45c43d3d5e94076160c189ed03740db770a2ca31e54687cdda972c01949fa2ba3b21782c130d4e0c05792a223f976329935063fb852692326bfc0fa0e"); }); it("should compute guarded inner tx and guarded relayed v1 transaction", async function () { diff --git a/src/relayedTransactionV2Builder.spec.ts b/src/relayedTransactionV2Builder.spec.ts index b0aabd51e..62542ebd2 100644 --- a/src/relayedTransactionV2Builder.spec.ts +++ b/src/relayedTransactionV2Builder.spec.ts @@ -86,7 +86,7 @@ describe("test relayed v2 transaction builder", function () { assert.equal(relayedTxV2.getNonce().valueOf(), 37); assert.equal( relayedTxV2.getData().toString(), - "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@b6c5262d9837853e2201de357c1cc4c9803988a42d7049d26b7785dd0ac2bd4c6a8804b6fd9cf845fe2c2a622774b1a2dbd0a417c9a0bc3f0563a85bd15e710a"); + "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c"); }); }); diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index d53308653..8cc6157c2 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -190,7 +190,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getData().toString(), "getUltimateAnswer"); assert.equal( transaction.getHash().toString(), - "60d0956a8902c1179dce92d91bd9670e31b9a9cd07c1d620edb7754a315b4818" + "3579ad09099feb9755c860ddd225251170806d833342e912fccdfe2ed5c3a364" ); transaction = interaction.withNonce(1).buildTransaction(); @@ -200,7 +200,7 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getNonce().valueOf(), 1); assert.equal( transaction.getHash().toString(), - "acd207c38f6c3341b18d8ef331fa07ba49615fa12d7610aad5d8495293049f24" + "ad513ce7c5d371d30e48f073326899766736eac1ac231d847d45bc3facbcb496" ); // Execute, and wait for execution diff --git a/src/testutils/wallets.ts b/src/testutils/wallets.ts index a77f15357..fefefb059 100644 --- a/src/testutils/wallets.ts +++ b/src/testutils/wallets.ts @@ -92,7 +92,7 @@ export class TestWallet { async sync(provider: IAccountFetcher) { let accountOnNetwork = await provider.getAccount(this.address); - await this.account.update(accountOnNetwork); + this.account.update(accountOnNetwork); return this; } } diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index f4c90c09b..5062563e2 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -52,8 +52,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); + assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); + assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); }); it("with data, no value", async () => { @@ -69,8 +69,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("e47fd437fc17ac9a69f7bf5f85bafa9e7628d851c4f69bd9fedc7e36029708b2e6d168d5cd652ea78beedd06d4440974ca46c403b14071a1a148d4188f6f2c0d", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "95ed9ac933712d7d77721d75eecfc7896873bb0d746417153812132521636872"); + assert.equal(transaction.getSignature().toString("hex"), "f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e"); + assert.equal(transaction.getHash().toString(), "10a2bd6f9c358d2c9645368081999efd2a4cc7f24bdfdd75e8f57485fd702001"); }); it("with data, with opaque, unused options (the protocol ignores the options when version == 1)", async () => { @@ -104,8 +104,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("9074789e0b4f9b2ac24b1fd351a4dd840afcfeb427b0f93e2a2d429c28c65ee9f4c288ca4dbde79de0e5bcf8c1a5d26e1b1c86203faea923e0edefb0b5099b0c", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "af53e0fc86612d5068862716b5169effdf554951ecc89849b0e836eb0b63fa3e"); + assert.equal(transaction.getSignature().toString("hex"), "b45f22e9f57a6df22670fcc3566723a0711a05ac2547456de59fd222a54940e4a1d99bd414897ccbf5c02a842ad86e638989b7f4d30edd26c99a8cd1eb092304"); + assert.equal(transaction.getHash().toString(), "84125d7154d81a723642100bdf74e6df99f7c069c016d1e6bbeb408fd4e961bf"); }); it("with data, with large value", async () => { @@ -121,8 +121,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("39938d15812708475dfc8125b5d41dbcea0b2e3e7aabbbfceb6ce4f070de3033676a218b73facd88b1432d7d4accab89c6130b3abe5cc7bbbb5146e61d355b03", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "e4a6048d92409cfe50f12e81218cb92f39966c618979a693b8d16320a06061c1"); + assert.equal(transaction.getSignature().toString("hex"), "01f05aa8cb0614e12a94ab9dcbde5e78370a4e05d23ef25a1fb9d5fcf1cb3b1f33b919cd8dafb1704efb18fa233a8aa0d3344fb6ee9b613a7d7a403786ffbd0a"); + assert.equal(transaction.getHash().toString(), "321e1f1a0e3d06edade34fd0fdf3b4859e4328a73706a442c2439968a074113c"); }); it("with nonce = 0", async () => { @@ -139,7 +139,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04", transaction.getSignature().toString("hex")); + assert.equal(transaction.getSignature().toString("hex"), "dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04"); assert.equal(transaction.getHash().toString(), "6ffa1a75f98aaf336bfb87ef13b9b5a477a017158285d34ee2a503668767e69e"); }); @@ -155,8 +155,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); + assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); + assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); let result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); @@ -174,8 +174,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("b56769014f2bdc5cf9fc4a05356807d71fcf8775c819b0f1b0964625b679c918ffa64862313bfef86f99b38cb84fcdb16fa33ad6eb565276616723405cd8f109", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "eb30c50c8831885ebcfac986d27e949ec02cf25676e22a009b7a486e5431ec2e"); + assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); + assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); let result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); @@ -194,8 +194,8 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.carol.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "5966dd6b98fc5ecbcd203fa38fac7059ba5c17683099071883b0ad6697386769321d851388a99cb8b81aab625aa2d7e13621432dbd8ab334c5891cd7c7755200"); - assert.equal(transaction.getHash().toString(), "5728fadbc6c1024c4a0d5552eca44e80c182dc9077e58e31d599cf9496c96d1e"); + assert.equal(transaction.getSignature().toString("hex"), "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06"); + assert.equal(transaction.getHash().toString(), "edc84d776bfd655ddbd6fce24a83e379496ac47890d00be9c8bb2c6666fa3fd8"); }); it("computes correct fee", () => { @@ -213,7 +213,7 @@ describe("test transaction construction", async () => { MinGasLimit: 10, GasPerDataByte: 1500, GasPriceModifier: 0.01, - ChainID: "T" + ChainID: "local-testnet" }; let fee = transaction.computeFee(networkConfig); From 0a3e425799e5a3c09248e6de6b54fa8c86ea5de0 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Dec 2023 19:31:36 +0200 Subject: [PATCH 058/275] sign transactions instead of hardcoding signatures --- src/relayedTransactionV1Builder.spec.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index 265345309..68248b8db 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -135,7 +135,7 @@ describe("test relayed v1 transaction builder", function () { }); innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); - innerTx.applyGuardianSignature(new Signature("c72e08622c86d9b6889fb9f33eed75c6a04a940daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); + innerTx.applyGuardianSignature(await grace.signer.sign(innerTx.serializeForSigning())); const builder = new RelayedTransactionV1Builder(); const relayedTxV1 = builder @@ -148,8 +148,8 @@ describe("test relayed v1 transaction builder", function () { relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); - assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a227879344959697947326261496e376e7a507531317871424b6c4132714153676c526b7873797131785a417a3839635454697a6237425855305737374a44613679323370434f2f745355383777336358496652746642413d3d227d"); - assert.equal(relayedTxV1.getSignature().toString("hex"), "54a7a3a45c43d3d5e94076160c189ed03740db770a2ca31e54687cdda972c01949fa2ba3b21782c130d4e0c05792a223f976329935063fb852692326bfc0fa0e"); + assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a222b5431526f4833625a792f54423177342b6a365155477258645637457577553073753948646551626453515269463953757a686d634b705463526d58595252366c534c6652394931624d7134674730436538363741513d3d227d"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "39cff9d5100e290fbc7361cb6e2402261caf864257b4116f150e0c61e7869155dff8361fa5449431eb7a8ed847c01ba9b3b5ebafe5fac1a3d40c64829d827e00"); }); it("should compute guarded inner tx and guarded relayed v1 transaction", async function () { @@ -173,8 +173,7 @@ describe("test relayed v1 transaction builder", function () { }); innerTx.applySignature(await bob.signer.sign(innerTx.serializeForSigning())); - innerTx.applyGuardianSignature(new Signature("b12d08732c86d9b6889fb9f33eed65c6a04a960daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); - + innerTx.applyGuardianSignature(await grace.signer.sign(innerTx.serializeForSigning())); const builder = new RelayedTransactionV1Builder(); const relayedTxV1 = builder .setInnerTransaction(innerTx) @@ -187,10 +186,10 @@ describe("test relayed v1 transaction builder", function () { .build(); relayedTxV1.applySignature(await alice.signer.sign(relayedTxV1.serializeForSigning())); - relayedTxV1.applyGuardianSignature(new Signature("d32c08722c86d9b6889fb9f33eed65c6a04a970daa012825464c6ccaad71640cfcf5c4d38b36fb0575345bbec90daeb2db7a423bfb5253cef0ddc5c87d1b5f04")); + relayedTxV1.applyGuardianSignature(await frank.signer.sign(relayedTxV1.serializeForSigning())); assert.equal(relayedTxV1.getNonce().valueOf(), 2627); - assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b546e5674596d5679222c227369676e6174757265223a223469724d4b4a656d724d375174344e7635487633544c44683775654779487045564c4371674a3677652f7a662b746a4933354975573452633458543451533433475333356158386c6a533834324a38426854645043673d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a227353304963797947326261496e376e7a5075316c7871424b6c6732714153676c526b7873797131785a417a3839635454697a6237425855305737374a44613679323370434f2f745355383777336358496652746642413d3d227d"); - assert.equal(relayedTxV1.getSignature().toString("hex"), "15fe39045685625d0f1742e34ba7679d225d49fc1f1f2ab363b7e78beddb8d278d11f5658a0d0e996d28ba77c49bc6d614b62a4eb7e74f363546ecaa2a84d905"); + assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b546e5674596d5679222c227369676e6174757265223a223469724d4b4a656d724d375174344e7635487633544c44683775654779487045564c4371674a3677652f7a662b746a4933354975573452633458543451533433475333356158386c6a533834324a38426854645043673d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a2270424754394e674a78307539624c56796b654d78786a454865374269696c37764932324a46676f32787a6e2f496e3032463769546563356b44395045324f747065386c475335412b532f4a36417762576834446744673d3d227d"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "8ede1bbeed96b102344dffeac12c2592c62b7313cdeb132e8c8bf11d2b1d3bb8189d257a6dbcc99e222393d9b9ec77656c349dae97a32e68bdebd636066bf706"); }); }); From 07d93c98d0291bc110f1c534ea51024a158a88ce Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Dec 2023 14:08:11 +0200 Subject: [PATCH 059/275] deprecate old relayed transactions builders --- src/errors.ts | 9 +++++++ src/relayedTransactionV1Builder.ts | 3 +++ src/relayedTransactionV2Builder.ts | 3 +++ .../transactionPayloadBuilders.ts | 3 +++ .../relayedTransactionsFactory.ts | 24 +++++++++++++++++++ 5 files changed, 42 insertions(+) create mode 100644 src/transactionsFactories/relayedTransactionsFactory.ts diff --git a/src/errors.ts b/src/errors.ts index 53d83bc6e..caa1308a0 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -352,3 +352,12 @@ export class ErrBadUsage extends Err { super(message); } } + +/** + * Signals an invalid inner transaction for relayed transactions + */ +export class ErrInvalidInnerTransaction extends Err{ + public constructor(message: string){ + super(message); + } +} \ No newline at end of file diff --git a/src/relayedTransactionV1Builder.ts b/src/relayedTransactionV1Builder.ts index 2e690e225..d87d84e53 100644 --- a/src/relayedTransactionV1Builder.ts +++ b/src/relayedTransactionV1Builder.ts @@ -7,6 +7,9 @@ import { TransactionOptions, TransactionVersion } from "./networkParams"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +/** + * @deprecated Use {@link RelayedTransactionsFactory} instead. + */ export class RelayedTransactionV1Builder { innerTransaction: Transaction | undefined; relayerAddress: IAddress | undefined; diff --git a/src/relayedTransactionV2Builder.ts b/src/relayedTransactionV2Builder.ts index 2717e7757..6cb1ce126 100644 --- a/src/relayedTransactionV2Builder.ts +++ b/src/relayedTransactionV2Builder.ts @@ -5,6 +5,9 @@ import { AddressValue, ArgSerializer, BytesValue, U64Value } from "./smartcontra import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +/** + * @deprecated Use {@link RelayedTransactionsFactory} instead. + */ export class RelayedTransactionV2Builder { innerTransaction: Transaction | undefined; innerTransactionGasLimit: IGasLimit | undefined; diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index 07e65276a..c70fbdccb 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -9,6 +9,9 @@ export const WasmVirtualMachine = "0500"; /** * A builder for {@link TransactionPayload} objects, to be used for Smart Contract deployment transactions. */ +/** + * @deprecated Use {@link SmartContractTransactionsFactory} instead. + */ export class ContractDeployPayloadBuilder { private code: ICode | null = null; private codeMetadata: ICodeMetadata = ""; diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts new file mode 100644 index 000000000..61c37bc45 --- /dev/null +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -0,0 +1,24 @@ +import BigNumber from "bignumber.js"; +import { Transaction } from "../transaction"; +import { IAddress } from "../interface"; +import { ErrInvalidInnerTransaction } from "../errors"; + +interface IConfig { + chainID: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; +} + +export class RelayedTransactionsFactory { + private readonly config: IConfig; + + constructor(config: IConfig) { + this.config = config; + } + + createRelayedV1Transaction(options: { innerTransaction: Transaction; relayerAddress: IAddress }) { + if (!options.innerTransaction.getGasLimit()) { + throw new ErrInvalidInnerTransaction("The gas limit is not set for the inner transaction"); + } + } +} From c54501cc842e05fe956705ed7fc2bff435e90a9d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Dec 2023 17:07:26 +0200 Subject: [PATCH 060/275] implement new transaction class and transaction computer --- src/interface.ts | 18 ++++ src/transaction.ts | 256 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 257 insertions(+), 17 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index 4a0c10369..0fe960767 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -55,3 +55,21 @@ export interface ITokenTransfer { * @deprecated Use {@link ITokenTransfer} instead. */ export type ITokenPayment = ITokenTransfer; + +export interface ITransactionNext { + sender: string; + receiver: string; + gasLimit: BigNumber.Value; + chainID: string; + nonce: BigNumber.Value; + value: BigNumber.Value; + senderUsername: string; + receiverUsername: string; + gasPrice: BigNumber.Value; + data: Uint8Array; + version: number; + options: number; + guardian: string; + signature: Uint8Array; + guardianSignature: Uint8Array; + } diff --git a/src/transaction.ts b/src/transaction.ts index 691411337..9d33c149a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,17 +1,16 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { Compatibility } from "./compatibility"; -import { TRANSACTION_MIN_GAS_PRICE } from "./constants"; +import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT } from "./constants"; import * as errors from "./errors"; import { Hash } from "./hash"; -import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; +import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; import { INetworkConfig } from "./interfaceOfNetwork"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; import { Signature, interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; import { guardNotEmpty } from "./utils"; -import { DraftTransaction } from "./draftTransaction"; const createTransactionHasher = require("blake2b"); const TRANSACTION_HASH_LENGTH = 32; @@ -153,20 +152,6 @@ export class Transaction { this.hash = TransactionHash.empty(); } - /** - * Creates a new Transaction object from a DraftTransaction. - */ - static fromDraft(draft: DraftTransaction): Transaction { - return new Transaction({ - sender: Address.fromBech32(draft.sender), - receiver: Address.fromBech32(draft.receiver), - gasLimit: new BigNumber(draft.gasLimit).toNumber(), - chainID: "", - value: draft.value, - data: new TransactionPayload(Buffer.from(draft.data)) - }) - } - getNonce(): INonce { return this.nonce; } @@ -435,6 +420,31 @@ export class Transaction { return feeForMove.plus(processingFee); } + + /** + * Creates a new Transaction object from a TransactionNext object. + */ + static fromTransactionNext(transaction: ITransactionNext): Transaction { + const tx = new Transaction({ + sender: Address.fromBech32(transaction.sender), + receiver: Address.fromBech32(transaction.receiver), + gasLimit: new BigNumber(transaction.gasLimit).toNumber(), + chainID: transaction.chainID, + value: transaction.value, + data: new TransactionPayload(Buffer.from(transaction.data)), + nonce: Number(transaction.nonce), + gasPrice: Number(transaction.gasPrice), + receiverUsername: transaction.receiverUsername, + senderUsername: transaction.senderUsername, + options: transaction.options, + version: transaction.version, + guardian: Address.fromBech32(transaction.guardian) + }); + tx.applySignature(transaction.signature); + tx.applyGuardianSignature(transaction.guardianSignature); + + return tx; + } } /** @@ -458,3 +468,215 @@ export class TransactionHash extends Hash { } } +/** + * An abstraction for creating, signing and broadcasting transactions. + * Will replace the {@link Transaction} class in the future. + */ +export class TransactionNext{ + /** + * The nonce of the transaction (the account sequence number of the sender). + */ + public nonce: BigNumber.Value; + + /** + * The value to transfer. + */ + public value: BigNumber.Value; + + /** + * The address of the sender. + */ + public sender: string; + + /** + * The address of the receiver. + */ + public receiver: string; + + /** + * The username of the sender. + */ + public senderUsername: string; + + /** + * The username of the receiver. + */ + public receiverUsername: string; + + /** + * The gas price to be used. + */ + public gasPrice: BigNumber.Value; + + /** + * The maximum amount of gas to be consumed when processing the transaction. + */ + public gasLimit: BigNumber.Value; + + /** + * The payload of the transaction. + */ + public data: Uint8Array; + + /** + * The chain ID of the Network (e.g. "1" for Mainnet). + */ + public chainID: string; + + /** + * The version, required by the Network in order to correctly interpret the contents of the transaction. + */ + public version: number; + + /** + * The options field of the transactions. + */ + public options: number; + + /** + * The address of the guardian. + */ + public guardian: string; + + /** + * The signature. + */ + public signature: Uint8Array; + + /** + * The signature of the guardian. + */ + public guardianSignature: Uint8Array; + + /** + * Creates a new Transaction object. + */ + public constructor({ + sender, + receiver, + gasLimit, + chainID, + nonce, + value, + senderUsername, + receiverUsername, + gasPrice, + data, + version, + options, + guardian, + }: { + nonce?: BigNumber.Value; + value?: BigNumber.Value; + sender: string; + receiver: string; + senderUsername?: string; + receiverUsername?: string; + gasPrice?: BigNumber.Value; + gasLimit: BigNumber.Value; + data?: Uint8Array; + chainID: string; + version?: number; + options?: number; + guardian?: string; + }) { + this.nonce = nonce || 0; + this.value = value || new BigNumber(0); + this.sender = sender; + this.receiver = receiver; + this.senderUsername = senderUsername || ""; + this.receiverUsername = receiverUsername || ""; + this.gasPrice = gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE); + this.gasLimit = gasLimit; + this.data = data || new Uint8Array(); + this.chainID = chainID; + this.version = version || TRANSACTION_OPTIONS_DEFAULT; + this.options = options || TRANSACTION_OPTIONS_DEFAULT; + this.guardian = guardian || ""; + + this.signature = new Uint8Array(); + this.guardianSignature = new Uint8Array(); + } +} + +/** + * An utilitary class meant to work together with the {@link TransactionNext} class. + */ +export class TransactionComputer { + constructor() {} + + computeTrnsactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber{ + let moveBalanceGas = + networkConfig.MinGasLimit.valueOf() + + transaction.data.length * networkConfig.GasPerDataByte.valueOf(); + if (new BigNumber(moveBalanceGas) > transaction.gasLimit) { + throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); + } + + let gasPrice = new BigNumber(transaction.gasPrice); + let feeForMove = new BigNumber(moveBalanceGas).multipliedBy(gasPrice); + if (moveBalanceGas === transaction.gasLimit.valueOf()) { + return feeForMove; + } + + let diff = new BigNumber(transaction.gasLimit).minus(new BigNumber(moveBalanceGas)); + let modifiedGasPrice = gasPrice.multipliedBy( + new BigNumber(networkConfig.GasPriceModifier.valueOf()) + ); + let processingFee = diff.multipliedBy(modifiedGasPrice); + + return feeForMove.plus(processingFee); + } + + computeBytesForSigning(transaction: ITransactionNext): Uint8Array{ + let plainTransaction = this.toPlainObject(transaction); + + if (plainTransaction.signature) { + delete plainTransaction.signature; + } + + if (plainTransaction.guardianSignature) { + delete plainTransaction.guardianSignature; + } + + if (!plainTransaction.guardian) { + delete plainTransaction.guardian + } + + let serialized = JSON.stringify(plainTransaction); + + return new Uint8Array(Buffer.from(serialized).buffer); + } + + computeTransactionHash(transaction: ITransactionNext): Uint8Array{ + let serializer = new ProtoSerializer(); + + const tx = Transaction.fromTransactionNext(transaction); + let buffer = serializer.serializeTransaction(tx); + let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) + .update(buffer); + + return hash; + } + + private toPlainObject(transaction: ITransactionNext) { + return { + nonce: Number(transaction.nonce), + value: transaction.value.toString(), + receiver: transaction.receiver, + sender: transaction.sender, + senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, + receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), + data: transaction.data.length == 0 ? undefined : Buffer.from(transaction.data).toString("base64"), + chainID: transaction.chainID, + version: transaction.version, + options: transaction.options == 0 ? undefined : transaction.options, + guardian: transaction.guardian == "" ? undefined : transaction.guardian, + signature: transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), + guardianSignature: transaction.guardianSignature.length == 0 ? undefined : Buffer.from(transaction.guardianSignature).toString("hex") + } + } + +} From 2af440b8d300e624b50a631a5713de508a02b7cb Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 21 Dec 2023 18:05:08 +0200 Subject: [PATCH 061/275] unit tests for TransctionNext --- .../interaction.local.net.spec.ts | 2 +- src/transaction.local.net.spec.ts | 2 +- src/transaction.spec.ts | 24 +- src/transaction.ts | 53 +++-- src/transactionNext.spec.ts | 217 ++++++++++++++++++ 5 files changed, 280 insertions(+), 18 deletions(-) create mode 100644 src/transactionNext.spec.ts diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 802724e35..57db4e3c5 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -228,7 +228,7 @@ describe("test smart contract interactor", function () { const wallet = options.wallet; const serialized = transaction.serializeForSigning(); - const signature = await wallet.signerNext.sign(serialized); + const signature = await wallet.signer.sign(serialized); transaction.applySignature(signature); } }); diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 30f674ec3..56fa581ec 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -137,7 +137,7 @@ describe("test transaction", function () { const wallet = options.wallet; const serialized = transaction.serializeForSigning(); - const signature = await wallet.signerNext.sign(serialized); + const signature = await wallet.signer.sign(serialized); transaction.applySignature(signature); } }); diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index f4c90c09b..748bcf9c5 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -4,7 +4,7 @@ import { Address } from "./address"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction } from "./transaction"; +import { Transaction, TransactionNext } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { DraftTransaction } from "./draftTransaction"; import { TRANSACTION_MIN_GAS_PRICE } from "./constants"; @@ -40,6 +40,28 @@ describe("test transaction construction", async () => { assert.deepEqual(transaction.getSignature(), Buffer.from([])); }); + it("create transaction from transaction next", async () => { + const nextTransaction = new TransactionNext({ + sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + gasLimit: 56000, + value: "1000000000000000000", + data: Buffer.from("test"), + chainID: "T" + }); + + const transaction = Transaction.fromTransactionNext(nextTransaction); + assert.deepEqual(transaction.getSender(), Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")); + assert.deepEqual(transaction.getReceiver(), Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx")); + assert.equal(transaction.getGasLimit().valueOf(), 56000); + assert.equal(transaction.getValue().toString(), "1000000000000000000"); + assert.equal(transaction.getData().toString(), "test"); + assert.equal(transaction.getChainID().valueOf(), "T"); + assert.equal(transaction.getNonce().valueOf(), 0); + assert.equal(transaction.getGasPrice().valueOf(), TRANSACTION_MIN_GAS_PRICE); + assert.deepEqual(transaction.getSignature(), Buffer.from([])); + }); + it("with no data, no value", async () => { let transaction = new Transaction({ nonce: 89, diff --git a/src/transaction.ts b/src/transaction.ts index 9d33c149a..5a4ad8ec7 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -11,6 +11,7 @@ import { ProtoSerializer } from "./proto"; import { Signature, interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; import { guardNotEmpty } from "./utils"; +import { DraftTransaction } from "./draftTransaction"; const createTransactionHasher = require("blake2b"); const TRANSACTION_HASH_LENGTH = 32; @@ -421,6 +422,20 @@ export class Transaction { return feeForMove.plus(processingFee); } + /** + * Creates a new Transaction object from a DraftTransaction. + */ + static fromDraft(draft: DraftTransaction): Transaction { + return new Transaction({ + sender: Address.fromBech32(draft.sender), + receiver: Address.fromBech32(draft.receiver), + gasLimit: new BigNumber(draft.gasLimit).toNumber(), + chainID: "", + value: draft.value, + data: new TransactionPayload(Buffer.from(draft.data)) + }) + } + /** * Creates a new Transaction object from a TransactionNext object. */ @@ -437,11 +452,20 @@ export class Transaction { receiverUsername: transaction.receiverUsername, senderUsername: transaction.senderUsername, options: transaction.options, - version: transaction.version, - guardian: Address.fromBech32(transaction.guardian) + version: transaction.version }); - tx.applySignature(transaction.signature); - tx.applyGuardianSignature(transaction.guardianSignature); + + if (transaction.guardian) { + tx.guardian = Address.fromBech32(transaction.guardian) + } + + if (transaction.signature.length) { + tx.applySignature(transaction.signature); + } + + if (transaction.guardianSignature) { + tx.applyGuardianSignature(transaction.guardianSignature); + } return tx; } @@ -605,23 +629,22 @@ export class TransactionNext{ export class TransactionComputer { constructor() {} - computeTrnsactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber{ - let moveBalanceGas = - networkConfig.MinGasLimit.valueOf() + - transaction.data.length * networkConfig.GasPerDataByte.valueOf(); - if (new BigNumber(moveBalanceGas) > transaction.gasLimit) { + computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber{ + let moveBalanceGas = new BigNumber( + networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte); + if (moveBalanceGas > transaction.gasLimit) { throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); } let gasPrice = new BigNumber(transaction.gasPrice); - let feeForMove = new BigNumber(moveBalanceGas).multipliedBy(gasPrice); - if (moveBalanceGas === transaction.gasLimit.valueOf()) { + let feeForMove = moveBalanceGas.multipliedBy(gasPrice); + if (moveBalanceGas === transaction.gasLimit) { return feeForMove; } - let diff = new BigNumber(transaction.gasLimit).minus(new BigNumber(moveBalanceGas)); + let diff = new BigNumber(transaction.gasLimit).minus(moveBalanceGas); let modifiedGasPrice = gasPrice.multipliedBy( - new BigNumber(networkConfig.GasPriceModifier.valueOf()) + new BigNumber(networkConfig.GasPriceModifier) ); let processingFee = diff.multipliedBy(modifiedGasPrice); @@ -643,9 +666,9 @@ export class TransactionComputer { delete plainTransaction.guardian } - let serialized = JSON.stringify(plainTransaction); + const serialized = JSON.stringify(plainTransaction); - return new Uint8Array(Buffer.from(serialized).buffer); + return new Uint8Array(Buffer.from(serialized)); } computeTransactionHash(transaction: ITransactionNext): Uint8Array{ diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts new file mode 100644 index 000000000..5d7bcfe9c --- /dev/null +++ b/src/transactionNext.spec.ts @@ -0,0 +1,217 @@ +import { assert } from "chai"; +import { TestWallet, loadTestWallets } from "./testutils"; +import { TransactionNext, TransactionComputer, Transaction } from "./transaction"; +import BigNumber from "bignumber.js"; +import { ProtoSerializer } from "./proto"; + +class NetworkConfig { + MinGasLimit: number; + GasPerDataByte: number; + GasPriceModifier: number; + ChainID: string; + + constructor(minGasLimit: number = 50000) { + this.MinGasLimit = minGasLimit; + this.GasPerDataByte = 1500; + this.GasPriceModifier = 0.01; + this.ChainID = "D"; + } +} + +describe("test transaction next", async () => { + let wallets: Record; + const networkConfig = new NetworkConfig(); + const transactionComputer = new TransactionComputer(); + + before(async function () { + wallets = await loadTestWallets(); + }); + + it("should serialize transaction for signing", async () => { + const sender = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + const receiver = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; + + let transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: sender, + receiver: receiver, + gasLimit: 50000, + value: 0, + version: 2, + nonce: 89, + }); + + let serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + let serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + + assert.equal( + serializedTransaction, + `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}` + ); + + transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: sender, + receiver: receiver, + gasLimit: 70000, + value: new BigNumber("1000000000000000000"), + version: 2, + nonce: 90, + data: new Uint8Array(Buffer.from("hello")), + }); + + serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + + assert.equal( + serializedTransaction, + `{"nonce":90,"value":"1000000000000000000","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":70000,"data":"aGVsbG8=","chainID":"D","version":2}` + ); + }); + + it("should serialize transaction with usernames", async () => { + const transaction = new TransactionNext({ + chainID: "T", + sender: wallets.carol.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 50000, + value: new BigNumber("1000000000000000000"), + version: 2, + nonce: 204, + senderUsername: "carol", + receiverUsername: "alice", + }); + + transaction.signature = await wallets.carol.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)) + ); + console.log(Buffer.from(transaction.signature).toString("hex")); + + assert.equal( + Buffer.from(transaction.signature).toString("hex"), + "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06" + ); + }); + + it("should compute transaction hash", async () => { + const transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 100000, + value: new BigNumber("1000000000000"), + version: 2, + nonce: 17243, + data: Buffer.from("testtx"), + }); + transaction.signature = Buffer.from( + "eaa9e4dfbd21695d9511e9754bde13e90c5cfb21748a339a79be11f744c71872e9fe8e73c6035c413f5f08eef09e5458e9ea6fc315ff4da0ab6d000b450b2a07", + "hex" + ); + + const hash: any = transactionComputer.computeTransactionHash(transaction); + assert.equal(hash.digest("hex"), "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03"); + }); + + it("should compute transaction hash with usernames", async () => { + const transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 100000, + value: new BigNumber("1000000000000"), + version: 2, + nonce: 17244, + data: Buffer.from("testtx"), + senderUsername: "alice", + receiverUsername: "alice", + }); + transaction.signature = Buffer.from( + "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", + "hex" + ); + + const hash: any = transactionComputer.computeTransactionHash(transaction); + assert.equal(hash.digest("hex"), "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29"); + }); + + it("should throw `NotEnoughGas` error", async () => { + const transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 50000, + data: Buffer.from("toolittlegaslimit"), + }); + + assert.throws(() => { + transactionComputer.computeTransactionFee(transaction, networkConfig); + }); + }); + + it("should compute transaction fee", async () => { + const transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 20, + gasPrice: 500, + }); + + const config = new NetworkConfig(10); + const gasLimit = transactionComputer.computeTransactionFee(transaction, config); + assert.equal(gasLimit.toString(), "5050"); + }); + + it("should compute transaction fee for transaction with data field", async () => { + const transaction = new TransactionNext({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 12010, + gasPrice: 500, + data: Buffer.from("testdata"), + }); + + const config = new NetworkConfig(10); + const gasLimit = transactionComputer.computeTransactionFee(transaction, config); + assert.equal(gasLimit.toString(), "6005000"); + }); + + it.only("should compute guarded transaction", async () => { + const alice = wallets.alice; + + const transaction = new TransactionNext({ + chainID: "local-testnet", + sender: alice.address.bech32(), + receiver: wallets.bob.address.bech32(), + gasLimit: 150000, + gasPrice: 1000000000, + data: Buffer.from("test data field"), + version: 2, + options: 2, + nonce: 92, + value: new BigNumber("123456789000000000000000000000"), + guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", + }); + transaction.guardianSignature = new Uint8Array(64); + transaction.signature = new Uint8Array( + await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))) + ); + + const oldTransaction = Transaction.fromTransactionNext(transaction); + + let serializer = new ProtoSerializer(); + let buffer = serializer.serializeTransaction(oldTransaction); + assert.equal( + buffer.toString("hex"), + "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ); + + const txHash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(txHash).toString("hex"), + "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c" + ); + }); +}); From 43cd1b351ae95b57dde17136636b46d4276ce19f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Dec 2023 14:19:04 +0200 Subject: [PATCH 062/275] fixes --- src/transaction.ts | 9 +++++---- src/transactionNext.spec.ts | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 5a4ad8ec7..178744a29 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -445,7 +445,7 @@ export class Transaction { receiver: Address.fromBech32(transaction.receiver), gasLimit: new BigNumber(transaction.gasLimit).toNumber(), chainID: transaction.chainID, - value: transaction.value, + value: new BigNumber(transaction.value).toFixed(0), data: new TransactionPayload(Buffer.from(transaction.data)), nonce: Number(transaction.nonce), gasPrice: Number(transaction.gasPrice), @@ -677,15 +677,16 @@ export class TransactionComputer { const tx = Transaction.fromTransactionNext(transaction); let buffer = serializer.serializeTransaction(tx); let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) - .update(buffer); + .update(buffer) + .digest("hex"); - return hash; + return new Uint8Array(Buffer.from(hash, "hex")); } private toPlainObject(transaction: ITransactionNext) { return { nonce: Number(transaction.nonce), - value: transaction.value.toString(), + value: new BigNumber(transaction.value).toFixed(0), receiver: transaction.receiver, sender: transaction.sender, senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts index 5d7bcfe9c..3649ad01a 100644 --- a/src/transactionNext.spec.ts +++ b/src/transactionNext.spec.ts @@ -109,8 +109,11 @@ describe("test transaction next", async () => { "hex" ); - const hash: any = transactionComputer.computeTransactionHash(transaction); - assert.equal(hash.digest("hex"), "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03"); + const hash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(hash).toString("hex"), + "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03" + ); }); it("should compute transaction hash with usernames", async () => { @@ -131,8 +134,11 @@ describe("test transaction next", async () => { "hex" ); - const hash: any = transactionComputer.computeTransactionHash(transaction); - assert.equal(hash.digest("hex"), "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29"); + const hash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(hash).toString("hex"), + "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29" + ); }); it("should throw `NotEnoughGas` error", async () => { @@ -178,7 +184,7 @@ describe("test transaction next", async () => { assert.equal(gasLimit.toString(), "6005000"); }); - it.only("should compute guarded transaction", async () => { + it("should compute guarded transaction", async () => { const alice = wallets.alice; const transaction = new TransactionNext({ @@ -187,7 +193,7 @@ describe("test transaction next", async () => { receiver: wallets.bob.address.bech32(), gasLimit: 150000, gasPrice: 1000000000, - data: Buffer.from("test data field"), + data: new Uint8Array(Buffer.from("test data field")), version: 2, options: 2, nonce: 92, From c82b0fa25c9309d9b75283a966584d8ac19773f4 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 3 Jan 2024 13:32:00 +0200 Subject: [PATCH 063/275] fixes after review --- src/transaction.spec.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 748bcf9c5..0f0d3f738 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -41,22 +41,23 @@ describe("test transaction construction", async () => { }); it("create transaction from transaction next", async () => { - const nextTransaction = new TransactionNext({ + const plainTransactionNextObject = { sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", gasLimit: 56000, value: "1000000000000000000", data: Buffer.from("test"), chainID: "T" - }); + }; + const nextTransaction = new TransactionNext(plainTransactionNextObject); const transaction = Transaction.fromTransactionNext(nextTransaction); - assert.deepEqual(transaction.getSender(), Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")); - assert.deepEqual(transaction.getReceiver(), Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx")); - assert.equal(transaction.getGasLimit().valueOf(), 56000); - assert.equal(transaction.getValue().toString(), "1000000000000000000"); - assert.equal(transaction.getData().toString(), "test"); - assert.equal(transaction.getChainID().valueOf(), "T"); + assert.deepEqual(transaction.getSender(), Address.fromBech32(plainTransactionNextObject.sender)); + assert.deepEqual(transaction.getReceiver(), Address.fromBech32(plainTransactionNextObject.receiver)); + assert.equal(transaction.getGasLimit().valueOf(), plainTransactionNextObject.gasLimit); + assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value); + assert.equal(transaction.getData().toString(), plainTransactionNextObject.data.toString()); + assert.equal(transaction.getChainID().valueOf(), plainTransactionNextObject.chainID); assert.equal(transaction.getNonce().valueOf(), 0); assert.equal(transaction.getGasPrice().valueOf(), TRANSACTION_MIN_GAS_PRICE); assert.deepEqual(transaction.getSignature(), Buffer.from([])); From ed2bb69e64659258ecc67f4c45f9a64634f446be Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 3 Jan 2024 17:09:49 +0200 Subject: [PATCH 064/275] add method for creating relayed v1 transactions --- src/errors.ts | 2 +- src/transaction.ts | 4 +- .../relayedTransactionsFactory.spec.ts | 181 ++++++++++++++++++ .../relayedTransactionsFactory.ts | 60 +++++- 4 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 src/transactionsFactories/relayedTransactionsFactory.spec.ts diff --git a/src/errors.ts b/src/errors.ts index caa1308a0..1f23fd1ca 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -360,4 +360,4 @@ export class ErrInvalidInnerTransaction extends Err{ public constructor(message: string){ super(message); } -} \ No newline at end of file +} diff --git a/src/transaction.ts b/src/transaction.ts index 178744a29..899e40692 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { Compatibility } from "./compatibility"; -import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT } from "./constants"; +import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; import * as errors from "./errors"; import { Hash } from "./hash"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; @@ -614,7 +614,7 @@ export class TransactionNext{ this.gasLimit = gasLimit; this.data = data || new Uint8Array(); this.chainID = chainID; - this.version = version || TRANSACTION_OPTIONS_DEFAULT; + this.version = version || TRANSACTION_VERSION_DEFAULT; this.options = options || TRANSACTION_OPTIONS_DEFAULT; this.guardian = guardian || ""; diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts new file mode 100644 index 000000000..8737b363b --- /dev/null +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -0,0 +1,181 @@ +import { assert } from "chai"; +import { TestWallet, loadTestWallets } from "../testutils"; +import { TransactionComputer, TransactionNext } from "../transaction"; +import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; +import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; +import BigNumber from "bignumber.js"; + +describe("test relayed v1 transaction builder", function () { + const config = new TransactionsFactoryConfig("T"); + const factory = new RelayedTransactionsFactory(config); + const transactionComputer = new TransactionComputer(); + let alice: TestWallet, bob: TestWallet, carol: TestWallet, grace: TestWallet, frank: TestWallet; + + before(async function () { + ({ alice, bob, carol, grace, frank } = await loadTestWallets()); + }); + + it("should throw exception when creating relayed v1 transaction with invalid inner transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: alice.address.bech32(), + receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + gasLimit: 10000000, + data: Buffer.from("getContractConfig"), + chainID: config.chainID, + }); + + assert.throws(() => { + factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, relayerAddress: bob.address }), + "The inner transaction is not signed"; + }); + + innerTransaction.gasLimit = 0; + innerTransaction.signature = Buffer.from("invalidsignature"); + + assert.throws(() => { + factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, relayerAddress: bob.address }), + "The gas limit is not set for the inner transaction"; + }); + }); + + it("should create relayed v1 transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: bob.address.bech32(), + receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + gasLimit: 60000000, + data: Buffer.from("getContractConfig"), + chainID: config.chainID, + nonce: 198, + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV1Transaction({ + innerTransaction: innerTransaction, + relayerAddress: alice.address, + }); + relayedTransaction.nonce = 2627; + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2272525455544858677a4273496e4f6e454b6b7869642b354e66524d486e33534948314673746f577352434c434b3258514c41614f4e704449346531476173624c5150616130566f364144516d4f2b52446b6f364a43413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a327d" + ); + assert.equal( + Buffer.from(relayedTransaction.signature).toString("hex"), + "128e7cdc14c2b9beee2f3ff7a7fa5d1f5ef31a654a0c92e223c90ab28265fa277d306f23a06536248cf9573e828017004fb639617fade4d68a37524aafca710d" + ); + }); + + it("should create relayed v1 transaction with usernames", async function () { + let innerTransaction = new TransactionNext({ + sender: carol.address.bech32(), + receiver: alice.address.bech32(), + gasLimit: 50000, + chainID: config.chainID, + nonce: 208, + senderUsername: "carol", + receiverUsername: "alice", + value: new BigNumber("1000000000000000000"), + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await carol.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV1Transaction({ + innerTransaction: innerTransaction, + relayerAddress: frank.address, + }); + relayedTransaction.nonce = 715; + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a226a33427a6469554144325963517473576c65707663664a6f75657a48573063316b735a424a4d6339573167435450512b6870636759457858326f6f367a4b5654347464314b4b6f79783841526a346e336474576c44413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d" + ); + assert.equal( + Buffer.from(relayedTransaction.signature).toString("hex"), + "3787d640e5a579e7977a4a1bcdd435ad11855632fa4a414a06fbf8355692d1a58d76ef0adbdd6ccd6bd3c329f36bd53c180d4873ec1a6c558e659aeb9ab92d00" + ); + }); + + it("should create relayed v1 transaction with guarded inner transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: bob.address.bech32(), + receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", + gasLimit: 60000000, + chainID: config.chainID, + data: Buffer.from("getContractConfig"), + nonce: 198, + version: 2, + options: 2, + guardian: grace.address.bech32(), + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.guardianSignature = await grace.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV1Transaction({ + innerTransaction: innerTransaction, + relayerAddress: alice.address, + }); + relayedTransaction.nonce = 2627; + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a222b5431526f4833625a792f54423177342b6a365155477258645637457577553073753948646551626453515269463953757a686d634b705463526d58595252366c534c6652394931624d7134674730436538363741513d3d227d" + ); + assert.equal( + Buffer.from(relayedTransaction.signature).toString("hex"), + "39cff9d5100e290fbc7361cb6e2402261caf864257b4116f150e0c61e7869155dff8361fa5449431eb7a8ed847c01ba9b3b5ebafe5fac1a3d40c64829d827e00" + ); + }); + + it("should create guarded relayed v1 transaction with guarded inner transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: bob.address.bech32(), + receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", + gasLimit: 60000000, + chainID: config.chainID, + data: Buffer.from("addNumber"), + nonce: 198, + version: 2, + options: 2, + guardian: grace.address.bech32(), + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.guardianSignature = await grace.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV1Transaction({ + innerTransaction: innerTransaction, + relayerAddress: alice.address, + }); + relayedTransaction.nonce = 2627; + relayedTransaction.options = 2; + relayedTransaction.guardian = frank.address.bech32(); + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.guardianSignature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b546e5674596d5679222c227369676e6174757265223a223469724d4b4a656d724d375174344e7635487633544c44683775654779487045564c4371674a3677652f7a662b746a4933354975573452633458543451533433475333356158386c6a533834324a38426854645043673d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a2270424754394e674a78307539624c56796b654d78786a454865374269696c37764932324a46676f32787a6e2f496e3032463769546563356b44395045324f747065386c475335412b532f4a36417762576834446744673d3d227d" + ); + assert.equal( + Buffer.from(relayedTransaction.signature).toString("hex"), + "8ede1bbeed96b102344dffeac12c2592c62b7313cdeb132e8c8bf11d2b1d3bb8189d257a6dbcc99e222393d9b9ec77656c349dae97a32e68bdebd636066bf706" + ); + }); +}); diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 61c37bc45..42495a16b 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -1,7 +1,8 @@ import BigNumber from "bignumber.js"; -import { Transaction } from "../transaction"; +import { TransactionNext } from "../transaction"; import { IAddress } from "../interface"; import { ErrInvalidInnerTransaction } from "../errors"; +import { Address } from "../address"; interface IConfig { chainID: string; @@ -16,9 +17,62 @@ export class RelayedTransactionsFactory { this.config = config; } - createRelayedV1Transaction(options: { innerTransaction: Transaction; relayerAddress: IAddress }) { - if (!options.innerTransaction.getGasLimit()) { + createRelayedV1Transaction(options: { + innerTransaction: TransactionNext; + relayerAddress: IAddress; + }): TransactionNext { + if (!options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit is not set for the inner transaction"); } + + if (!options.innerTransaction.signature.length) { + throw new ErrInvalidInnerTransaction("The inner transaction is not signed"); + } + + const serializedTransaction = this.prepareInnerTransactionForRelayedV1(options.innerTransaction); + const data = `relayedTx@${Buffer.from(serializedTransaction).toString("hex")}`; + + const gasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy(new BigNumber(data.length)); + const gasLimit = new BigNumber(this.config.minGasLimit) + .plus(gasForDataLength) + .plus(new BigNumber(options.innerTransaction.gasLimit)); + + return new TransactionNext({ + chainID: this.config.chainID, + sender: options.relayerAddress.bech32(), + receiver: options.innerTransaction.sender, + gasLimit: gasLimit, + data: Buffer.from(data), + }); + } + + private prepareInnerTransactionForRelayedV1(innerTransaction: TransactionNext): string { + const txObject = { + nonce: new BigNumber(innerTransaction.nonce.toString(), 10).toNumber(), + sender: Address.fromBech32(innerTransaction.sender).pubkey().toString("base64"), + receiver: Address.fromBech32(innerTransaction.receiver).pubkey().toString("base64"), + value: new BigNumber(innerTransaction.value.toString(), 10).toNumber(), + gasPrice: new BigNumber(innerTransaction.gasPrice.toString(), 10).toNumber(), + gasLimit: new BigNumber(innerTransaction.gasLimit.toString(), 10).toNumber(), + data: Buffer.from(innerTransaction.data).toString("base64"), + signature: Buffer.from(innerTransaction.signature).toString("base64"), + chainID: Buffer.from(innerTransaction.chainID).toString("base64"), + version: innerTransaction.version, + options: innerTransaction.options.valueOf() == 0 ? undefined : innerTransaction.options, + guardian: innerTransaction.guardian + ? Address.fromBech32(innerTransaction.guardian).pubkey().toString("base64") + : undefined, + guardianSignature: innerTransaction.guardianSignature.length + ? Buffer.from(innerTransaction.guardianSignature).toString("base64") + : undefined, + sndUserName: innerTransaction.senderUsername + ? Buffer.from(innerTransaction.senderUsername).toString("base64") + : undefined, + rcvUserName: innerTransaction.receiverUsername + ? Buffer.from(innerTransaction.receiverUsername).toString("base64") + : undefined, + }; + + return JSON.stringify(txObject); } } From abfd4bcea53fff6adce2d19d006638597725c22d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 3 Jan 2024 19:54:41 +0200 Subject: [PATCH 065/275] add method for creating relayed v2 transactions --- .../relayedTransactionsFactory.spec.ts | 62 +++++++++++++++++++ .../relayedTransactionsFactory.ts | 52 ++++++++++++++-- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 8737b363b..2c53bb04f 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -178,4 +178,66 @@ describe("test relayed v1 transaction builder", function () { "8ede1bbeed96b102344dffeac12c2592c62b7313cdeb132e8c8bf11d2b1d3bb8189d257a6dbcc99e222393d9b9ec77656c349dae97a32e68bdebd636066bf706" ); }); + + it("should throw exception when creating relayed v2 transaction with invalid inner transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: bob.address.bech32(), + receiver: bob.address.bech32(), + gasLimit: 50000, + chainID: config.chainID, + }); + + assert.throws(() => { + factory.createRelayedV2Transaction({ + innerTransaction: innerTransaction, + innerTransactionGasLimit: 50000, + relayerAddress: carol.address, + }), + "The gas limit should not be set for the inner transaction"; + }); + + innerTransaction.gasLimit = 0; + + assert.throws(() => { + factory.createRelayedV2Transaction({ + innerTransaction: innerTransaction, + innerTransactionGasLimit: 50000, + relayerAddress: carol.address, + }), + "The inner transaction is not signed"; + }); + }); + + it("should create relayed v2 transaction", async function () { + let innerTransaction = new TransactionNext({ + sender: bob.address.bech32(), + receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + gasLimit: 0, + chainID: config.chainID, + data: Buffer.from("getContractConfig"), + nonce: 15, + version: 2, + options: 0, + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV2Transaction({ + innerTransaction: innerTransaction, + innerTransactionGasLimit: new BigNumber("60000000"), + relayerAddress: alice.address, + }); + relayedTransaction.nonce = 37; + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal(relayedTransaction.version, 2); + assert.equal(relayedTransaction.options, 0); + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c" + ); + }); }); diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 42495a16b..7f66aff9e 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -1,8 +1,9 @@ import BigNumber from "bignumber.js"; import { TransactionNext } from "../transaction"; -import { IAddress } from "../interface"; +import { IAddress, ITransactionNext } from "../interface"; import { ErrInvalidInnerTransaction } from "../errors"; import { Address } from "../address"; +import { AddressValue, ArgSerializer, BytesValue, U64Value } from "../smartcontracts"; interface IConfig { chainID: string; @@ -18,7 +19,7 @@ export class RelayedTransactionsFactory { } createRelayedV1Transaction(options: { - innerTransaction: TransactionNext; + innerTransaction: ITransactionNext; relayerAddress: IAddress; }): TransactionNext { if (!options.innerTransaction.gasLimit) { @@ -32,9 +33,11 @@ export class RelayedTransactionsFactory { const serializedTransaction = this.prepareInnerTransactionForRelayedV1(options.innerTransaction); const data = `relayedTx@${Buffer.from(serializedTransaction).toString("hex")}`; - const gasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy(new BigNumber(data.length)); + const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( + new BigNumber(data.length) + ); const gasLimit = new BigNumber(this.config.minGasLimit) - .plus(gasForDataLength) + .plus(additionalGasForDataLength) .plus(new BigNumber(options.innerTransaction.gasLimit)); return new TransactionNext({ @@ -46,6 +49,47 @@ export class RelayedTransactionsFactory { }); } + createRelayedV2Transaction(options: { + innerTransaction: ITransactionNext; + innerTransactionGasLimit: BigNumber.Value; + relayerAddress: IAddress; + }): TransactionNext { + if (options.innerTransaction.gasLimit) { + throw new ErrInvalidInnerTransaction("The gas limit should not be set for the inner transaction"); + } + + if (!options.innerTransaction.signature.length) { + throw new ErrInvalidInnerTransaction("The inner transaction is not signed"); + } + + const { argumentsString } = new ArgSerializer().valuesToString([ + new AddressValue(Address.fromBech32(options.innerTransaction.receiver)), + new U64Value(options.innerTransaction.nonce), + new BytesValue(Buffer.from(options.innerTransaction.data)), + new BytesValue(Buffer.from(options.innerTransaction.signature)), + ]); + + const data = `relayedTxV2@${argumentsString}`; + + const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( + new BigNumber(data.length) + ); + const gasLimit = new BigNumber(options.innerTransaction.gasLimit) + .plus(new BigNumber(this.config.minGasLimit)) + .plus(additionalGasForDataLength); + + return new TransactionNext({ + sender: options.relayerAddress.bech32(), + receiver: options.innerTransaction.sender, + value: 0, + gasLimit: gasLimit, + chainID: this.config.chainID, + data: Buffer.from(data), + version: options.innerTransaction.version, + options: options.innerTransaction.options, + }); + } + private prepareInnerTransactionForRelayedV1(innerTransaction: TransactionNext): string { const txObject = { nonce: new BigNumber(innerTransaction.nonce.toString(), 10).toNumber(), From 55703bea1aa71aba811abc56a620b8ed1eeaab9a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 4 Jan 2024 13:51:53 +0200 Subject: [PATCH 066/275] fixes after review --- src/transaction.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 178744a29..ec0e41395 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,7 +1,7 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { Compatibility } from "./compatibility"; -import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT } from "./constants"; +import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; import * as errors from "./errors"; import { Hash } from "./hash"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; @@ -463,7 +463,7 @@ export class Transaction { tx.applySignature(transaction.signature); } - if (transaction.guardianSignature) { + if (transaction.guardianSignature.length) { tx.applyGuardianSignature(transaction.guardianSignature); } @@ -614,7 +614,7 @@ export class TransactionNext{ this.gasLimit = gasLimit; this.data = data || new Uint8Array(); this.chainID = chainID; - this.version = version || TRANSACTION_OPTIONS_DEFAULT; + this.version = version || TRANSACTION_VERSION_DEFAULT; this.options = options || TRANSACTION_OPTIONS_DEFAULT; this.guardian = guardian || ""; @@ -630,29 +630,29 @@ export class TransactionComputer { constructor() {} computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber{ - let moveBalanceGas = new BigNumber( + const moveBalanceGas = new BigNumber( networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte); if (moveBalanceGas > transaction.gasLimit) { throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); } - let gasPrice = new BigNumber(transaction.gasPrice); - let feeForMove = moveBalanceGas.multipliedBy(gasPrice); + const gasPrice = new BigNumber(transaction.gasPrice); + const feeForMove = moveBalanceGas.multipliedBy(gasPrice); if (moveBalanceGas === transaction.gasLimit) { return feeForMove; } - let diff = new BigNumber(transaction.gasLimit).minus(moveBalanceGas); - let modifiedGasPrice = gasPrice.multipliedBy( + const diff = new BigNumber(transaction.gasLimit).minus(moveBalanceGas); + const modifiedGasPrice = gasPrice.multipliedBy( new BigNumber(networkConfig.GasPriceModifier) ); - let processingFee = diff.multipliedBy(modifiedGasPrice); + const processingFee = diff.multipliedBy(modifiedGasPrice); return feeForMove.plus(processingFee); } computeBytesForSigning(transaction: ITransactionNext): Uint8Array{ - let plainTransaction = this.toPlainObject(transaction); + const plainTransaction = this.toPlainObject(transaction); if (plainTransaction.signature) { delete plainTransaction.signature; @@ -675,12 +675,12 @@ export class TransactionComputer { let serializer = new ProtoSerializer(); const tx = Transaction.fromTransactionNext(transaction); - let buffer = serializer.serializeTransaction(tx); - let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) + const buffer = serializer.serializeTransaction(tx); + const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) .update(buffer) .digest("hex"); - return new Uint8Array(Buffer.from(hash, "hex")); + return Buffer.from(hash, "hex"); } private toPlainObject(transaction: ITransactionNext) { @@ -693,11 +693,11 @@ export class TransactionComputer { receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, gasPrice: Number(transaction.gasPrice), gasLimit: Number(transaction.gasLimit), - data: transaction.data.length == 0 ? undefined : Buffer.from(transaction.data).toString("base64"), + data: transaction.data && transaction.data.length === 0 ? undefined : Buffer.from(transaction.data).toString("base64"), chainID: transaction.chainID, version: transaction.version, - options: transaction.options == 0 ? undefined : transaction.options, - guardian: transaction.guardian == "" ? undefined : transaction.guardian, + options: transaction.options ? transaction.options : undefined, + guardian: transaction.guardian ? transaction.guardian : undefined, signature: transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), guardianSignature: transaction.guardianSignature.length == 0 ? undefined : Buffer.from(transaction.guardianSignature).toString("hex") } From 0b92e8511481ef336b89c041f1e08f2c637efe9b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 8 Jan 2024 16:01:31 +0200 Subject: [PATCH 067/275] fix gas computation for relayed v2 --- src/transactionsFactories/relayedTransactionsFactory.spec.ts | 1 + src/transactionsFactories/relayedTransactionsFactory.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 2c53bb04f..9dffd4154 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -235,6 +235,7 @@ describe("test relayed v1 transaction builder", function () { assert.equal(relayedTransaction.version, 2); assert.equal(relayedTransaction.options, 0); + assert.equal(relayedTransaction.gasLimit.toString(), "60414500"); assert.equal( Buffer.from(relayedTransaction.data).toString(), "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c" diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 7f66aff9e..74e86294c 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -74,7 +74,7 @@ export class RelayedTransactionsFactory { const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( new BigNumber(data.length) ); - const gasLimit = new BigNumber(options.innerTransaction.gasLimit) + const gasLimit = new BigNumber(options.innerTransactionGasLimit) .plus(new BigNumber(this.config.minGasLimit)) .plus(additionalGasForDataLength); From c027a00517fe87835c1b732887cb6a922fd57c6a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 19 Jan 2024 14:22:08 +0200 Subject: [PATCH 068/275] bugfixes and fixes after review --- package-lock.json | 11 ++++++ package.json | 1 + src/relayedTransactionV1Builder.spec.ts | 36 +++++++++++++++++++ src/relayedTransactionV1Builder.ts | 6 ++-- .../relayedTransactionsFactory.spec.ts | 34 ++++++++++++++++++ .../relayedTransactionsFactory.ts | 12 ++++--- 6 files changed, 93 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index db9905f8d..2edd91a28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", + "@types/json-bigint": "^1.0.4", "bech32": "1.1.4", "bignumber.js": "9.0.1", "blake2b": "2.1.3", @@ -645,6 +646,11 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "node_modules/@types/json-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz", + "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==" + }, "node_modules/@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -4926,6 +4932,11 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "@types/json-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz", + "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==" + }, "@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", diff --git a/package.json b/package.json index 5b98c6475..c62d3184f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", + "@types/json-bigint": "^1.0.4", "bech32": "1.1.4", "bignumber.js": "9.0.1", "blake2b": "2.1.3", diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index 68248b8db..5695160f0 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -114,6 +114,42 @@ describe("test relayed v1 transaction builder", function () { assert.equal(relayedTxV1.getSignature().toString("hex"), "3787d640e5a579e7977a4a1bcdd435ad11855632fa4a414a06fbf8355692d1a58d76ef0adbdd6ccd6bd3c329f36bd53c180d4873ec1a6c558e659aeb9ab92d00"); }); + it("should compute relayed v1 transaction with big value", async function () { + const networkConfig = { + MinGasLimit: 50_000, + GasPerDataByte: 1_500, + GasPriceModifier: 0.01, + ChainID: "T" + }; + + const innerTx = new Transaction({ + nonce: 208, + value: TokenTransfer.egldFromAmount(1999999), + sender: carol.address, + receiver: alice.address, + senderUsername: "carol", + receiverUsername: "alice", + gasLimit: 50000, + chainID: networkConfig.ChainID + }); + + innerTx.applySignature(await carol.signer.sign(innerTx.serializeForSigning())); + + const builder = new RelayedTransactionV1Builder(); + const relayedTxV1 = builder + .setInnerTransaction(innerTx) + .setRelayerNonce(715) + .setNetworkConfig(networkConfig) + .setRelayerAddress(frank.address) + .build(); + + relayedTxV1.applySignature(await frank.signer.sign(relayedTxV1.serializeForSigning())); + + assert.equal(relayedTxV1.getNonce().valueOf(), 715); + assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313939393939393030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22594661677972512f726d614c7333766e7159307657553858415a7939354b4e31725738347a4f764b62376c7a3773576e2f566a546d68704378774d682b7261314e444832574d6f3965507648304f79427453776a44773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d"); + assert.equal(relayedTxV1.getSignature().toString("hex"), "c0fb5cf8c0a413d6988ba35dc279c63f8849572c5f23b1cab36dcc50952dc3ed9da01068d6ac0cbde7e14167bfc2eca5164d5c2154c89eb313c9c596e3f8b801"); + }); + it("should compute guarded inner Tx - relayed v1 transaction", async function () { const networkConfig = { MinGasLimit: 50_000, diff --git a/src/relayedTransactionV1Builder.ts b/src/relayedTransactionV1Builder.ts index d87d84e53..43a66d0d5 100644 --- a/src/relayedTransactionV1Builder.ts +++ b/src/relayedTransactionV1Builder.ts @@ -7,6 +7,8 @@ import { TransactionOptions, TransactionVersion } from "./networkParams"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +const JSONbig = require("json-bigint"); + /** * @deprecated Use {@link RelayedTransactionsFactory} instead. */ @@ -134,7 +136,7 @@ export class RelayedTransactionV1Builder { "nonce": this.innerTransaction.getNonce().valueOf(), "sender": new Address(this.innerTransaction.getSender().bech32()).pubkey().toString("base64"), "receiver": new Address(this.innerTransaction.getReceiver().bech32()).pubkey().toString("base64"), - "value": new BigNumber(this.innerTransaction.getValue().toString(), 10).toNumber(), + "value": BigInt(this.innerTransaction.getValue().toString()), "gasPrice": this.innerTransaction.getGasPrice().valueOf(), "gasLimit": this.innerTransaction.getGasLimit().valueOf(), "data": this.innerTransaction.getData().valueOf().toString("base64"), @@ -148,6 +150,6 @@ export class RelayedTransactionV1Builder { "rcvUserName": this.innerTransaction.getReceiverUsername() ? Buffer.from(this.innerTransaction.getReceiverUsername()).toString("base64") : undefined, }; - return JSON.stringify(txObject); + return JSONbig.stringify(txObject); } } diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 9dffd4154..50be725c2 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -104,6 +104,40 @@ describe("test relayed v1 transaction builder", function () { ); }); + it("should create relayed v1 transaction with big value", async function () { + let innerTransaction = new TransactionNext({ + sender: carol.address.bech32(), + receiver: alice.address.bech32(), + gasLimit: 50000, + chainID: config.chainID, + nonce: 208, + senderUsername: "carol", + receiverUsername: "alice", + value: new BigNumber("1999999000000000000000000"), + }); + + const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); + innerTransaction.signature = await carol.signer.sign(Buffer.from(serializedInnerTransaction)); + + const relayedTransaction = factory.createRelayedV1Transaction({ + innerTransaction: innerTransaction, + relayerAddress: frank.address, + }); + relayedTransaction.nonce = 715; + + const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); + relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + + assert.equal( + Buffer.from(relayedTransaction.data).toString(), + "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313939393939393030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22594661677972512f726d614c7333766e7159307657553858415a7939354b4e31725738347a4f764b62376c7a3773576e2f566a546d68704378774d682b7261314e444832574d6f3965507648304f79427453776a44773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d" + ); + assert.equal( + Buffer.from(relayedTransaction.signature).toString("hex"), + "c0fb5cf8c0a413d6988ba35dc279c63f8849572c5f23b1cab36dcc50952dc3ed9da01068d6ac0cbde7e14167bfc2eca5164d5c2154c89eb313c9c596e3f8b801" + ); + }); + it("should create relayed v1 transaction with guarded inner transaction", async function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 74e86294c..898c9e8ba 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -5,6 +5,8 @@ import { ErrInvalidInnerTransaction } from "../errors"; import { Address } from "../address"; import { AddressValue, ArgSerializer, BytesValue, U64Value } from "../smartcontracts"; +const JSONbig = require("json-bigint"); + interface IConfig { chainID: string; minGasLimit: BigNumber.Value; @@ -92,12 +94,12 @@ export class RelayedTransactionsFactory { private prepareInnerTransactionForRelayedV1(innerTransaction: TransactionNext): string { const txObject = { - nonce: new BigNumber(innerTransaction.nonce.toString(), 10).toNumber(), + nonce: new BigNumber(innerTransaction.nonce).toNumber(), sender: Address.fromBech32(innerTransaction.sender).pubkey().toString("base64"), receiver: Address.fromBech32(innerTransaction.receiver).pubkey().toString("base64"), - value: new BigNumber(innerTransaction.value.toString(), 10).toNumber(), - gasPrice: new BigNumber(innerTransaction.gasPrice.toString(), 10).toNumber(), - gasLimit: new BigNumber(innerTransaction.gasLimit.toString(), 10).toNumber(), + value: BigInt(new BigNumber(innerTransaction.value).toFixed(0)), + gasPrice: new BigNumber(innerTransaction.gasPrice).toNumber(), + gasLimit: new BigNumber(innerTransaction.gasLimit).toNumber(), data: Buffer.from(innerTransaction.data).toString("base64"), signature: Buffer.from(innerTransaction.signature).toString("base64"), chainID: Buffer.from(innerTransaction.chainID).toString("base64"), @@ -117,6 +119,6 @@ export class RelayedTransactionsFactory { : undefined, }; - return JSON.stringify(txObject); + return JSONbig.stringify(txObject); } } From 06fbc6d4e7dd80f83727b8bbcb56b19427424df6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 19 Jan 2024 14:27:11 +0200 Subject: [PATCH 069/275] update package.json --- package-lock.json | 14 +------------- package.json | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2edd91a28..8d649008f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,11 @@ "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", - "@types/json-bigint": "^1.0.4", "bech32": "1.1.4", "bignumber.js": "9.0.1", "blake2b": "2.1.3", "buffer": "6.0.3", + "json-bigint": "1.0.0", "json-duplicate-key-handle": "1.0.0", "keccak": "3.0.2", "protobufjs": "7.2.4" @@ -646,11 +646,6 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, - "node_modules/@types/json-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz", - "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==" - }, "node_modules/@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -2695,7 +2690,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "dev": true, "dependencies": { "bignumber.js": "^9.0.0" } @@ -4932,11 +4926,6 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, - "@types/json-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz", - "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==" - }, "@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -6580,7 +6569,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "dev": true, "requires": { "bignumber.js": "^9.0.0" } diff --git a/package.json b/package.json index c62d3184f..5512cd1a3 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", - "@types/json-bigint": "^1.0.4", + "json-bigint": "1.0.0", "bech32": "1.1.4", "bignumber.js": "9.0.1", "blake2b": "2.1.3", From cc521e97c9525d9746ea2be6511a9914fbb8ab10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 30 Jan 2024 18:16:57 +0200 Subject: [PATCH 070/275] Switch to beta. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e2e9cad0..37e8166f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.18.0", + "version": "v13.0.0-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.18.0", + "version": "v13.0.0-beta.0", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 15109992e..d80789854 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.18.0", + "version": "v13.0.0-beta.0", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 80bbd5cae07b5866dba1289d4284d682f91c9b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 30 Jan 2024 18:51:35 +0200 Subject: [PATCH 071/275] Fix / bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 37e8166f4..633dcfe2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "v13.0.0-beta.0", + "version": "13.0.0-beta.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "v13.0.0-beta.0", + "version": "13.0.0-beta.1", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index d80789854..ad6da6df8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "v13.0.0-beta.0", + "version": "13.0.0-beta.1", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 61adbbea9133a71081b741ff952f7914e1b02e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 30 Jan 2024 20:36:20 +0200 Subject: [PATCH 072/275] Enable & configure eslint. --- .eslintrc.js | 45 + .prettierrc | 5 + package-lock.json | 2765 +++++++++++++++-- package.json | 11 +- src/reflection.ts | 4 +- src/relayedTransactionV1Builder.spec.ts | 1 - src/relayedTransactionV1Builder.ts | 1 - src/smartcontracts/argSerializer.ts | 2 + src/smartcontracts/code.spec.ts | 11 +- src/smartcontracts/code.ts | 2 - src/smartcontracts/codec/address.ts | 2 +- src/smartcontracts/codec/h256.ts | 2 +- src/smartcontracts/codec/option.ts | 2 +- src/smartcontracts/smartContract.ts | 11 +- src/smartcontracts/typesystem/numerical.ts | 4 +- src/smartcontracts/typesystem/struct.ts | 6 +- .../typesystem/typeExpressionParser.ts | 4 +- src/tokens.ts | 2 +- src/transaction.ts | 18 +- src/transactionPayload.ts | 2 - ...anagementTransactionIntentsFactory.spec.ts | 6 +- .../tokenManagementTransactionsFactory.ts | 8 +- tsconfig.eslint.json | 21 + tsconfig.tests.json | 6 +- tslint.json | 16 - 25 files changed, 2572 insertions(+), 385 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .prettierrc create mode 100644 tsconfig.eslint.json delete mode 100644 tslint.json diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..0303fe9e0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,45 @@ +module.exports = { + parser: "@typescript-eslint/parser", + parserOptions: { + project: "tsconfig.eslint.json", + sourceType: "module", + }, + plugins: ["@typescript-eslint/eslint-plugin"], + extends: [ + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + root: true, + env: { + node: true + }, + ignorePatterns: [ + ".eslintrc.js", + "node_modules", + "out", + "node_modules", + "out", + "out-tests", + "out-browser", + "out-browser-tests", + ], + rules: { + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/quotes": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-namespace": "warn", + "@typescript-eslint/no-var-requires": "warn", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-unused-vars": ["warn", { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" + }], + "prefer-const": "off", + }, +}; diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..b59536091 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": false, + "trailingComma": "all", + "printWidth": 140 +} diff --git a/package-lock.json b/package-lock.json index 633dcfe2b..51031e87c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,14 +26,19 @@ "@types/chai": "4.2.11", "@types/mocha": "9.1.0", "@types/node": "13.13.2", + "@typescript-eslint/eslint-plugin": "5.44.0", + "@typescript-eslint/parser": "5.44.0", "assert": "2.0.0", "axios": "1.6.5", "browserify": "17.0.0", "chai": "4.2.0", + "eslint": "8.28.0", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-prettier": "3.4.1", "esmify": "2.1.1", "mocha": "9.2.2", + "prettier": "2.2.1", "ts-node": "9.1.1", - "tslint": "6.1.3", "typescript": "4.1.2" } }, @@ -43,6 +48,15 @@ "@multiversx/sdk-wallet@4.0.0-beta.3": { "extraneous": true }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -429,6 +443,77 @@ "node": ">=6.9.0" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -580,6 +665,41 @@ } ] }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -646,6 +766,12 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -657,6 +783,343 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz", + "integrity": "sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/type-utils": "5.44.0", + "@typescript-eslint/utils": "5.44.0", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.44.0.tgz", + "integrity": "sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/typescript-estree": "5.44.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz", + "integrity": "sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/visitor-keys": "5.44.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz", + "integrity": "sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/utils": "5.44.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.44.0.tgz", + "integrity": "sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz", + "integrity": "sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/visitor-keys": "5.44.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.44.0.tgz", + "integrity": "sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/typescript-estree": "5.44.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz", + "integrity": "sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.44.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -675,6 +1138,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -695,6 +1167,22 @@ "node": ">=0.4.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -750,6 +1238,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1405,15 +1902,6 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -1439,6 +1927,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -1594,12 +2091,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1702,6 +2193,20 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -1771,6 +2276,12 @@ "node": ">=0.12" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -1873,100 +2384,399 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true, "engines": { - "node": ">=0.4", - "npm": ">=1.2" + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/ed25519-hd-key": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.1.2.tgz", + "integrity": "sha512-/0y9y6N7vM6Kj5ASr9J9wcMVDTtygxSOvYX+PJiMD7VcxCx2G03V5bLRl8Dug9EgkLFsLhGqBtQWQRcElEeWTA==", + "dev": true, + "dependencies": { + "bip39": "3.0.2", + "create-hmac": "1.1.7", + "tweetnacl": "1.0.3" + } + }, + "node_modules/ed2curve": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz", + "integrity": "sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ==", + "dev": true, + "dependencies": { + "tweetnacl": "1.x.x" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", + "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.15.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { - "readable-stream": "^2.0.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/ed25519-hd-key": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.1.2.tgz", - "integrity": "sha512-/0y9y6N7vM6Kj5ASr9J9wcMVDTtygxSOvYX+PJiMD7VcxCx2G03V5bLRl8Dug9EgkLFsLhGqBtQWQRcElEeWTA==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "bip39": "3.0.2", - "create-hmac": "1.1.7", - "tweetnacl": "1.0.3" + "engines": { + "node": ">=4.0" } }, - "node_modules/ed2curve": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz", - "integrity": "sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "tweetnacl": "1.x.x" + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, "node_modules/esmify": { @@ -1987,17 +2797,84 @@ "through2": "^2.0.5" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "acorn": "bin/acorn" }, "engines": { - "node": ">=4" + "node": ">=0.4.0" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" } }, "node_modules/esutils": { @@ -2028,12 +2905,73 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, + "node_modules/fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2071,6 +3009,26 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.4", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", @@ -2228,6 +3186,26 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -2240,6 +3218,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -2422,6 +3406,40 @@ } ] }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2604,6 +3622,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2656,6 +3683,16 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-sdsl": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", + "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2694,6 +3731,12 @@ "bignumber.js": "^9.0.0" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-duplicate-key-handle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-duplicate-key-handle/-/json-duplicate-key-handle-1.0.0.tgz", @@ -2702,6 +3745,18 @@ "backslash": "^0.2.0" } }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -2766,6 +3821,15 @@ "node": ">= 6" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/labeled-stream-splicer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", @@ -2776,6 +3840,19 @@ "stream-splicer": "^2.0.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2803,6 +3880,12 @@ "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -2921,15 +4004,37 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, "node_modules/miller-rabin": { @@ -3005,18 +4110,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -3227,6 +4320,18 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -3300,6 +4405,23 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -3342,6 +4464,18 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -3388,6 +4522,15 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -3403,6 +4546,15 @@ "node": ">= 0.8.0" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -3446,6 +4598,39 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3535,6 +4720,26 @@ "node": ">=0.4.x" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3611,6 +4816,18 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3637,6 +4854,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -3647,6 +4898,29 @@ "inherits": "^2.0.1" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3718,6 +4992,27 @@ "fast-safe-stringify": "^2.0.7" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/shell-quote": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", @@ -3747,6 +5042,15 @@ } ] }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -3775,12 +5079,6 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -3939,6 +5237,12 @@ "acorn-node": "^1.2.0" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4029,89 +5333,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - } - }, - "node_modules/tslint/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/tslint/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslint/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -4124,6 +5345,18 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4133,6 +5366,18 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4203,6 +5448,24 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -4438,6 +5701,12 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -4731,6 +6000,57 @@ "to-fast-properties": "^2.0.0" } }, + "@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -4860,6 +6180,32 @@ "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "dev": true }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -4926,6 +6272,12 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -4937,6 +6289,217 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" }, + "@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz", + "integrity": "sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/type-utils": "5.44.0", + "@typescript-eslint/utils": "5.44.0", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/parser": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.44.0.tgz", + "integrity": "sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/typescript-estree": "5.44.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz", + "integrity": "sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/visitor-keys": "5.44.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz", + "integrity": "sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/utils": "5.44.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/types": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.44.0.tgz", + "integrity": "sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz", + "integrity": "sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/visitor-keys": "5.44.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.44.0.tgz", + "integrity": "sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.44.0", + "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/typescript-estree": "5.44.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz", + "integrity": "sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.44.0", + "eslint-visitor-keys": "^3.3.0" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -4949,6 +6512,13 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -4966,6 +6536,18 @@ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -5009,6 +6591,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -5579,12 +7167,6 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", - "dev": true - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -5607,6 +7189,12 @@ "get-intrinsic": "^1.0.2" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -5723,12 +7311,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5828,6 +7410,17 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -5877,6 +7470,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -5957,6 +7556,24 @@ } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -6013,36 +7630,223 @@ "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", + "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.15.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true } } }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "esmify": { @@ -6063,10 +7867,63 @@ "through2": "^2.0.5" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "dependencies": { + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + } + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { @@ -6091,12 +7948,67 @@ "safe-buffer": "^5.1.1" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, + "fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6122,6 +8034,23 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "follow-redirects": { "version": "1.15.4", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", @@ -6231,6 +8160,20 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -6240,6 +8183,12 @@ "get-intrinsic": "^1.1.3" } }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -6370,6 +8319,28 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -6507,6 +8478,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -6544,6 +8521,12 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "js-sdsl": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", + "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6573,6 +8556,12 @@ "bignumber.js": "^9.0.0" } }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-duplicate-key-handle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-duplicate-key-handle/-/json-duplicate-key-handle-1.0.0.tgz", @@ -6581,6 +8570,18 @@ "backslash": "^0.2.0" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -6625,6 +8626,15 @@ } } }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "labeled-stream-splicer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", @@ -6635,6 +8645,16 @@ "stream-splicer": "^2.0.0" } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6656,6 +8676,12 @@ "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -6757,6 +8783,22 @@ "safe-buffer": "^5.1.2" } }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -6817,15 +8859,6 @@ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -6984,6 +9017,18 @@ "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -7037,6 +9082,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -7067,6 +9126,15 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -7107,6 +9175,12 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -7119,6 +9193,12 @@ "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", "dev": true }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -7150,6 +9230,27 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -7227,6 +9328,12 @@ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -7302,6 +9409,12 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7319,6 +9432,27 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -7329,6 +9463,15 @@ "inherits": "^2.0.1" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7380,6 +9523,21 @@ "fast-safe-stringify": "^2.0.7" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "shell-quote": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", @@ -7392,6 +9550,12 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7416,12 +9580,6 @@ } } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, "stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -7557,6 +9715,12 @@ "acorn-node": "^1.2.0" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -7625,69 +9789,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -7700,12 +9801,27 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -7747,6 +9863,23 @@ "picocolors": "^1.0.0" } }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + } + } + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", diff --git a/package.json b/package.json index ad6da6df8..3be1cbab0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "compile": "tsc -p tsconfig.json", "compile-proto": "npx pbjs -t static-module -w commonjs -o src/proto/compiled.js src/proto/transaction.proto && npx pbts -o src/proto/compiled.d.ts src/proto/compiled.js", "browser-tests": "make clean && make browser-tests && http-server --port=9876 -o browser-tests/index.html", - "lint": "tslint --project .", + "lint": "eslint .", "pretest": "npm run compile", "prepare": "npm run compile" }, @@ -49,7 +49,12 @@ "esmify": "2.1.1", "mocha": "9.2.2", "ts-node": "9.1.1", - "tslint": "6.1.3", - "typescript": "4.1.2" + "typescript": "4.1.2", + "@typescript-eslint/eslint-plugin": "5.44.0", + "@typescript-eslint/parser": "5.44.0", + "eslint": "8.28.0", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-prettier": "3.4.1", + "prettier": "2.2.1" } } diff --git a/src/reflection.ts b/src/reflection.ts index 836ffdb03..1c020c23c 100644 --- a/src/reflection.ts +++ b/src/reflection.ts @@ -1,5 +1,5 @@ -export function getJavascriptPrototypesInHierarchy(obj: Object, filter: (prototype: any) => boolean): Object[] { - let prototypes: Object[] = []; +export function getJavascriptPrototypesInHierarchy(obj: any, filter: (prototype: any) => boolean): any[] { + let prototypes: any[] = []; let prototype: any = Object.getPrototypeOf(obj); while (prototype && filter(prototype)) { diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index 5695160f0..aeb5a060a 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -3,7 +3,6 @@ import { Address } from "./address"; import * as errors from "./errors"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { RelayedTransactionV1Builder } from "./relayedTransactionV1Builder"; -import { Signature } from "./signature"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; import { Transaction } from "./transaction"; diff --git a/src/relayedTransactionV1Builder.ts b/src/relayedTransactionV1Builder.ts index 43a66d0d5..c4871b61b 100644 --- a/src/relayedTransactionV1Builder.ts +++ b/src/relayedTransactionV1Builder.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { Address } from "./address"; import { ErrInvalidRelayedV1BuilderArguments } from "./errors"; import { IAddress, INonce } from "./interface"; diff --git a/src/smartcontracts/argSerializer.ts b/src/smartcontracts/argSerializer.ts index d4dbeafb3..fbf3c492e 100644 --- a/src/smartcontracts/argSerializer.ts +++ b/src/smartcontracts/argSerializer.ts @@ -55,6 +55,7 @@ export class ArgSerializer { */ buffersToValues(buffers: Buffer[], parameters: IParameterDefinition[]): TypedValue[] { // TODO: Refactor, split (function is quite complex). + // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; buffers = buffers || []; @@ -158,6 +159,7 @@ export class ArgSerializer { */ valuesToBuffers(values: TypedValue[]): Buffer[] { // TODO: Refactor, split (function is quite complex). + // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; const buffers: Buffer[] = []; diff --git a/src/smartcontracts/code.spec.ts b/src/smartcontracts/code.spec.ts index 1a5f3d94e..2dd2425df 100644 --- a/src/smartcontracts/code.spec.ts +++ b/src/smartcontracts/code.spec.ts @@ -1,26 +1,25 @@ import { assert } from "chai"; import { Code } from "./code"; -import { Hash } from "../hash"; -describe("Code Class Tests", function() { +describe("Code Class Tests", function () { const sampleHex = "abcdef0123456789"; const sampleBuffer = Buffer.from(sampleHex, "hex"); - it("should create Code from buffer", function() { + it("should create Code from buffer", function () { const code = Code.fromBuffer(sampleBuffer); assert.instanceOf(code, Code); assert.equal(code.toString(), sampleHex); }); - it("should create Code from hex string", function() { + it("should create Code from hex string", function () { const code = Code.fromHex(sampleHex); assert.instanceOf(code, Code); assert.equal(code.toString(), sampleHex); }); - it("should return the correct buffer from valueOf", function() { + it("should return the correct buffer from valueOf", function () { const code = Code.fromHex(sampleHex); const buffer = code.valueOf(); @@ -28,7 +27,7 @@ describe("Code Class Tests", function() { assert.equal(buffer.toString("hex"), sampleHex); }); - it("should compute hash correctly", function() { + it("should compute hash correctly", function () { const code = Code.fromHex(sampleHex); const hash = code.computeHash(); diff --git a/src/smartcontracts/code.ts b/src/smartcontracts/code.ts index 54c540a35..6b7700414 100644 --- a/src/smartcontracts/code.ts +++ b/src/smartcontracts/code.ts @@ -1,5 +1,3 @@ -import { Hash } from "../hash"; - const createHasher = require('blake2b') const CODE_HASH_LENGTH = 32 diff --git a/src/smartcontracts/codec/address.ts b/src/smartcontracts/codec/address.ts index 5c8d57fad..35dd0a825 100644 --- a/src/smartcontracts/codec/address.ts +++ b/src/smartcontracts/codec/address.ts @@ -21,7 +21,7 @@ export class AddressBinaryCodec { * @param buffer the input buffer */ decodeTopLevel(buffer: Buffer): AddressValue { - let [decoded, length] = this.decodeNested(buffer); + let [decoded, _length] = this.decodeNested(buffer); return decoded; } diff --git a/src/smartcontracts/codec/h256.ts b/src/smartcontracts/codec/h256.ts index 7806c2a80..76418b650 100644 --- a/src/smartcontracts/codec/h256.ts +++ b/src/smartcontracts/codec/h256.ts @@ -18,7 +18,7 @@ export class H256BinaryCodec { * @param buffer the input buffer */ decodeTopLevel(buffer: Buffer): H256Value { - let [decoded, length] = this.decodeNested(buffer); + let [decoded, _length] = this.decodeNested(buffer); return decoded; } diff --git a/src/smartcontracts/codec/option.ts b/src/smartcontracts/codec/option.ts index f10971224..37cdc58ef 100644 --- a/src/smartcontracts/codec/option.ts +++ b/src/smartcontracts/codec/option.ts @@ -34,7 +34,7 @@ export class OptionValueBinaryCodec { throw new errors.ErrCodec("invalid buffer for optional value"); } - let [decoded, decodedLength] = this.binaryCodec.decodeNested(buffer.slice(1), type); + let [decoded, _decodedLength] = this.binaryCodec.decodeNested(buffer.slice(1), type); return new OptionValue(type, decoded); } diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 09ba8858d..b70aaf480 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -1,12 +1,16 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; import { Compatibility } from "../compatibility"; +import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; import { ErrContractHasNoAddress } from "../errors"; import { IAddress, INonce } from "../interface"; +import { TokenComputer } from "../tokens"; import { Transaction } from "../transaction"; +import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { guardValueIsSet } from "../utils"; -import { bigIntToBuffer } from "./codec/utils"; import { CodeMetadata } from "./codeMetadata"; +import { bigIntToBuffer } from "./codec/utils"; import { ContractFunction } from "./function"; import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; @@ -14,10 +18,6 @@ import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; import { WasmVirtualMachine } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; -import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; -import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; -import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; -import { TokenComputer } from "../tokens"; const createKeccakHash = require("keccak"); interface IAbi { @@ -62,6 +62,7 @@ export class SmartContract implements ISmartContract { } private setupMethods() { + // eslint-disable-next-line @typescript-eslint/no-this-alias let contract = this; let abi = this.getAbi(); diff --git a/src/smartcontracts/typesystem/numerical.ts b/src/smartcontracts/typesystem/numerical.ts index e7222e167..0530468fd 100644 --- a/src/smartcontracts/typesystem/numerical.ts +++ b/src/smartcontracts/typesystem/numerical.ts @@ -1,6 +1,6 @@ -import * as errors from "../../errors"; -import { PrimitiveType, PrimitiveValue, Type } from "./types"; import BigNumber from "bignumber.js"; +import * as errors from "../../errors"; +import { PrimitiveType, PrimitiveValue } from "./types"; export class NumericalType extends PrimitiveType { static ClassName = "NumericalType"; diff --git a/src/smartcontracts/typesystem/struct.ts b/src/smartcontracts/typesystem/struct.ts index e0adaac06..5483aa8d7 100644 --- a/src/smartcontracts/typesystem/struct.ts +++ b/src/smartcontracts/typesystem/struct.ts @@ -1,5 +1,5 @@ -import { ErrMissingFieldOnStruct, ErrTypingSystem } from "../../errors"; -import { FieldDefinition, Field, Fields } from "./fields"; +import { ErrMissingFieldOnStruct } from "../../errors"; +import { Field, FieldDefinition, Fields } from "./fields"; import { CustomType, TypedValue } from "./types"; export class StructType extends CustomType { @@ -81,7 +81,7 @@ export class Struct extends TypedValue { return result; } - + equals(other: Struct): boolean { if (!this.getType().equals(other.getType())) { return false; diff --git a/src/smartcontracts/typesystem/typeExpressionParser.ts b/src/smartcontracts/typesystem/typeExpressionParser.ts index 97be25865..564bf8bef 100644 --- a/src/smartcontracts/typesystem/typeExpressionParser.ts +++ b/src/smartcontracts/typesystem/typeExpressionParser.ts @@ -1,6 +1,6 @@ import * as errors from "../../errors"; import { Type } from "./types"; -var jsonHandler = require("json-duplicate-key-handle"); +const jsonHandler = require("json-duplicate-key-handle"); export class TypeExpressionParser { parse(expression: string): Type { @@ -41,7 +41,7 @@ export class TypeExpressionParser { private getJsonedString(expression: string) { let jsoned = ""; - for (var i = 0; i < expression.length; i++) { + for (let i = 0; i < expression.length; i++) { let char = expression.charAt(i); let previousChar = expression.charAt(i - 1); let nextChar = expression.charAt(i + 1); diff --git a/src/tokens.ts b/src/tokens.ts index ddc0981ab..b0020339c 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -22,7 +22,7 @@ export class NextTokenTransfer { } export class TokenComputer { - constructor() {} + constructor() { } isFungible(token: Token): boolean { return token.nonce === 0; diff --git a/src/transaction.ts b/src/transaction.ts index ec0e41395..019cab3b0 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -2,6 +2,7 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { Compatibility } from "./compatibility"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; +import { DraftTransaction } from "./draftTransaction"; import * as errors from "./errors"; import { Hash } from "./hash"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; @@ -11,7 +12,6 @@ import { ProtoSerializer } from "./proto"; import { Signature, interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; import { guardNotEmpty } from "./utils"; -import { DraftTransaction } from "./draftTransaction"; const createTransactionHasher = require("blake2b"); const TRANSACTION_HASH_LENGTH = 32; @@ -440,7 +440,7 @@ export class Transaction { * Creates a new Transaction object from a TransactionNext object. */ static fromTransactionNext(transaction: ITransactionNext): Transaction { - const tx = new Transaction({ + const tx = new Transaction({ sender: Address.fromBech32(transaction.sender), receiver: Address.fromBech32(transaction.receiver), gasLimit: new BigNumber(transaction.gasLimit).toNumber(), @@ -462,7 +462,7 @@ export class Transaction { if (transaction.signature.length) { tx.applySignature(transaction.signature); } - + if (transaction.guardianSignature.length) { tx.applyGuardianSignature(transaction.guardianSignature); } @@ -496,7 +496,7 @@ export class TransactionHash extends Hash { * An abstraction for creating, signing and broadcasting transactions. * Will replace the {@link Transaction} class in the future. */ -export class TransactionNext{ +export class TransactionNext { /** * The nonce of the transaction (the account sequence number of the sender). */ @@ -627,9 +627,9 @@ export class TransactionNext{ * An utilitary class meant to work together with the {@link TransactionNext} class. */ export class TransactionComputer { - constructor() {} + constructor() { } - computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber{ + computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber { const moveBalanceGas = new BigNumber( networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte); if (moveBalanceGas > transaction.gasLimit) { @@ -651,7 +651,7 @@ export class TransactionComputer { return feeForMove.plus(processingFee); } - computeBytesForSigning(transaction: ITransactionNext): Uint8Array{ + computeBytesForSigning(transaction: ITransactionNext): Uint8Array { const plainTransaction = this.toPlainObject(transaction); if (plainTransaction.signature) { @@ -671,7 +671,7 @@ export class TransactionComputer { return new Uint8Array(Buffer.from(serialized)); } - computeTransactionHash(transaction: ITransactionNext): Uint8Array{ + computeTransactionHash(transaction: ITransactionNext): Uint8Array { let serializer = new ProtoSerializer(); const tx = Transaction.fromTransactionNext(transaction); @@ -679,7 +679,7 @@ export class TransactionComputer { const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) .update(buffer) .digest("hex"); - + return Buffer.from(hash, "hex"); } diff --git a/src/transactionPayload.ts b/src/transactionPayload.ts index f8ef13a71..8cd07ae29 100644 --- a/src/transactionPayload.ts +++ b/src/transactionPayload.ts @@ -1,5 +1,3 @@ -import { ContractCallPayloadBuilder, ContractDeployPayloadBuilder, ContractUpgradePayloadBuilder } from "./smartcontracts/transactionPayloadBuilders"; - /** * The "data" field of a Transaction, as an immutable object. */ diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 4ef3502ed..bdd6ffcb1 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -1,9 +1,9 @@ +import BigNumber from "bignumber.js"; import { assert } from "chai"; +import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { loadTestWallets, TestWallet } from "../testutils"; import { TokenManagementTransactionsFactory } from "./tokenManagementTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import BigNumber from "bignumber.js"; -import { ESDT_CONTRACT_ADDRESS } from "../constants"; describe("test token management transactions factory", () => { let frank: TestWallet, grace: TestWallet; @@ -137,7 +137,7 @@ describe("test token management transactions factory", () => { sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, - name: `test`, + name: "test", royalties: 1000, hash: "abba", attributes: Buffer.from("test"), diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 13c957512..d4580b721 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,11 +1,11 @@ import BigNumber from "bignumber.js"; +import { Address } from "../address"; +import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { DraftTransaction } from "../draftTransaction"; -import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { IAddress } from "../interface"; -import { utf8ToHex, boolToHex, bigIntToHex, addressToHex, byteArrayToHex } from "../utils.codec"; -import { ESDT_CONTRACT_ADDRESS } from "../constants"; -import { Address } from "../address"; import { Logger } from "../logger"; +import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; +import { DraftTransactionBuilder } from "./draftTransactionBuilder"; interface Config { chainID: string; diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 000000000..a85044d61 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "target": "ES2015", + "lib": [ + "ES2015", + "DOM" + ], + "allowJs": true, + "strict": true, + "strictPropertyInitialization": true, + "strictNullChecks": true, + "skipLibCheck": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUnusedParameters": true, + "esModuleInterop": true, + "declaration": true, + "noEmit": true, + } +} diff --git a/tsconfig.tests.json b/tsconfig.tests.json index 150c202de..29ec228e4 100644 --- a/tsconfig.tests.json +++ b/tsconfig.tests.json @@ -23,12 +23,10 @@ "src/**/*", ], "exclude": [ - "node_modules", + "node_modules", "out", "out-tests", "out-browser", - "out-browser-tests", - "src/examples", - "src/_docs" + "out-browser-tests" ] } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 9e0c39729..000000000 --- a/tslint.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "rules": { - "no-string-throw": true, - "no-unused-expression": true, - "no-duplicate-variable": true, - "no-floating-promises": true, - "curly": true, - "class-name": true, - "semicolon": [ - true, - "always" - ], - "triple-equals": false - }, - "defaultSeverity": "warning" -} From ebcd47a89d934d39701650b83c7a700f8031b934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 30 Jan 2024 20:43:41 +0200 Subject: [PATCH 073/275] Add prettier. --- .prettierrc | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index b59536091..e7cf084b5 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { "singleQuote": false, "trailingComma": "all", - "printWidth": 140 + "tabWidth": 4 } diff --git a/package.json b/package.json index 3be1cbab0..4bc332721 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "compile-proto": "npx pbjs -t static-module -w commonjs -o src/proto/compiled.js src/proto/transaction.proto && npx pbts -o src/proto/compiled.d.ts src/proto/compiled.js", "browser-tests": "make clean && make browser-tests && http-server --port=9876 -o browser-tests/index.html", "lint": "eslint .", + "pretty": "prettier --write ./src/**/*.{js,ts}", "pretest": "npm run compile", "prepare": "npm run compile" }, From 9e266796d2e014e8e71d1a3f219a29ef5e6fc672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 30 Jan 2024 20:44:58 +0200 Subject: [PATCH 074/275] Add lint on workflow. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 987f2a803..b3e02a3d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: npm ci + - run: npm run lint - run: npm run compile - run: npm run compile-browser - run: npm test From 04a34715bbe9120cba1e5a71d67563261689e99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 31 Jan 2024 10:46:10 +0200 Subject: [PATCH 075/275] Fix eslint config (remove extra tsconfig). --- .eslintrc.js | 4 +--- tsconfig.eslint.json | 21 --------------------- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 tsconfig.eslint.json diff --git a/.eslintrc.js b/.eslintrc.js index 0303fe9e0..b822dafbf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { parser: "@typescript-eslint/parser", parserOptions: { - project: "tsconfig.eslint.json", + project: ["tsconfig.json", "tsconfig.tests.json"], sourceType: "module", }, plugins: ["@typescript-eslint/eslint-plugin"], @@ -18,8 +18,6 @@ module.exports = { ".eslintrc.js", "node_modules", "out", - "node_modules", - "out", "out-tests", "out-browser", "out-browser-tests", diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json deleted file mode 100644 index a85044d61..000000000 --- a/tsconfig.eslint.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "module": "CommonJS", - "target": "ES2015", - "lib": [ - "ES2015", - "DOM" - ], - "allowJs": true, - "strict": true, - "strictPropertyInitialization": true, - "strictNullChecks": true, - "skipLibCheck": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUnusedParameters": true, - "esModuleInterop": true, - "declaration": true, - "noEmit": true, - } -} From 2d88457445304b6ba3d4bfc7d914b033a009b4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 2 Feb 2024 10:47:50 +0200 Subject: [PATCH 076/275] Run "pretty" (partially). --- .prettierrc | 3 +- src/account.ts | 2 +- src/address.spec.ts | 17 +++--- src/address.ts | 8 ++- src/asyncTimer.spec.ts | 3 +- src/compatibility.ts | 8 ++- src/gasEstimator.spec.ts | 2 +- src/gasEstimator.ts | 8 ++- src/hash.ts | 2 +- src/index.ts | 3 +- src/interfaceOfNetwork.ts | 5 +- src/logger.ts | 3 +- src/networkParams.spec.ts | 10 +++- src/networkParams.ts | 12 +++-- src/signature.ts | 3 +- src/smartcontracts/argSerializer.spec.ts | 23 +++++--- src/smartcontracts/argSerializer.ts | 11 ++-- src/smartcontracts/argumentErrorContext.ts | 16 ++++-- src/smartcontracts/code.spec.ts | 2 +- src/smartcontracts/code.ts | 12 ++--- src/smartcontracts/codeMetadata.spec.ts | 12 +++-- src/smartcontracts/codec/address.ts | 4 +- src/smartcontracts/codec/binary.ts | 16 +----- src/smartcontracts/codec/enum.ts | 10 ++-- src/smartcontracts/codec/fields.ts | 4 +- src/smartcontracts/codec/h256.ts | 4 +- src/smartcontracts/codec/numerical.ts | 14 +++-- src/smartcontracts/codec/primitive.ts | 8 +-- src/smartcontracts/function.ts | 2 +- .../typesystem/abiRegistry.spec.ts | 38 +++++++++++--- src/smartcontracts/typesystem/abiRegistry.ts | 46 +++++++++------- src/smartcontracts/typesystem/address.ts | 2 +- src/smartcontracts/typesystem/algebraic.ts | 2 +- src/smartcontracts/typesystem/boolean.ts | 2 +- .../typesystem/composite.spec.ts | 5 +- src/smartcontracts/typesystem/composite.ts | 4 +- .../typesystem/endpoint.spec.ts | 25 +++++---- src/smartcontracts/typesystem/endpoint.ts | 31 +++++++---- src/smartcontracts/typesystem/enum.spec.ts | 52 ++++++------------- src/smartcontracts/typesystem/enum.ts | 10 ++-- src/smartcontracts/typesystem/event.ts | 13 ++--- src/smartcontracts/typesystem/factory.ts | 4 +- src/smartcontracts/typesystem/fields.ts | 8 +-- src/smartcontracts/typesystem/generic.ts | 2 +- src/smartcontracts/typesystem/index.ts | 1 - src/smartcontracts/typesystem/matchers.ts | 8 +-- src/smartcontracts/typesystem/struct.spec.ts | 15 +++--- src/smartcontracts/typesystem/struct.ts | 8 +-- .../typesystem/tokenIdentifier.ts | 4 +- src/smartcontracts/typesystem/tuple.ts | 8 +-- .../typesystem/typeMapper.spec.ts | 12 +++-- src/smartcontracts/typesystem/typeMapper.ts | 10 ++-- src/smartcontracts/typesystem/types.spec.ts | 45 ++++++++++------ src/smartcontracts/typesystem/types.ts | 49 +++++++++-------- src/testutils/mockProvider.ts | 40 +++++++------- src/testutils/networkProviders.ts | 8 ++- src/testutils/utils.ts | 22 ++++---- src/testutils/wallets.ts | 23 +++++--- src/tokenTransfer.spec.ts | 10 +++- src/tokenTransfer.ts | 15 ++++-- src/tokenTransferBuilders.spec.ts | 21 ++++++-- src/tokens.ts | 6 +-- src/utils.ts | 6 +-- 63 files changed, 446 insertions(+), 336 deletions(-) diff --git a/.prettierrc b/.prettierrc index e7cf084b5..9e4d56ada 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,6 @@ { "singleQuote": false, "trailingComma": "all", - "tabWidth": 4 + "tabWidth": 4, + "printWidth": 120 } diff --git a/src/account.ts b/src/account.ts index 8d10b89f7..68ccf6092 100644 --- a/src/account.ts +++ b/src/account.ts @@ -30,7 +30,7 @@ export class Account { /** * Updates account properties (such as nonce, balance). */ - update(obj: { nonce: INonce, balance: IAccountBalance}) { + update(obj: { nonce: INonce; balance: IAccountBalance }) { this.nonce = obj.nonce; this.balance = obj.balance; } diff --git a/src/address.spec.ts b/src/address.spec.ts index ca731f8e6..248b858a1 100644 --- a/src/address.spec.ts +++ b/src/address.spec.ts @@ -2,7 +2,6 @@ import { assert } from "chai"; import { Address } from "./address"; import * as errors from "./errors"; - describe("test address", () => { let aliceBech32 = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; let bobBech32 = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; @@ -41,13 +40,19 @@ describe("test address", () => { assert.throw(() => new Address("foo"), errors.ErrAddressCannotCreate); assert.throw(() => new Address("a".repeat(7)), errors.ErrAddressCannotCreate); assert.throw(() => new Address(Buffer.from("aaaa", "hex")), errors.ErrAddressCannotCreate); - assert.throw(() => new Address("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2"), errors.ErrAddressCannotCreate); - assert.throw(() => new Address("xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz"), errors.ErrAddressCannotCreate); + assert.throw( + () => new Address("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2"), + errors.ErrAddressCannotCreate, + ); + assert.throw( + () => new Address("xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz"), + errors.ErrAddressCannotCreate, + ); }); it("should validate the address without throwing the error", () => { assert.isTrue(Address.isValid(aliceBech32)); - assert.isFalse(Address.isValid('xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz')); - assert.isFalse(Address.isValid('erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2')) - }) + assert.isFalse(Address.isValid("xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz")); + assert.isFalse(Address.isValid("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2")); + }); }); diff --git a/src/address.ts b/src/address.ts index 48bfdbaa8..546017459 100644 --- a/src/address.ts +++ b/src/address.ts @@ -128,14 +128,12 @@ export class Address { static isValid(value: string): boolean { const decoded = bech32.decodeUnsafe(value); const prefix = decoded?.prefix; - const pubkey = decoded - ? Buffer.from(bech32.fromWords(decoded.words)) - : undefined; + const pubkey = decoded ? Buffer.from(bech32.fromWords(decoded.words)) : undefined; if (prefix !== HRP || pubkey?.length !== PUBKEY_LENGTH) { return false; } - + return true; } @@ -205,7 +203,7 @@ export class Address { toJSON(): object { return { bech32: this.bech32(), - pubkey: this.hex() + pubkey: this.hex(), }; } diff --git a/src/asyncTimer.spec.ts b/src/asyncTimer.spec.ts index 8166ce800..903a4cc9b 100644 --- a/src/asyncTimer.spec.ts +++ b/src/asyncTimer.spec.ts @@ -2,7 +2,6 @@ import { assert } from "chai"; import * as errors from "./errors"; import { AsyncTimer } from "./asyncTimer"; - describe("test asyncTimer", () => { it("should start timer and resolve promise", async () => { let timer = new AsyncTimer("test"); @@ -21,7 +20,7 @@ describe("test asyncTimer", () => { let longPromise = longTimer.start(42000); let shortTimerThenAbortLongTimer = shortPromise.then(() => longTimer.abort()); - let longTimerThenCatchAbort = longPromise.catch(reason => error = reason); + let longTimerThenCatchAbort = longPromise.catch((reason) => (error = reason)); await Promise.all([shortTimerThenAbortLongTimer, longTimerThenCatchAbort]); diff --git a/src/compatibility.ts b/src/compatibility.ts index 274423603..3aec47640 100644 --- a/src/compatibility.ts +++ b/src/compatibility.ts @@ -16,9 +16,13 @@ export class Compatibility { } if (!address || address.bech32() == "") { - console.warn(`${context}: address should be set; ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`); + console.warn( + `${context}: address should be set; ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, + ); } else if (address.bech32() == Address.Zero().bech32()) { - console.warn(`${context}: address should not be the 'zero' address (also known as the 'contracts deployment address'); ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`); + console.warn( + `${context}: address should not be the 'zero' address (also known as the 'contracts deployment address'); ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, + ); } } } diff --git a/src/gasEstimator.spec.ts b/src/gasEstimator.spec.ts index 740ed4ef2..e1394717f 100644 --- a/src/gasEstimator.spec.ts +++ b/src/gasEstimator.spec.ts @@ -24,7 +24,7 @@ describe("test gas estimator", () => { gasPerDataByte: 3000, gasCostESDTTransfer: 200000, gasCostESDTNFTTransfer: 300000, - gasCostESDTNFTMultiTransfer: 400000 + gasCostESDTNFTMultiTransfer: 400000, }); assert.equal(estimator.forEGLDTransfer(0), 10000); diff --git a/src/gasEstimator.ts b/src/gasEstimator.ts index 6207c1bfa..368be5e53 100644 --- a/src/gasEstimator.ts +++ b/src/gasEstimator.ts @@ -17,13 +17,13 @@ export const DefaultGasConfiguration: IGasConfiguration = { gasPerDataByte: 1500, gasCostESDTTransfer: 200000, gasCostESDTNFTTransfer: 200000, - gasCostESDTNFTMultiTransfer: 200000 + gasCostESDTNFTMultiTransfer: 200000, }; // Additional gas to account for eventual increases in gas requirements (thus avoid fast-breaking changes in clients of the library). const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; -// Additional gas to account for extra blockchain operations (e.g. data movement (between accounts) for NFTs), +// Additional gas to account for extra blockchain operations (e.g. data movement (between accounts) for NFTs), // and for eventual increases in gas requirements (thus avoid fast-breaking changes in clients of the library). const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -35,9 +35,7 @@ export class GasEstimator { } forEGLDTransfer(dataLength: number) { - const gasLimit = - this.gasConfiguration.minGasLimit + - this.gasConfiguration.gasPerDataByte * dataLength; + const gasLimit = this.gasConfiguration.minGasLimit + this.gasConfiguration.gasPerDataByte * dataLength; return gasLimit; } diff --git a/src/hash.ts b/src/hash.ts index 5f7095a76..40efda328 100644 --- a/src/hash.ts +++ b/src/hash.ts @@ -8,7 +8,7 @@ export class Hash { /** * Creates a new Hash object. - * + * * @param hash The hash, as a Buffer or a hex-encoded string. */ constructor(hash: Buffer | string) { diff --git a/src/index.ts b/src/index.ts index 545ba1904..9063e99ad 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -require('./globals'); +require("./globals"); export * from "./account"; export * from "./address"; @@ -21,4 +21,3 @@ export * from "./transactionPayload"; export * from "./transactionWatcher"; export * from "./transferTransactionsFactory"; export * from "./utils"; - diff --git a/src/interfaceOfNetwork.ts b/src/interfaceOfNetwork.ts index 942a9b5ff..84b284fca 100644 --- a/src/interfaceOfNetwork.ts +++ b/src/interfaceOfNetwork.ts @@ -65,7 +65,10 @@ export interface IContractReturnCode { export interface ITransactionLogs { events: ITransactionEvent[]; - findSingleOrNoneEvent(identifier: string, predicate?: (event: ITransactionEvent) => boolean): ITransactionEvent | undefined; + findSingleOrNoneEvent( + identifier: string, + predicate?: (event: ITransactionEvent) => boolean, + ): ITransactionEvent | undefined; } export interface ITransactionEvent { diff --git a/src/logger.ts b/src/logger.ts index 50ff4d254..65910ea6c 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -4,7 +4,7 @@ export enum LogLevel { Info = 2, Warn = 3, Error = 4, - None = 5 + None = 5, } export class Logger { @@ -54,4 +54,3 @@ export class Logger { console.error(message, optionalParams); } } - diff --git a/src/networkParams.spec.ts b/src/networkParams.spec.ts index c217414e3..7f127437b 100644 --- a/src/networkParams.spec.ts +++ b/src/networkParams.spec.ts @@ -1,6 +1,9 @@ import { assert } from "chai"; import { - TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT + TRANSACTION_OPTIONS_DEFAULT, + TRANSACTION_OPTIONS_TX_GUARDED, + TRANSACTION_OPTIONS_TX_HASH_SIGN, + TRANSACTION_VERSION_DEFAULT, } from "./constants"; import { TransactionOptions, TransactionVersion } from "./networkParams"; @@ -61,7 +64,10 @@ describe("test transaction options", () => { assert.isTrue(optionsWithGuardian.isWithGuardian()); const optionsWithHashSignAndGuardian = TransactionOptions.withOptions({ hashSign: true, guarded: true }); - assert.equal(optionsWithHashSignAndGuardian.valueOf(), TRANSACTION_OPTIONS_TX_HASH_SIGN | TRANSACTION_OPTIONS_TX_GUARDED); + assert.equal( + optionsWithHashSignAndGuardian.valueOf(), + TRANSACTION_OPTIONS_TX_HASH_SIGN | TRANSACTION_OPTIONS_TX_GUARDED, + ); assert.isTrue(optionsWithHashSignAndGuardian.isWithHashSign()); assert.isTrue(optionsWithHashSignAndGuardian.isWithGuardian()); }); diff --git a/src/networkParams.ts b/src/networkParams.ts index 24b8b7017..36f8a23c7 100644 --- a/src/networkParams.ts +++ b/src/networkParams.ts @@ -1,4 +1,9 @@ -import { TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, TRANSACTION_VERSION_DEFAULT } from "./constants"; +import { + TRANSACTION_OPTIONS_DEFAULT, + TRANSACTION_OPTIONS_TX_GUARDED, + TRANSACTION_OPTIONS_TX_HASH_SIGN, + TRANSACTION_VERSION_DEFAULT, +} from "./constants"; import * as errors from "./errors"; export class TransactionVersion { @@ -68,10 +73,7 @@ export class TransactionOptions { /** * Creates a TransactionOptions object from a set of options. */ - public static withOptions(options: { - hashSign?: boolean, - guarded?: boolean - }): TransactionOptions { + public static withOptions(options: { hashSign?: boolean; guarded?: boolean }): TransactionOptions { let value = 0; if (options.hashSign) { diff --git a/src/signature.ts b/src/signature.ts index e307a2255..95fe99778 100644 --- a/src/signature.ts +++ b/src/signature.ts @@ -1,6 +1,5 @@ import * as errors from "./errors"; - const SIGNATURE_LENGTH = 64; /** @@ -59,7 +58,7 @@ export class Signature { } } -export function interpretSignatureAsBuffer(signature: { hex(): string; } | Uint8Array): Buffer { +export function interpretSignatureAsBuffer(signature: { hex(): string } | Uint8Array): Buffer { if (ArrayBuffer.isView(signature)) { return Buffer.from(signature); } else if ((signature).hex != null) { diff --git a/src/smartcontracts/argSerializer.spec.ts b/src/smartcontracts/argSerializer.spec.ts index 06bcac914..840650820 100644 --- a/src/smartcontracts/argSerializer.spec.ts +++ b/src/smartcontracts/argSerializer.spec.ts @@ -29,7 +29,7 @@ describe("test serializer", () => { serializeThenDeserialize( ["u32", "i64", "bytes"], [new U32Value(100), new I64Value(new BigNumber("-1")), new BytesValue(Buffer.from("abba", "hex"))], - "64@ff@abba" + "64@ff@abba", ); serializeThenDeserialize( @@ -39,7 +39,7 @@ describe("test serializer", () => { OptionValue.newMissing(), CompositeValue.fromItems(new U8Value(3), new BytesValue(Buffer.from("abba", "hex"))), ], - "0100000064@@03@abba" + "0100000064@@03@abba", ); serializeThenDeserialize( @@ -49,19 +49,26 @@ describe("test serializer", () => { VariadicValue.fromItems( new BytesValue(Buffer.from("abba", "hex")), new BytesValue(Buffer.from("abba", "hex")), - new BytesValue(Buffer.from("abba", "hex")) + new BytesValue(Buffer.from("abba", "hex")), ), ], - "00080009@abba@abba@abba" + "00080009@abba@abba@abba", ); serializeThenDeserialize( ["MultiArg, List>", "VarArgs"], [ - CompositeValue.fromItems(OptionValue.newProvided(new U8Value(7)), List.fromItems([new U16Value(8), new U16Value(9)])), - VariadicValue.fromItems(new BytesValue(Buffer.from("abba", "hex")), new BytesValue(Buffer.from("abba", "hex")), new BytesValue(Buffer.from("abba", "hex"))) + CompositeValue.fromItems( + OptionValue.newProvided(new U8Value(7)), + List.fromItems([new U16Value(8), new U16Value(9)]), + ), + VariadicValue.fromItems( + new BytesValue(Buffer.from("abba", "hex")), + new BytesValue(Buffer.from("abba", "hex")), + new BytesValue(Buffer.from("abba", "hex")), + ), ], - "0107@00080009@abba@abba@abba" + "0107@00080009@abba@abba@abba", ); }); @@ -69,7 +76,7 @@ describe("test serializer", () => { serializeThenDeserialize( ["tuple2"], [Tuple.fromItems([new I32Value(100), new I16Value(10)])], - "00000064000a" + "00000064000a", ); }); diff --git a/src/smartcontracts/argSerializer.ts b/src/smartcontracts/argSerializer.ts index fbf3c492e..f065ba7ae 100644 --- a/src/smartcontracts/argSerializer.ts +++ b/src/smartcontracts/argSerializer.ts @@ -5,7 +5,6 @@ import { OptionalType, OptionalValue } from "./typesystem/algebraic"; import { CompositeType, CompositeValue } from "./typesystem/composite"; import { VariadicType, VariadicValue } from "./typesystem/variadic"; - interface IArgSerializerOptions { codec: ICodec; } @@ -22,7 +21,7 @@ interface IParameterDefinition { // TODO: perhaps move default construction options to a factory (ArgSerializerFactory), instead of referencing them in the constructor // (postpone as much as possible, breaking change) const defaultArgSerializerOptions: IArgSerializerOptions = { - codec: new BinaryCodec() + codec: new BinaryCodec(), }; export class ArgSerializer { @@ -47,7 +46,7 @@ export class ArgSerializer { */ stringToBuffers(joinedString: string): Buffer[] { // We also keep the zero-length buffers (they could encode missing options, Option). - return joinedString.split(ARGUMENTS_SEPARATOR).map(item => Buffer.from(item, "hex")); + return joinedString.split(ARGUMENTS_SEPARATOR).map((item) => Buffer.from(item, "hex")); } /** @@ -137,7 +136,7 @@ export class ArgSerializer { /** * Serializes a set of typed values into an arguments string (e.g. aa@bb@@cc). */ - valuesToString(values: TypedValue[]): { argumentsString: string, count: number } { + valuesToString(values: TypedValue[]): { argumentsString: string; count: number } { let strings = this.valuesToStrings(values); let argumentsString = strings.join(ARGUMENTS_SEPARATOR); let count = strings.length; @@ -149,7 +148,7 @@ export class ArgSerializer { */ valuesToStrings(values: TypedValue[]): string[] { let buffers = this.valuesToBuffers(values); - let strings = buffers.map(buffer => buffer.toString("hex")); + let strings = buffers.map((buffer) => buffer.toString("hex")); return strings; } @@ -192,7 +191,7 @@ export class ArgSerializer { handleValue(item); } - return + return; } // Non-composite (singular), non-variadic (fixed) type. diff --git a/src/smartcontracts/argumentErrorContext.ts b/src/smartcontracts/argumentErrorContext.ts index 76543ddf8..661f62b22 100644 --- a/src/smartcontracts/argumentErrorContext.ts +++ b/src/smartcontracts/argumentErrorContext.ts @@ -13,11 +13,15 @@ export class ArgumentErrorContext { } throwError(specificError: string): never { - throw new ErrInvalidArgument(`Error when converting arguments for endpoint (endpoint name: ${this.endpointName}, argument index: ${this.argumentIndex}, name: ${this.parameterDefinition.name}, type: ${this.parameterDefinition.type})\nNested error: ${specificError}`); + throw new ErrInvalidArgument( + `Error when converting arguments for endpoint (endpoint name: ${this.endpointName}, argument index: ${this.argumentIndex}, name: ${this.parameterDefinition.name}, type: ${this.parameterDefinition.type})\nNested error: ${specificError}`, + ); } convertError(native: any, typeName: string): never { - this.throwError(`Can't convert argument (argument: ${native}, type ${typeof native}), wanted type: ${typeName})`); + this.throwError( + `Can't convert argument (argument: ${native}, type ${typeof native}), wanted type: ${typeName})`, + ); } unhandledType(functionName: string, type: Type): never { @@ -27,14 +31,18 @@ export class ArgumentErrorContext { guardSameLength(native: any[], valueTypes: T[]) { native = native || []; if (native.length != valueTypes.length) { - this.throwError(`Incorrect composite type length: have ${native.length}, expected ${valueTypes.length} (argument: ${native})`); + this.throwError( + `Incorrect composite type length: have ${native.length}, expected ${valueTypes.length} (argument: ${native})`, + ); } } guardHasField(native: any, fieldName: string) { native = native || {}; if (!(fieldName in native)) { - this.throwError(`Struct argument does not contain a field named "${fieldName}" (argument: ${JSON.stringify(native)})`); + this.throwError( + `Struct argument does not contain a field named "${fieldName}" (argument: ${JSON.stringify(native)})`, + ); } } } diff --git a/src/smartcontracts/code.spec.ts b/src/smartcontracts/code.spec.ts index 2dd2425df..1933cfefe 100644 --- a/src/smartcontracts/code.spec.ts +++ b/src/smartcontracts/code.spec.ts @@ -32,6 +32,6 @@ describe("Code Class Tests", function () { const hash = code.computeHash(); assert.instanceOf(hash, Buffer); - assert.equal(hash.toString('hex'), 'ac86b78afd9bdda3641a47a4aff2a7ee26acd40cc534d63655e9dfbf3f890a02') + assert.equal(hash.toString("hex"), "ac86b78afd9bdda3641a47a4aff2a7ee26acd40cc534d63655e9dfbf3f890a02"); }); }); diff --git a/src/smartcontracts/code.ts b/src/smartcontracts/code.ts index 6b7700414..e7a8b68d2 100644 --- a/src/smartcontracts/code.ts +++ b/src/smartcontracts/code.ts @@ -1,5 +1,5 @@ -const createHasher = require('blake2b') -const CODE_HASH_LENGTH = 32 +const createHasher = require("blake2b"); +const CODE_HASH_LENGTH = 32; /** * Bytecode of a Smart Contract, as an abstraction. @@ -22,7 +22,7 @@ export class Code { * Creates a Code object from a hex-encoded string. */ static fromHex(hex: string): Code { - return new Code(hex) + return new Code(hex); } /** @@ -37,10 +37,8 @@ export class Code { } computeHash(): Buffer { - const hash = createHasher(CODE_HASH_LENGTH) - .update(this.valueOf()) - .digest(); + const hash = createHasher(CODE_HASH_LENGTH).update(this.valueOf()).digest(); - return Buffer.from(hash) + return Buffer.from(hash); } } diff --git a/src/smartcontracts/codeMetadata.spec.ts b/src/smartcontracts/codeMetadata.spec.ts index 685d8cf5f..7b0eab88c 100644 --- a/src/smartcontracts/codeMetadata.spec.ts +++ b/src/smartcontracts/codeMetadata.spec.ts @@ -58,9 +58,13 @@ describe("CodeMetadata Class Tests", function () { it("should handle buffer too short error", function () { const buffer = Buffer.from([CodeMetadata.ByteZero.Upgradeable]); - assert.throws(() => { - CodeMetadata.fromBuffer(buffer); - }, Error, "Buffer is too short."); + assert.throws( + () => { + CodeMetadata.fromBuffer(buffer); + }, + Error, + "Buffer is too short.", + ); }); it("should test code metadata from bytes", () => { @@ -72,7 +76,7 @@ describe("CodeMetadata Class Tests", function () { upgradeable: true, readable: false, payable: false, - payableBySc: false + payableBySc: false, }); }); }); diff --git a/src/smartcontracts/codec/address.ts b/src/smartcontracts/codec/address.ts index 35dd0a825..8e640d540 100644 --- a/src/smartcontracts/codec/address.ts +++ b/src/smartcontracts/codec/address.ts @@ -4,7 +4,7 @@ import { AddressValue } from "../typesystem"; export class AddressBinaryCodec { /** * Reads and decodes an AddressValue from a given buffer. - * + * * @param buffer the input buffer */ decodeNested(buffer: Buffer): [AddressValue, number] { @@ -17,7 +17,7 @@ export class AddressBinaryCodec { /** * Reads and decodes an AddressValue from a given buffer. - * + * * @param buffer the input buffer */ decodeTopLevel(buffer: Buffer): AddressValue { diff --git a/src/smartcontracts/codec/binary.ts b/src/smartcontracts/codec/binary.ts index 519ad2a5e..1b9709315 100644 --- a/src/smartcontracts/codec/binary.ts +++ b/src/smartcontracts/codec/binary.ts @@ -80,13 +80,7 @@ export class BinaryCodec { } encodeNested(typedValue: TypedValue): Buffer { - guardTrue( - typedValue - .getType() - .getCardinality() - .isSingular(), - "singular cardinality, thus encodable type" - ); + guardTrue(typedValue.getType().getCardinality().isSingular(), "singular cardinality, thus encodable type"); return onTypedValueSelect(typedValue, { onPrimitive: () => this.primitiveCodec.encodeNested(typedValue), @@ -100,13 +94,7 @@ export class BinaryCodec { } encodeTopLevel(typedValue: TypedValue): Buffer { - guardTrue( - typedValue - .getType() - .getCardinality() - .isSingular(), - "singular cardinality, thus encodable type" - ); + guardTrue(typedValue.getType().getCardinality().isSingular(), "singular cardinality, thus encodable type"); return onTypedValueSelect(typedValue, { onPrimitive: () => this.primitiveCodec.encodeTopLevel(typedValue), diff --git a/src/smartcontracts/codec/enum.ts b/src/smartcontracts/codec/enum.ts index 4d9be4c89..d73e79bd2 100644 --- a/src/smartcontracts/codec/enum.ts +++ b/src/smartcontracts/codec/enum.ts @@ -23,7 +23,7 @@ export class EnumBinaryCodec { let variant = type.getVariantByDiscriminant(discriminant); let fieldDefinitions = variant.getFieldsDefinitions(); - + let [fields, lengthOfFields]: [Field[], number] = this.fieldsCodec.decodeNested(buffer, fieldDefinitions); let enumValue = new EnumValue(type, variant, fields); @@ -33,7 +33,7 @@ export class EnumBinaryCodec { private readDiscriminant(buffer: Buffer): [discriminant: number, length: number] { let [value, length] = this.binaryCodec.decodeNested(buffer, new U8Type()); let discriminant = value.valueOf(); - + return [discriminant, length]; } @@ -51,9 +51,11 @@ export class EnumBinaryCodec { let fields = enumValue.getFields(); let hasFields = fields.length > 0; let fieldsBuffer = this.fieldsCodec.encodeNested(fields); - + let discriminant = new U8Value(enumValue.discriminant); - let discriminantBuffer = hasFields ? this.binaryCodec.encodeNested(discriminant) : this.binaryCodec.encodeTopLevel(discriminant); + let discriminantBuffer = hasFields + ? this.binaryCodec.encodeNested(discriminant) + : this.binaryCodec.encodeTopLevel(discriminant); return Buffer.concat([discriminantBuffer, fieldsBuffer]); } diff --git a/src/smartcontracts/codec/fields.ts b/src/smartcontracts/codec/fields.ts index d5b6dee28..31a88ab58 100644 --- a/src/smartcontracts/codec/fields.ts +++ b/src/smartcontracts/codec/fields.ts @@ -20,13 +20,13 @@ export class FieldsBinaryCodec { let field = new Field(decoded, fieldDefinition.name); fields.push(field); } - + return [fields, totalLength]; } encodeNested(fields: ReadonlyArray): Buffer { let buffers: Buffer[] = []; - + for (const field of fields) { let fieldBuffer = this.binaryCodec.encodeNested(field.value); buffers.push(fieldBuffer); diff --git a/src/smartcontracts/codec/h256.ts b/src/smartcontracts/codec/h256.ts index 76418b650..27a043c43 100644 --- a/src/smartcontracts/codec/h256.ts +++ b/src/smartcontracts/codec/h256.ts @@ -3,7 +3,7 @@ import { H256Value } from "../typesystem/h256"; export class H256BinaryCodec { /** * Reads and decodes a H256Value from a given buffer. - * + * * @param buffer the input buffer */ decodeNested(buffer: Buffer): [H256Value, number] { @@ -14,7 +14,7 @@ export class H256BinaryCodec { /** * Reads and decodes a H256Value from a given buffer. - * + * * @param buffer the input buffer */ decodeTopLevel(buffer: Buffer): H256Value { diff --git a/src/smartcontracts/codec/numerical.ts b/src/smartcontracts/codec/numerical.ts index 38016615b..9dd27f6e6 100644 --- a/src/smartcontracts/codec/numerical.ts +++ b/src/smartcontracts/codec/numerical.ts @@ -1,7 +1,15 @@ import BigNumber from "bignumber.js"; import { NumericalType, NumericalValue } from "../typesystem"; import { SizeOfU32 } from "./constants"; -import { bigIntToBuffer, bufferToBigInt, cloneBuffer, flipBufferBitsInPlace, isMsbOne, isMsbZero, prependByteToBuffer } from "./utils"; +import { + bigIntToBuffer, + bufferToBigInt, + cloneBuffer, + flipBufferBitsInPlace, + isMsbOne, + isMsbZero, + prependByteToBuffer, +} from "./utils"; /** * Encodes and decodes "NumericalValue" objects. @@ -91,7 +99,7 @@ export class NumericalBinaryCodec { // Fix ambiguity if any if (isMsbZero(buffer)) { - buffer = prependByteToBuffer(buffer, 0xFF); + buffer = prependByteToBuffer(buffer, 0xff); } const paddingBytes = Buffer.alloc(size - buffer.length, 0xff); @@ -135,7 +143,7 @@ export class NumericalBinaryCodec { // Fix ambiguity if any if (isMsbZero(buffer)) { - buffer = prependByteToBuffer(buffer, 0xFF); + buffer = prependByteToBuffer(buffer, 0xff); } return buffer; diff --git a/src/smartcontracts/codec/primitive.ts b/src/smartcontracts/codec/primitive.ts index 833b9e141..f761c0df2 100644 --- a/src/smartcontracts/codec/primitive.ts +++ b/src/smartcontracts/codec/primitive.ts @@ -56,7 +56,7 @@ export class PrimitiveBinaryCodec { onString: () => this.stringCodec.decodeNested(buffer), onH256: () => this.h256Codec.decodeNested(buffer), onTokenIndetifier: () => this.tokenIdentifierCodec.decodeNested(buffer), - onNothing: () => this.nothingCodec.decodeNested() + onNothing: () => this.nothingCodec.decodeNested(), }); } @@ -69,7 +69,7 @@ export class PrimitiveBinaryCodec { onString: () => this.stringCodec.decodeTopLevel(buffer), onH256: () => this.h256Codec.decodeTopLevel(buffer), onTokenIndetifier: () => this.tokenIdentifierCodec.decodeTopLevel(buffer), - onNothing: () => this.nothingCodec.decodeTopLevel() + onNothing: () => this.nothingCodec.decodeTopLevel(), }); } @@ -82,7 +82,7 @@ export class PrimitiveBinaryCodec { onString: () => this.stringCodec.encodeNested(value), onH256: () => this.h256Codec.encodeNested(value), onTypeIdentifier: () => this.tokenIdentifierCodec.encodeNested(value), - onNothing: () => this.nothingCodec.encodeNested() + onNothing: () => this.nothingCodec.encodeNested(), }); } @@ -95,7 +95,7 @@ export class PrimitiveBinaryCodec { onString: () => this.stringCodec.encodeTopLevel(value), onH256: () => this.h256Codec.encodeTopLevel(value), onTypeIdentifier: () => this.tokenIdentifierCodec.encodeTopLevel(value), - onNothing: () => this.nothingCodec.encodeTopLevel() + onNothing: () => this.nothingCodec.encodeTopLevel(), }); } } diff --git a/src/smartcontracts/function.ts b/src/smartcontracts/function.ts index 83d55e3f0..b8547e46a 100644 --- a/src/smartcontracts/function.ts +++ b/src/smartcontracts/function.ts @@ -11,7 +11,7 @@ export class ContractFunction { /** * Creates a ContractFunction object, given its name. - * + * * @param name the name of the function */ constructor(name: string) { diff --git a/src/smartcontracts/typesystem/abiRegistry.spec.ts b/src/smartcontracts/typesystem/abiRegistry.spec.ts index 3d151e1d0..e9930b4ec 100644 --- a/src/smartcontracts/typesystem/abiRegistry.spec.ts +++ b/src/smartcontracts/typesystem/abiRegistry.spec.ts @@ -64,7 +64,7 @@ describe("test abi registry", () => { let bc = new BinaryCodec(); let buff = Buffer.from( "0588c738a5d26c0e3a2b4f9e8110b540ee9c0b71a3be057569a5a7b0fcb482c8f70000000806f05b59d3b200000000000b68656c6c6f20776f726c6400000000", - "hex" + "hex", ); let registry = await loadAbiRegistry("src/testdata/multisig.abi.json"); @@ -74,7 +74,7 @@ describe("test abi registry", () => { let result = bc.decodeTopLevel(buff, performAction.output[0].type); assert.deepEqual( JSON.stringify(result.valueOf()), - `{"name":"SendTransferExecute","fields":[{"to":{"bech32":"erd13rrn3fwjds8r5260n6q3pd2qa6wqkudrhczh26d957c0edyzermshds0k8","pubkey":"88c738a5d26c0e3a2b4f9e8110b540ee9c0b71a3be057569a5a7b0fcb482c8f7"},"egld_amount":"500000000000000000","endpoint_name":{"type":"Buffer","data":[104,101,108,108,111,32,119,111,114,108,100]},"arguments":[]}]}` + `{"name":"SendTransferExecute","fields":[{"to":{"bech32":"erd13rrn3fwjds8r5260n6q3pd2qa6wqkudrhczh26d957c0edyzermshds0k8","pubkey":"88c738a5d26c0e3a2b4f9e8110b540ee9c0b71a3be057569a5a7b0fcb482c8f7"},"egld_amount":"500000000000000000","endpoint_name":{"type":"Buffer","data":[104,101,108,108,111,32,119,111,114,108,100]},"arguments":[]}]}`, ); assert.equal(result.valueOf().name, "SendTransferExecute"); }); @@ -98,7 +98,12 @@ describe("test abi registry", () => { it("should load ABI when custom types are out of order (a)", async () => { const registry = await loadAbiRegistry("src/testdata/custom-types-out-of-order-a.abi.json"); - assert.deepEqual(registry.getStruct("EsdtTokenTransfer").getNamesOfDependencies(), ["EsdtTokenType", "TokenIdentifier", "u64", "BigUint"]); + assert.deepEqual(registry.getStruct("EsdtTokenTransfer").getNamesOfDependencies(), [ + "EsdtTokenType", + "TokenIdentifier", + "u64", + "BigUint", + ]); assert.deepEqual(registry.getEnum("EsdtTokenType").getNamesOfDependencies(), []); assert.deepEqual(registry.getStruct("TypeA").getNamesOfDependencies(), ["TypeB", "TypeC", "u64"]); assert.deepEqual(registry.getStruct("TypeB").getNamesOfDependencies(), ["TypeC", "u64"]); @@ -108,7 +113,12 @@ describe("test abi registry", () => { it("should load ABI when custom types are out of order (b)", async () => { const registry = await loadAbiRegistry("src/testdata/custom-types-out-of-order-b.abi.json"); - assert.deepEqual(registry.getStruct("EsdtTokenTransfer").getNamesOfDependencies(), ["EsdtTokenType", "TokenIdentifier", "u64", "BigUint"]); + assert.deepEqual(registry.getStruct("EsdtTokenTransfer").getNamesOfDependencies(), [ + "EsdtTokenType", + "TokenIdentifier", + "u64", + "BigUint", + ]); assert.deepEqual(registry.getEnum("EsdtTokenType").getNamesOfDependencies(), []); assert.deepEqual(registry.getStruct("TypeA").getNamesOfDependencies(), ["TypeB", "TypeC", "u64"]); assert.deepEqual(registry.getStruct("TypeB").getNamesOfDependencies(), ["TypeC", "u64"]); @@ -119,15 +129,29 @@ describe("test abi registry", () => { const registry = await loadAbiRegistry("src/testdata/custom-types-out-of-order-c.abi.json"); assert.lengthOf(registry.customTypes, 5); - assert.deepEqual(registry.getStruct("LoanCreateOptions").getNamesOfDependencies(), ["BigUint", "Address", "TokenIdentifier", "Status", "bytes"]); - + assert.deepEqual(registry.getStruct("LoanCreateOptions").getNamesOfDependencies(), [ + "BigUint", + "Address", + "TokenIdentifier", + "Status", + "bytes", + ]); }); it("should load ABI when custom types are out of order (community example: d)", async () => { const registry = await loadAbiRegistry("src/testdata/custom-types-out-of-order-d.abi.json"); assert.lengthOf(registry.customTypes, 12); - assert.deepEqual(registry.getStruct("AuctionItem").getNamesOfDependencies(), ["u64", "Address", "BigUint", "Option", "NftData", "bytes", "TokenIdentifier", "List"]); + assert.deepEqual(registry.getStruct("AuctionItem").getNamesOfDependencies(), [ + "u64", + "Address", + "BigUint", + "Option", + "NftData", + "bytes", + "TokenIdentifier", + "List", + ]); }); it("should load ABI with counted-variadic", async () => { diff --git a/src/smartcontracts/typesystem/abiRegistry.ts b/src/smartcontracts/typesystem/abiRegistry.ts index 27c300eee..601b65be8 100644 --- a/src/smartcontracts/typesystem/abiRegistry.ts +++ b/src/smartcontracts/typesystem/abiRegistry.ts @@ -20,8 +20,8 @@ export class AbiRegistry { name: string; constructorDefinition: EndpointDefinition; endpoints: EndpointDefinition[]; - customTypes: CustomType[], - events?: EventDefinition[] + customTypes: CustomType[]; + events?: EventDefinition[]; }) { this.name = options.name; this.constructorDefinition = options.constructorDefinition; @@ -32,10 +32,10 @@ export class AbiRegistry { static create(options: { name?: string; - constructor?: any, + constructor?: any; endpoints?: any[]; - types?: Record - events?: any[] + types?: Record; + events?: any[]; }): AbiRegistry { const name = options.name || interfaceNamePlaceholder; const constructor = options.constructor || {}; @@ -45,7 +45,7 @@ export class AbiRegistry { // Load arbitrary input parameters into properly-defined objects (e.g. EndpointDefinition and CustomType). const constructorDefinition = EndpointDefinition.fromJSON({ name: "constructor", ...constructor }); - const endpointDefinitions = endpoints.map(item => EndpointDefinition.fromJSON(item)); + const endpointDefinitions = endpoints.map((item) => EndpointDefinition.fromJSON(item)); const customTypes: CustomType[] = []; for (const customTypeName in types) { @@ -60,14 +60,14 @@ export class AbiRegistry { } } - const eventDefinitions = events.map(item => EventDefinition.fromJSON(item)); + const eventDefinitions = events.map((item) => EventDefinition.fromJSON(item)); const registry = new AbiRegistry({ name: name, constructorDefinition: constructorDefinition, endpoints: endpointDefinitions, customTypes: customTypes, - events: eventDefinitions + events: eventDefinitions, }); const remappedRegistry = registry.remapToKnownTypes(); @@ -158,26 +158,31 @@ export class AbiRegistry { constructorDefinition: newConstructor, endpoints: newEndpoints, customTypes: newCustomTypes, - events: newEvents + events: newEvents, }); return newRegistry; } - private mapCustomTypeDepthFirst(typeToMap: CustomType, allTypesToMap: CustomType[], mapper: TypeMapper, mappedTypes: CustomType[]) { - const hasBeenMapped = mappedTypes.findIndex(type => type.getName() == typeToMap.getName()) >= 0; + private mapCustomTypeDepthFirst( + typeToMap: CustomType, + allTypesToMap: CustomType[], + mapper: TypeMapper, + mappedTypes: CustomType[], + ) { + const hasBeenMapped = mappedTypes.findIndex((type) => type.getName() == typeToMap.getName()) >= 0; if (hasBeenMapped) { return; } for (const typeName of typeToMap.getNamesOfDependencies()) { - const dependencyType = allTypesToMap.find(type => type.getName() == typeName); + const dependencyType = allTypesToMap.find((type) => type.getName() == typeName); if (!dependencyType) { // It's a type that we don't have to map (e.g. could be a primitive type). continue; } - this.mapCustomTypeDepthFirst(dependencyType, allTypesToMap, mapper, mappedTypes) + this.mapCustomTypeDepthFirst(dependencyType, allTypesToMap, mapper, mappedTypes); } const mappedType = mapper.mapType(typeToMap); @@ -187,11 +192,11 @@ export class AbiRegistry { function mapEndpoint(endpoint: EndpointDefinition, mapper: TypeMapper): EndpointDefinition { const newInput = endpoint.input.map( - (e) => new EndpointParameterDefinition(e.name, e.description, mapper.mapType(e.type)) + (e) => new EndpointParameterDefinition(e.name, e.description, mapper.mapType(e.type)), ); const newOutput = endpoint.output.map( - (e) => new EndpointParameterDefinition(e.name, e.description, mapper.mapType(e.type)) + (e) => new EndpointParameterDefinition(e.name, e.description, mapper.mapType(e.type)), ); return new EndpointDefinition(endpoint.name, newInput, newOutput, endpoint.modifiers); @@ -199,11 +204,12 @@ function mapEndpoint(endpoint: EndpointDefinition, mapper: TypeMapper): Endpoint function mapEvent(event: EventDefinition, mapper: TypeMapper): EventDefinition { const newInputs = event.inputs.map( - (e) => new EventTopicDefinition({ - name: e.name, - type: mapper.mapType(e.type), - indexed: e.indexed - }) + (e) => + new EventTopicDefinition({ + name: e.name, + type: mapper.mapType(e.type), + indexed: e.indexed, + }), ); return new EventDefinition(event.identifier, newInputs); diff --git a/src/smartcontracts/typesystem/address.ts b/src/smartcontracts/typesystem/address.ts index 25a869840..53391e952 100644 --- a/src/smartcontracts/typesystem/address.ts +++ b/src/smartcontracts/typesystem/address.ts @@ -32,7 +32,7 @@ export class AddressValue extends PrimitiveValue { /** * Returns whether two objects have the same value. - * + * * @param other another AddressValue */ equals(other: AddressValue): boolean { diff --git a/src/smartcontracts/typesystem/algebraic.ts b/src/smartcontracts/typesystem/algebraic.ts index 5d41282c6..91225dee0 100644 --- a/src/smartcontracts/typesystem/algebraic.ts +++ b/src/smartcontracts/typesystem/algebraic.ts @@ -16,7 +16,7 @@ export class OptionalType extends Type { } isAssignableFrom(type: Type): boolean { - if (!(type.hasExactClass(OptionalType.ClassName))) { + if (!type.hasExactClass(OptionalType.ClassName)) { return false; } diff --git a/src/smartcontracts/typesystem/boolean.ts b/src/smartcontracts/typesystem/boolean.ts index 78b68dac1..9eef9423b 100644 --- a/src/smartcontracts/typesystem/boolean.ts +++ b/src/smartcontracts/typesystem/boolean.ts @@ -30,7 +30,7 @@ export class BooleanValue extends PrimitiveValue { /** * Returns whether two objects have the same value. - * + * * @param other another BooleanValue */ equals(other: BooleanValue): boolean { diff --git a/src/smartcontracts/typesystem/composite.spec.ts b/src/smartcontracts/typesystem/composite.spec.ts index f3b4ebf60..e8ee76269 100644 --- a/src/smartcontracts/typesystem/composite.spec.ts +++ b/src/smartcontracts/typesystem/composite.spec.ts @@ -5,7 +5,6 @@ import { CompositeType, CompositeValue } from "./composite"; import { EndpointParameterDefinition } from "./endpoint"; import { U32Type, U32Value } from "./numerical"; - describe("test composite", () => { const serializer = new ArgSerializer(); @@ -21,7 +20,7 @@ describe("test composite", () => { it("should get valueOf() upon decoding", () => { const compositeType = new CompositeType(new U32Type(), new BytesType()); - const endpointDefinition = new EndpointParameterDefinition("", "", compositeType) + const endpointDefinition = new EndpointParameterDefinition("", "", compositeType); const [compositeValue] = serializer.stringToValues("2a@abba", [endpointDefinition]); const values = compositeValue.valueOf(); @@ -43,7 +42,7 @@ describe("test composite", () => { it("should get valueOf() upon decoding, when items are missing", () => { const compositeType = new CompositeType(new U32Type(), new BytesType()); - const endpointDefinition = new EndpointParameterDefinition("", "", compositeType) + const endpointDefinition = new EndpointParameterDefinition("", "", compositeType); const [compositeValue] = serializer.stringToValues("", [endpointDefinition]); const values = compositeValue.valueOf(); diff --git a/src/smartcontracts/typesystem/composite.ts b/src/smartcontracts/typesystem/composite.ts index b34417953..6892a9a1f 100644 --- a/src/smartcontracts/typesystem/composite.ts +++ b/src/smartcontracts/typesystem/composite.ts @@ -32,7 +32,7 @@ export class CompositeValue extends TypedValue { } static fromItems(...items: TypedValue[]): CompositeValue { - let typeParameters = items.map(value => value.getType()); + let typeParameters = items.map((value) => value.getType()); let type = new CompositeType(...typeParameters); return new CompositeValue(type, items); } @@ -42,7 +42,7 @@ export class CompositeValue extends TypedValue { } valueOf(): any[] { - return this.items.map(item => item?.valueOf()); + return this.items.map((item) => item?.valueOf()); } equals(other: CompositeValue): boolean { diff --git a/src/smartcontracts/typesystem/endpoint.spec.ts b/src/smartcontracts/typesystem/endpoint.spec.ts index 41e7f1f8b..b26cdb26f 100644 --- a/src/smartcontracts/typesystem/endpoint.spec.ts +++ b/src/smartcontracts/typesystem/endpoint.spec.ts @@ -1,19 +1,18 @@ import { assert } from "chai"; import { EndpointDefinition } from "./endpoint"; - describe("test endpoint", () => { - it('should handle an only-owner modifier', async () => { - const actual = EndpointDefinition.fromJSON({ - name: 'foo', - onlyOwner: true, - mutability: 'payable', - payableInTokens: [], - inputs: [], - outputs: [], - }) + it("should handle an only-owner modifier", async () => { + const actual = EndpointDefinition.fromJSON({ + name: "foo", + onlyOwner: true, + mutability: "payable", + payableInTokens: [], + inputs: [], + outputs: [], + }); - assert.isTrue(actual.modifiers.onlyOwner) - assert.isTrue(actual.modifiers.isOnlyOwner()) - }) + assert.isTrue(actual.modifiers.onlyOwner); + assert.isTrue(actual.modifiers.isOnlyOwner()); + }); }); diff --git a/src/smartcontracts/typesystem/endpoint.ts b/src/smartcontracts/typesystem/endpoint.ts index 4fa0cbdba..9868b72dd 100644 --- a/src/smartcontracts/typesystem/endpoint.ts +++ b/src/smartcontracts/typesystem/endpoint.ts @@ -10,7 +10,12 @@ export class EndpointDefinition { readonly output: EndpointParameterDefinition[] = []; readonly modifiers: EndpointModifiers; - constructor(name: string, input: EndpointParameterDefinition[], output: EndpointParameterDefinition[], modifiers: EndpointModifiers) { + constructor( + name: string, + input: EndpointParameterDefinition[], + output: EndpointParameterDefinition[], + modifiers: EndpointModifiers, + ) { this.name = name; this.input = input || []; this.output = output || []; @@ -22,12 +27,12 @@ export class EndpointDefinition { } static fromJSON(json: { - name: string, - onlyOwner?: boolean - mutability: string, - payableInTokens: string[], - inputs: any[], - outputs: any[] + name: string; + onlyOwner?: boolean; + mutability: string; + payableInTokens: string[]; + inputs: any[]; + outputs: any[]; }): EndpointDefinition { json.name = json.name == null ? NamePlaceholder : json.name; json.onlyOwner = json.onlyOwner || false; @@ -35,8 +40,8 @@ export class EndpointDefinition { json.inputs = json.inputs || []; json.outputs = json.outputs || []; - let input = json.inputs.map(param => EndpointParameterDefinition.fromJSON(param)); - let output = json.outputs.map(param => EndpointParameterDefinition.fromJSON(param)); + let input = json.inputs.map((param) => EndpointParameterDefinition.fromJSON(param)); + let output = json.outputs.map((param) => EndpointParameterDefinition.fromJSON(param)); let modifiers = new EndpointModifiers(json.mutability, json.payableInTokens, json.onlyOwner); return new EndpointDefinition(json.name, input, output, modifiers); @@ -98,8 +103,12 @@ export class EndpointParameterDefinition { this.type = type; } - static fromJSON(json: { name?: string, description?: string, type: string }): EndpointParameterDefinition { + static fromJSON(json: { name?: string; description?: string; type: string }): EndpointParameterDefinition { let parsedType = new TypeExpressionParser().parse(json.type); - return new EndpointParameterDefinition(json.name || NamePlaceholder, json.description || DescriptionPlaceholder, parsedType); + return new EndpointParameterDefinition( + json.name || NamePlaceholder, + json.description || DescriptionPlaceholder, + parsedType, + ); } } diff --git a/src/smartcontracts/typesystem/enum.spec.ts b/src/smartcontracts/typesystem/enum.spec.ts index 4e98ab650..50ede8e21 100644 --- a/src/smartcontracts/typesystem/enum.spec.ts +++ b/src/smartcontracts/typesystem/enum.spec.ts @@ -15,23 +15,18 @@ describe("test enums", () => { ]); let orangeVariant = new EnumVariantDefinition("Orange", 1, [ - new FieldDefinition("0", "hex code", new StringType()) + new FieldDefinition("0", "hex code", new StringType()), ]); - let enumType = new EnumType("Colour", [ - greenVariant, - orangeVariant - ]); + let enumType = new EnumType("Colour", [greenVariant, orangeVariant]); let green = new EnumValue(enumType, greenVariant, [ new Field(new U8Value(0), "0"), new Field(new U8Value(255), "1"), - new Field(new U8Value(0), "2") + new Field(new U8Value(0), "2"), ]); - let orange = new EnumValue(enumType, orangeVariant, [ - new Field(new StringValue("#FFA500"), "0") - ]); + let orange = new EnumValue(enumType, orangeVariant, [new Field(new StringValue("#FFA500"), "0")]); assert.lengthOf(green.getFields(), 3); assert.lengthOf(orange.getFields(), 1); @@ -52,7 +47,7 @@ describe("test enums", () => { ]); let orangeVariant = new EnumVariantDefinition("Orange", 1, [ - new FieldDefinition("0", "hex code", new StringType()) + new FieldDefinition("0", "hex code", new StringType()), ]); let yellowVariant = new EnumVariantDefinition("Yellow", 2, [ @@ -62,54 +57,37 @@ describe("test enums", () => { ]); // Define enum type - let enumType = new EnumType("Colour", [ - greenVariant, - orangeVariant, - yellowVariant - ]); + let enumType = new EnumType("Colour", [greenVariant, orangeVariant, yellowVariant]); // Create enum values let green = new EnumValue(enumType, greenVariant, [ new Field(new U8Value(0), "0"), new Field(new U8Value(255), "1"), - new Field(new U8Value(0), "2") + new Field(new U8Value(0), "2"), ]); - let orange = new EnumValue(enumType, orangeVariant, [ - new Field(new StringValue("#FFA500"), "0") - ]); + let orange = new EnumValue(enumType, orangeVariant, [new Field(new StringValue("#FFA500"), "0")]); let yellow = new EnumValue(enumType, yellowVariant, [ new Field(new U8Value(255), "red"), new Field(new U8Value(255), "green"), - new Field(new U8Value(0), "blue") + new Field(new U8Value(0), "blue"), ]); // Test valueOf() assert.deepEqual(green.valueOf(), { - "name": "Green", - "fields": [ - new BigNumber(0), - new BigNumber(255), - new BigNumber(0) - ] + name: "Green", + fields: [new BigNumber(0), new BigNumber(255), new BigNumber(0)], }); assert.deepEqual(orange.valueOf(), { - "name": "Orange", - "fields": [ - "#FFA500" - ] + name: "Orange", + fields: ["#FFA500"], }); assert.deepEqual(yellow.valueOf(), { - "name": "Yellow", - "fields": [ - new BigNumber(255), - new BigNumber(255), - new BigNumber(0) - ] + name: "Yellow", + fields: [new BigNumber(255), new BigNumber(255), new BigNumber(0)], }); }); }); - diff --git a/src/smartcontracts/typesystem/enum.ts b/src/smartcontracts/typesystem/enum.ts index 1320a4b41..a0a2b24d6 100644 --- a/src/smartcontracts/typesystem/enum.ts +++ b/src/smartcontracts/typesystem/enum.ts @@ -35,8 +35,8 @@ export class EnumType extends CustomType { return variants.map((variant, index) => { return { ...variant, - discriminant: index - } + discriminant: index, + }; }); } @@ -71,7 +71,7 @@ export class EnumVariantDefinition { constructor(name: string, discriminant: number, fieldsDefinitions: FieldDefinition[] = []) { guardTrue( discriminant < SimpleEnumMaxDiscriminant, - `discriminant for simple enum should be less than ${SimpleEnumMaxDiscriminant}` + `discriminant for simple enum should be less than ${SimpleEnumMaxDiscriminant}`, ); this.name = name; @@ -89,7 +89,7 @@ export class EnumVariantDefinition { } getFieldDefinition(name: string): FieldDefinition | undefined { - return this.fieldsDefinitions.find(item => item.name == name); + return this.fieldsDefinitions.find((item) => item.name == name); } getNamesOfDependencies(): string[] { @@ -109,7 +109,7 @@ export class EnumValue extends TypedValue { this.name = variant.name; this.discriminant = variant.discriminant; this.fields = fields; - this.fieldsByName = new Map(fields.map(field => [field.name, field])); + this.fieldsByName = new Map(fields.map((field) => [field.name, field])); let definitions = variant.getFieldsDefinitions(); Fields.checkTyping(this.fields, definitions); diff --git a/src/smartcontracts/typesystem/event.ts b/src/smartcontracts/typesystem/event.ts index 5b4dcac69..f358b4688 100644 --- a/src/smartcontracts/typesystem/event.ts +++ b/src/smartcontracts/typesystem/event.ts @@ -12,14 +12,11 @@ export class EventDefinition { this.inputs = inputs || []; } - static fromJSON(json: { - identifier: string, - inputs: any[] - }): EventDefinition { + static fromJSON(json: { identifier: string; inputs: any[] }): EventDefinition { json.identifier = json.identifier == null ? NamePlaceholder : json.identifier; json.inputs = json.inputs || []; - const inputs = json.inputs.map(param => EventTopicDefinition.fromJSON(param)); + const inputs = json.inputs.map((param) => EventTopicDefinition.fromJSON(param)); return new EventDefinition(json.identifier, inputs); } } @@ -29,19 +26,19 @@ export class EventTopicDefinition { readonly type: Type; readonly indexed: boolean; - constructor(options: { name: string, type: Type, indexed: boolean }) { + constructor(options: { name: string; type: Type; indexed: boolean }) { this.name = options.name; this.type = options.type; this.indexed = options.indexed; } - static fromJSON(json: { name?: string, type: string, indexed: boolean }): EventTopicDefinition { + static fromJSON(json: { name?: string; type: string; indexed: boolean }): EventTopicDefinition { const parsedType = new TypeExpressionParser().parse(json.type); return new EventTopicDefinition({ name: json.name || NamePlaceholder, type: parsedType, - indexed: json.indexed + indexed: json.indexed, }); } } diff --git a/src/smartcontracts/typesystem/factory.ts b/src/smartcontracts/typesystem/factory.ts index b48708295..651de575e 100644 --- a/src/smartcontracts/typesystem/factory.ts +++ b/src/smartcontracts/typesystem/factory.ts @@ -4,13 +4,13 @@ import { List } from "./generic"; import { TokenIdentifierValue } from "./tokenIdentifier"; export function createListOfAddresses(addresses: Address[]): List { - let addressesTyped = addresses.map(address => new AddressValue(address)); + let addressesTyped = addresses.map((address) => new AddressValue(address)); let list = List.fromItems(addressesTyped); return list; } export function createListOfTokenIdentifiers(identifiers: string[]): List { - let identifiersTyped = identifiers.map(identifier => new TokenIdentifierValue(identifier)); + let identifiersTyped = identifiers.map((identifier) => new TokenIdentifierValue(identifier)); let list = List.fromItems(identifiersTyped); return list; } diff --git a/src/smartcontracts/typesystem/fields.ts b/src/smartcontracts/typesystem/fields.ts index c281df94e..d8953cce4 100644 --- a/src/smartcontracts/typesystem/fields.ts +++ b/src/smartcontracts/typesystem/fields.ts @@ -13,7 +13,7 @@ export class FieldDefinition { this.type = type; } - static fromJSON(json: { name: string, description: string, type: string }): FieldDefinition { + static fromJSON(json: { name: string; description: string; type: string }): FieldDefinition { let parsedType = new TypeExpressionParser().parse(json.type); return new FieldDefinition(json.name, json.description, parsedType); } @@ -32,7 +32,9 @@ export class Field { const actualType: Type = this.value.getType(); if (!actualType.equals(expectedDefinition.type)) { - throw new errors.ErrTypingSystem(`check type of field "${expectedDefinition.name}; expected: ${expectedDefinition.type}, actual: ${actualType}"`); + throw new errors.ErrTypingSystem( + `check type of field "${expectedDefinition.name}; expected: ${expectedDefinition.type}, actual: ${actualType}"`, + ); } if (this.name != expectedDefinition.name) { throw new errors.ErrTypingSystem(`check name of field "${expectedDefinition.name}"`); @@ -53,7 +55,7 @@ export class Fields { for (let i = 0; i < fields.length; i++) { let field = fields[i]; let definition = definitions[i]; - + field.checkTyping(definition); } } diff --git a/src/smartcontracts/typesystem/generic.ts b/src/smartcontracts/typesystem/generic.ts index c8b540ea8..cfce5eb15 100644 --- a/src/smartcontracts/typesystem/generic.ts +++ b/src/smartcontracts/typesystem/generic.ts @@ -15,7 +15,7 @@ export class OptionType extends Type { } isAssignableFrom(type: Type): boolean { - if (!(type.hasExactClass(OptionType.ClassName))) { + if (!type.hasExactClass(OptionType.ClassName)) { return false; } diff --git a/src/smartcontracts/typesystem/index.ts b/src/smartcontracts/typesystem/index.ts index 4e79b5554..f7bc39d45 100644 --- a/src/smartcontracts/typesystem/index.ts +++ b/src/smartcontracts/typesystem/index.ts @@ -27,4 +27,3 @@ export * from "./typeExpressionParser"; export * from "./typeMapper"; export * from "./types"; export * from "./variadic"; - diff --git a/src/smartcontracts/typesystem/matchers.ts b/src/smartcontracts/typesystem/matchers.ts index c34e98e82..43957d535 100644 --- a/src/smartcontracts/typesystem/matchers.ts +++ b/src/smartcontracts/typesystem/matchers.ts @@ -27,7 +27,7 @@ export function onTypeSelect( onTuple: () => TResult; onEnum: () => TResult; onOther?: () => TResult; - } + }, ): TResult { if (type.hasExactClass(OptionType.ClassName)) { return selectors.onOption(); @@ -69,7 +69,7 @@ export function onTypedValueSelect( onTuple: () => TResult; onEnum: () => TResult; onOther?: () => TResult; - } + }, ): TResult { if (value.hasClassOrSuperclass(PrimitiveValue.ClassName)) { return selectors.onPrimitive(); @@ -112,7 +112,7 @@ export function onPrimitiveValueSelect( onTypeIdentifier: () => TResult; onNothing: () => TResult; onOther?: () => TResult; - } + }, ): TResult { if (value.hasExactClass(BooleanValue.ClassName)) { return selectors.onBoolean(); @@ -157,7 +157,7 @@ export function onPrimitiveTypeSelect( onTokenIndetifier: () => TResult; onNothing: () => TResult; onOther?: () => TResult; - } + }, ): TResult { if (type.hasExactClass(BooleanType.ClassName)) { return selectors.onBoolean(); diff --git a/src/smartcontracts/typesystem/struct.spec.ts b/src/smartcontracts/typesystem/struct.spec.ts index ae7639968..36209019d 100644 --- a/src/smartcontracts/typesystem/struct.spec.ts +++ b/src/smartcontracts/typesystem/struct.spec.ts @@ -8,15 +8,12 @@ import { TokenIdentifierType, TokenIdentifierValue } from "./tokenIdentifier"; describe("test structs", () => { it("should get fields", () => { - let fooType = new StructType( - "Foo", - [ - new FieldDefinition("a", "", new TokenIdentifierType()), - new FieldDefinition("b", "", new BigUIntType()), - new FieldDefinition("c", "", new U32Type()), - new FieldDefinition("d", "", new BytesType()), - ] - ); + let fooType = new StructType("Foo", [ + new FieldDefinition("a", "", new TokenIdentifierType()), + new FieldDefinition("b", "", new BigUIntType()), + new FieldDefinition("c", "", new U32Type()), + new FieldDefinition("d", "", new BytesType()), + ]); let fooStruct = new Struct(fooType, [ new Field(new TokenIdentifierValue("lucky-token"), "a"), diff --git a/src/smartcontracts/typesystem/struct.ts b/src/smartcontracts/typesystem/struct.ts index 5483aa8d7..94e367f8f 100644 --- a/src/smartcontracts/typesystem/struct.ts +++ b/src/smartcontracts/typesystem/struct.ts @@ -15,8 +15,8 @@ export class StructType extends CustomType { return StructType.ClassName; } - static fromJSON(json: { name: string, fields: any[] }): StructType { - let definitions = (json.fields || []).map(definition => FieldDefinition.fromJSON(definition)); + static fromJSON(json: { name: string; fields: any[] }): StructType { + let definitions = (json.fields || []).map((definition) => FieldDefinition.fromJSON(definition)); return new StructType(json.name, definitions); } @@ -25,7 +25,7 @@ export class StructType extends CustomType { } getFieldDefinition(name: string): FieldDefinition | undefined { - return this.fieldsDefinitions.find(item => item.name == name); + return this.fieldsDefinitions.find((item) => item.name == name); } getNamesOfDependencies(): string[] { @@ -44,7 +44,7 @@ export class Struct extends TypedValue { constructor(type: StructType, fields: Field[]) { super(type); this.fields = fields; - this.fieldsByName = new Map(fields.map(field => [field.name, field])); + this.fieldsByName = new Map(fields.map((field) => [field.name, field])); this.checkTyping(); } diff --git a/src/smartcontracts/typesystem/tokenIdentifier.ts b/src/smartcontracts/typesystem/tokenIdentifier.ts index 7ea324cfe..5fea9d8b2 100644 --- a/src/smartcontracts/typesystem/tokenIdentifier.ts +++ b/src/smartcontracts/typesystem/tokenIdentifier.ts @@ -24,7 +24,7 @@ export class TokenIdentifierValue extends PrimitiveValue { } static egld(): TokenIdentifierValue { - return new TokenIdentifierValue(EGLDTokenIdentifier) + return new TokenIdentifierValue(EGLDTokenIdentifier); } static esdtTokenIdentifier(identifier: string): TokenIdentifierValue { @@ -46,7 +46,7 @@ export class TokenIdentifierValue extends PrimitiveValue { if (this.getLength() != other.getLength()) { return false; } - + return this.value == other.value; } diff --git a/src/smartcontracts/typesystem/tuple.ts b/src/smartcontracts/typesystem/tuple.ts index caaf7fd4b..f249913db 100644 --- a/src/smartcontracts/typesystem/tuple.ts +++ b/src/smartcontracts/typesystem/tuple.ts @@ -15,13 +15,15 @@ export class TupleType extends StructType { } private static prepareName(typeParameters: Type[]): string { - let fields: string = typeParameters.map(type => type.toString()).join(", "); + let fields: string = typeParameters.map((type) => type.toString()).join(", "); let result = `tuple<${fields}>`; return result; } private static prepareFieldDefinitions(typeParameters: Type[]): FieldDefinition[] { - let result = typeParameters.map((type, i) => new FieldDefinition(prepareFieldName(i), "anonymous tuple field", type)); + let result = typeParameters.map( + (type, i) => new FieldDefinition(prepareFieldName(i), "anonymous tuple field", type), + ); return result; } } @@ -50,7 +52,7 @@ export class Tuple extends Struct { throw new errors.ErrTypingSystem("bad tuple items"); } - let fieldsTypes = items.map(item => item.getType()); + let fieldsTypes = items.map((item) => item.getType()); let tupleType = new TupleType(...fieldsTypes); let fields = items.map((item, i) => new Field(item, prepareFieldName(i))); diff --git a/src/smartcontracts/typesystem/typeMapper.spec.ts b/src/smartcontracts/typesystem/typeMapper.spec.ts index 987f16e34..130d511b6 100644 --- a/src/smartcontracts/typesystem/typeMapper.spec.ts +++ b/src/smartcontracts/typesystem/typeMapper.spec.ts @@ -39,10 +39,14 @@ describe("test mapper", () => { }); it("should map complex generic, composite, variadic types", () => { - testMapping("MultiResultVec>", new VariadicType( - new CompositeType(new I32Type(), new BytesType()), - )); - testMapping("VarArgs>", new VariadicType(new CompositeType(new I32Type(), new BytesType()))); + testMapping( + "MultiResultVec>", + new VariadicType(new CompositeType(new I32Type(), new BytesType())), + ); + testMapping( + "VarArgs>", + new VariadicType(new CompositeType(new I32Type(), new BytesType())), + ); testMapping("OptionalResult
", new OptionalType(new AddressType())); }); diff --git a/src/smartcontracts/typesystem/typeMapper.ts b/src/smartcontracts/typesystem/typeMapper.ts index 110c37fc6..edc40769f 100644 --- a/src/smartcontracts/typesystem/typeMapper.ts +++ b/src/smartcontracts/typesystem/typeMapper.ts @@ -21,7 +21,7 @@ import { U16Type, U32Type, U64Type, - U8Type + U8Type, } from "./numerical"; import { StringType } from "./string"; import { StructType } from "./struct"; @@ -99,7 +99,7 @@ export class TypeMapper { ["EgldOrEsdtTokenIdentifier", new TokenIdentifierType()], ["CodeMetadata", new CodeMetadataType()], ["nothing", new NothingType()], - ["AsyncCall", new NothingType()] + ["AsyncCall", new NothingType()], ]); this.learnedTypesMap = new Map(); @@ -180,8 +180,8 @@ export class TypeMapper { new EnumVariantDefinition( variant.name, variant.discriminant, - this.mappedFields(variant.getFieldsDefinitions()) - ) + this.mappedFields(variant.getFieldsDefinitions()), + ), ); let mappedEnum = new EnumType(type.getName(), variants); return mappedEnum; @@ -189,7 +189,7 @@ export class TypeMapper { private mappedFields(definitions: FieldDefinition[]): FieldDefinition[] { return definitions.map( - (definition) => new FieldDefinition(definition.name, definition.description, this.mapType(definition.type)) + (definition) => new FieldDefinition(definition.name, definition.description, this.mapType(definition.type)), ); } diff --git a/src/smartcontracts/typesystem/types.spec.ts b/src/smartcontracts/typesystem/types.spec.ts index 22f87769d..0639b9615 100644 --- a/src/smartcontracts/typesystem/types.spec.ts +++ b/src/smartcontracts/typesystem/types.spec.ts @@ -19,19 +19,19 @@ describe("test types", () => { }); it("should be assignable from", () => { - assert.isTrue((new Type("Type")).isAssignableFrom(new PrimitiveType("PrimitiveType"))); - assert.isTrue((new Type("Type")).isAssignableFrom(new BooleanType())); - assert.isTrue((new Type("Type")).isAssignableFrom(new AddressType())); - assert.isTrue((new Type("Type")).isAssignableFrom(new U32Type())); + assert.isTrue(new Type("Type").isAssignableFrom(new PrimitiveType("PrimitiveType"))); + assert.isTrue(new Type("Type").isAssignableFrom(new BooleanType())); + assert.isTrue(new Type("Type").isAssignableFrom(new AddressType())); + assert.isTrue(new Type("Type").isAssignableFrom(new U32Type())); - assert.isTrue((new PrimitiveType("PrimitiveType")).isAssignableFrom(new BooleanType())); - assert.isTrue((new PrimitiveType("PrimitiveType")).isAssignableFrom(new AddressType())); - assert.isTrue((new PrimitiveType("PrimitiveType")).isAssignableFrom(new U32Type())); + assert.isTrue(new PrimitiveType("PrimitiveType").isAssignableFrom(new BooleanType())); + assert.isTrue(new PrimitiveType("PrimitiveType").isAssignableFrom(new AddressType())); + assert.isTrue(new PrimitiveType("PrimitiveType").isAssignableFrom(new U32Type())); - assert.isTrue((new AddressType()).isAssignableFrom(new AddressType())); - assert.isFalse((new AddressType()).isAssignableFrom(new BooleanType())); - assert.isFalse((new U32Type()).isAssignableFrom(new BooleanType())); - assert.isFalse((new U32Type()).isAssignableFrom(new PrimitiveType("PrimitiveType"))); + assert.isTrue(new AddressType().isAssignableFrom(new AddressType())); + assert.isFalse(new AddressType().isAssignableFrom(new BooleanType())); + assert.isFalse(new U32Type().isAssignableFrom(new BooleanType())); + assert.isFalse(new U32Type().isAssignableFrom(new PrimitiveType("PrimitiveType"))); assert.isTrue(new BytesType().isAssignableFrom(new BytesType())); assert.isTrue(new U32Type().isAssignableFrom(parser.parse("u32"))); @@ -54,17 +54,32 @@ describe("test types", () => { it("should get fully qualified name", () => { assert.equal(new Type("foo").getFullyQualifiedName(), "multiversx:types:foo"); assert.equal(new U32Type().getFullyQualifiedName(), "multiversx:types:u32"); - assert.equal(parser.parse("MultiResultVec").getFullyQualifiedName(), "multiversx:types:MultiResultVec"); + assert.equal( + parser.parse("MultiResultVec").getFullyQualifiedName(), + "multiversx:types:MultiResultVec", + ); assert.equal(parser.parse("utf-8 string").getFullyQualifiedName(), "multiversx:types:utf-8 string"); - assert.equal(parser.parse("Option").getFullyQualifiedName(), "multiversx:types:Option"); + assert.equal( + parser.parse("Option").getFullyQualifiedName(), + "multiversx:types:Option", + ); }); it("types and values should have correct JavaScript class hierarchy", () => { assert.deepEqual(new U32Type().getClassHierarchy(), ["Type", "PrimitiveType", "NumericalType", "U32Type"]); - assert.deepEqual(new U32Value(42).getClassHierarchy(), ["TypedValue", "PrimitiveValue", "NumericalValue", "U32Value"]); + assert.deepEqual(new U32Value(42).getClassHierarchy(), [ + "TypedValue", + "PrimitiveValue", + "NumericalValue", + "U32Value", + ]); assert.deepEqual(new BytesType().getClassHierarchy(), ["Type", "PrimitiveType", "BytesType"]); - assert.deepEqual(new BytesValue(Buffer.from("foobar")).getClassHierarchy(), ["TypedValue", "PrimitiveValue", "BytesValue"]); + assert.deepEqual(new BytesValue(Buffer.from("foobar")).getClassHierarchy(), [ + "TypedValue", + "PrimitiveValue", + "BytesValue", + ]); }); it("should report type dependencies", () => { diff --git a/src/smartcontracts/typesystem/types.ts b/src/smartcontracts/typesystem/types.ts index 007b780cc..b3e68d5bb 100644 --- a/src/smartcontracts/typesystem/types.ts +++ b/src/smartcontracts/typesystem/types.ts @@ -12,7 +12,11 @@ export class Type { private readonly typeParameters: Type[]; protected readonly cardinality: TypeCardinality; - public constructor(name: string, typeParameters: Type[] = [], cardinality: TypeCardinality = TypeCardinality.fixed(1)) { + public constructor( + name: string, + typeParameters: Type[] = [], + cardinality: TypeCardinality = TypeCardinality.fixed(1), + ) { guardValueIsSet("name", name); this.name = name; @@ -29,8 +33,8 @@ export class Type { } getClassHierarchy(): string[] { - let prototypes = getJavascriptPrototypesInHierarchy(this, prototype => prototype.belongsToTypesystem); - let classNames = prototypes.map(prototype => (prototype).getClassName()).reverse(); + let prototypes = getJavascriptPrototypesInHierarchy(this, (prototype) => prototype.belongsToTypesystem); + let classNames = prototypes.map((prototype) => (prototype).getClassName()).reverse(); return classNames; } @@ -38,11 +42,13 @@ export class Type { * Gets the fully qualified name of the type, to allow for better (efficient and non-ambiguous) type comparison within the custom typesystem. */ getFullyQualifiedName(): string { - let joinedTypeParameters = this.getTypeParameters().map(type => type.getFullyQualifiedName()).join(", "); + let joinedTypeParameters = this.getTypeParameters() + .map((type) => type.getFullyQualifiedName()) + .join(", "); - return this.isGenericType() ? - `multiversx:types:${this.getName()}<${joinedTypeParameters}>` : - `multiversx:types:${this.getName()}`; + return this.isGenericType() + ? `multiversx:types:${this.getName()}<${joinedTypeParameters}>` + : `multiversx:types:${this.getName()}`; } hasExactClass(className: string): boolean { @@ -68,10 +74,12 @@ export class Type { } /** - * Generates type expressions similar to mx-sdk-rs. + * Generates type expressions similar to mx-sdk-rs. */ toString() { - let typeParameters: string = this.getTypeParameters().map(type => type.toString()).join(", "); + let typeParameters: string = this.getTypeParameters() + .map((type) => type.toString()) + .join(", "); let typeParametersExpression = typeParameters ? `<${typeParameters}>` : ""; return `${this.name}${typeParametersExpression}`; } @@ -103,11 +111,11 @@ export class Type { /** * Inspired from: https://docs.microsoft.com/en-us/dotnet/api/system.type.isassignablefrom * For (most) generics, type invariance is expected (assumed) - neither covariance, nor contravariance are supported yet (will be supported in a next release). - * + * * One exception though: for {@link OptionType}, we simulate covariance for missing (not provided) values. * For example, Option is assignable from Option. * For more details, see the implementation of {@link OptionType} and @{@link OptionalType}. - * + * * Also see: * - https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) * - https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance @@ -128,8 +136,8 @@ export class Type { } private static getFullyQualifiedNamesInHierarchy(type: Type): string[] { - let prototypes: any[] = getJavascriptPrototypesInHierarchy(type, prototype => prototype.belongsToTypesystem); - let fullyQualifiedNames = prototypes.map(prototype => prototype.getFullyQualifiedName.call(type)); + let prototypes: any[] = getJavascriptPrototypesInHierarchy(type, (prototype) => prototype.belongsToTypesystem); + let fullyQualifiedNames = prototypes.map((prototype) => prototype.getFullyQualifiedName.call(type)); return fullyQualifiedNames; } @@ -150,7 +158,7 @@ export class Type { toJSON(): any { return { name: this.name, - typeParameters: this.typeParameters.map(item => item.toJSON()) + typeParameters: this.typeParameters.map((item) => item.toJSON()), }; } @@ -161,14 +169,14 @@ export class Type { /** * A special marker for types within the custom typesystem. */ - belongsToTypesystem() { } + belongsToTypesystem() {} } /** * TODO: Simplify this class, keep only what is needed. - * + * * An abstraction for defining and operating with the cardinality of a (composite or simple) type. - * + * * Simple types (the ones that are directly encodable) have a fixed cardinality: [lower = 1, upper = 1]. * Composite types (not directly encodable) do not follow this constraint. For example: * - VarArgs: [lower = 0, upper = *] @@ -254,8 +262,8 @@ export abstract class TypedValue { } getClassHierarchy(): string[] { - let prototypes = getJavascriptPrototypesInHierarchy(this, prototype => prototype.belongsToTypesystem); - let classNames = prototypes.map(prototype => (prototype).getClassName()).reverse(); + let prototypes = getJavascriptPrototypesInHierarchy(this, (prototype) => prototype.belongsToTypesystem); + let classNames = prototypes.map((prototype) => (prototype).getClassName()).reverse(); return classNames; } @@ -278,7 +286,7 @@ export abstract class TypedValue { /** * A special marker for values within the custom typesystem. */ - belongsToTypesystem() { } + belongsToTypesystem() {} } export abstract class PrimitiveValue extends TypedValue { @@ -309,7 +317,6 @@ export class TypePlaceholder extends Type { } } - export class NullType extends Type { static ClassName = "NullType"; diff --git a/src/testutils/mockProvider.ts b/src/testutils/mockProvider.ts index 884ca6496..fc867a6c0 100644 --- a/src/testutils/mockProvider.ts +++ b/src/testutils/mockProvider.ts @@ -1,10 +1,21 @@ -import { ContractResultItem, ContractResults, TransactionOnNetwork, TransactionStatus } from "@multiversx/sdk-network-providers"; +import { + ContractResultItem, + ContractResults, + TransactionOnNetwork, + TransactionStatus, +} from "@multiversx/sdk-network-providers"; import { Address } from "../address"; import { AsyncTimer } from "../asyncTimer"; import * as errors from "../errors"; import { ErrMock } from "../errors"; import { IAddress } from "../interface"; -import { IAccountOnNetwork, IContractQueryResponse, INetworkConfig, ITransactionOnNetwork, ITransactionStatus } from "../interfaceOfNetwork"; +import { + IAccountOnNetwork, + IContractQueryResponse, + INetworkConfig, + ITransactionOnNetwork, + ITransactionStatus, +} from "../interfaceOfNetwork"; import { Query } from "../smartcontracts/query"; import { Transaction, TransactionHash } from "../transaction"; import { createAccountBalance } from "./utils"; @@ -24,18 +35,9 @@ export class MockProvider { this.transactions = new Map(); this.accounts = new Map(); - this.accounts.set( - MockProvider.AddressOfAlice.bech32(), - { nonce: 0, balance: createAccountBalance(1000) } - ); - this.accounts.set( - MockProvider.AddressOfBob.bech32(), - { nonce: 5, balance: createAccountBalance(500) } - ); - this.accounts.set( - MockProvider.AddressOfCarol.bech32(), - { nonce: 42, balance: createAccountBalance(300) } - ); + this.accounts.set(MockProvider.AddressOfAlice.bech32(), { nonce: 0, balance: createAccountBalance(1000) }); + this.accounts.set(MockProvider.AddressOfBob.bech32(), { nonce: 5, balance: createAccountBalance(500) }); + this.accounts.set(MockProvider.AddressOfCarol.bech32(), { nonce: 42, balance: createAccountBalance(300) }); } mockUpdateAccount(address: Address, mutate: (item: IAccountOnNetwork) => void) { @@ -69,7 +71,7 @@ export class MockProvider { let response = new TransactionOnNetwork({ status: new TransactionStatus("executed"), contractResults: new ContractResults([contractResult]), - isCompleted: true + isCompleted: true, }); this.getTransactionResponders.unshift(new GetTransactionResponder(predicate, response)); @@ -109,7 +111,7 @@ export class MockProvider { return account; } - throw new ErrMock("Account not found") + throw new ErrMock("Account not found"); } async sendTransaction(transaction: Transaction): Promise { @@ -119,8 +121,8 @@ export class MockProvider { sender: transaction.getSender(), receiver: transaction.getReceiver(), data: transaction.getData().valueOf(), - status: new TransactionStatus("pending") - }) + status: new TransactionStatus("pending"), + }), ); this.mockTransactionTimeline(transaction, this.nextTransactionTimelinePoints); @@ -176,7 +178,7 @@ export class Wait { } } -export class MarkCompleted { } +export class MarkCompleted {} class QueryContractResponder { readonly matches: (query: Query) => boolean; diff --git a/src/testutils/networkProviders.ts b/src/testutils/networkProviders.ts index 475da761c..736a9bedb 100644 --- a/src/testutils/networkProviders.ts +++ b/src/testutils/networkProviders.ts @@ -1,6 +1,12 @@ import { ApiNetworkProvider, ProxyNetworkProvider } from "@multiversx/sdk-network-providers"; import { IAddress } from "../interface"; -import { IAccountOnNetwork, IContractQueryResponse, INetworkConfig, ITransactionOnNetwork, ITransactionStatus } from "../interfaceOfNetwork"; +import { + IAccountOnNetwork, + IContractQueryResponse, + INetworkConfig, + ITransactionOnNetwork, + ITransactionStatus, +} from "../interfaceOfNetwork"; import { Query } from "../smartcontracts/query"; import { Transaction } from "../transaction"; diff --git a/src/testutils/utils.ts b/src/testutils/utils.ts index 4c59ad5dc..252e6b13f 100644 --- a/src/testutils/utils.ts +++ b/src/testutils/utils.ts @@ -11,12 +11,12 @@ import axios, { AxiosResponse } from "axios"; import BigNumber from "bignumber.js"; export async function prepareDeployment(obj: { - deployer: TestWallet, - contract: SmartContract, - codePath: string, - initArguments: TypedValue[], - gasLimit: IGasLimit, - chainID: IChainID + deployer: TestWallet; + contract: SmartContract; + codePath: string; + initArguments: TypedValue[]; + gasLimit: IGasLimit; + chainID: IChainID; }): Promise { let contract = obj.contract; let deployer = obj.deployer; @@ -26,13 +26,13 @@ export async function prepareDeployment(obj: { gasLimit: obj.gasLimit, initArguments: obj.initArguments, chainID: obj.chainID, - deployer: deployer.address + deployer: deployer.address, }); let nonce = deployer.account.getNonceThenIncrement(); let contractAddress = SmartContract.computeAddress(deployer.address, nonce); transaction.setNonce(nonce); - transaction.setSender(deployer.address) + transaction.setSender(deployer.address); contract.setAddress(contractAddress); transaction.applySignature(await deployer.signer.sign(transaction.serializeForSigning())); @@ -42,11 +42,11 @@ export async function prepareDeployment(obj: { export async function loadContractCode(path: PathLike): Promise { if (isOnBrowserTests()) { let response: AxiosResponse = await axios.get(path.toString(), { - responseType: 'arraybuffer', + responseType: "arraybuffer", transformResponse: [], headers: { - "Accept": "application/wasm" - } + Accept: "application/wasm", + }, }); let buffer = Buffer.from(response.data); diff --git a/src/testutils/wallets.ts b/src/testutils/wallets.ts index fefefb059..e86ce05c0 100644 --- a/src/testutils/wallets.ts +++ b/src/testutils/wallets.ts @@ -23,8 +23,21 @@ export async function syncTestWallets(wallets: Record, provi } export async function loadTestWallets(): Promise> { - let walletNames = ["alice", "bob", "carol", "dan", "eve", "frank", "grace", "heidi", "ivan", "judy", "mallory", "mike"]; - let wallets = await Promise.all(walletNames.map(async name => await loadTestWallet(name))); + let walletNames = [ + "alice", + "bob", + "carol", + "dan", + "eve", + "frank", + "grace", + "heidi", + "ivan", + "judy", + "mallory", + "mike", + ]; + let wallets = await Promise.all(walletNames.map(async (name) => await loadTestWallet(name))); let walletMap: Record = {}; for (let i in walletNames) { walletMap[walletNames[i]] = wallets[i]; @@ -44,11 +57,7 @@ export async function loadTestWallet(name: string): Promise { let jsonContents = JSON.parse(await readTestWalletFileContents(name + ".json")); let pemContents = await readTestWalletFileContents(name + ".pem"); let pemKey = UserSecretKey.fromPem(pemContents); - return new TestWallet( - new Address(jsonContents.address), - pemKey.hex(), - jsonContents, - pemContents); + return new TestWallet(new Address(jsonContents.address), pemKey.hex(), jsonContents, pemContents); } async function readTestWalletFileContents(name: string): Promise { diff --git a/src/tokenTransfer.spec.ts b/src/tokenTransfer.spec.ts index 5a891869c..274121a70 100644 --- a/src/tokenTransfer.spec.ts +++ b/src/tokenTransfer.spec.ts @@ -19,7 +19,10 @@ describe("test token transfer", () => { assert.equal(TokenTransfer.egldFromAmount(100).toPrettyString(), "100.000000000000000000 EGLD"); assert.equal(TokenTransfer.egldFromAmount(1000).toPrettyString(), "1000.000000000000000000 EGLD"); assert.equal(TokenTransfer.egldFromAmount("0.123456789").toPrettyString(), "0.123456789000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toPrettyString(), "0.123456789123456789 EGLD"); + assert.equal( + TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toPrettyString(), + "0.123456789123456789 EGLD", + ); assert.equal(TokenTransfer.egldFromBigInteger("1").toString(), "1"); assert.equal(TokenTransfer.egldFromBigInteger("1").toPrettyString(), "0.000000000000000001 EGLD"); @@ -34,7 +37,10 @@ describe("test token transfer", () => { assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.1", numDecimals).toString(), "100000"); assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.123456789", numDecimals).toString(), "123456"); assert.equal(TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toString(), "1000000"); - assert.equal(TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toPrettyString(), "1.000000 USDC-c76f1f"); + assert.equal( + TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toPrettyString(), + "1.000000 USDC-c76f1f", + ); }); it("should work with MetaESDT", () => { diff --git a/src/tokenTransfer.ts b/src/tokenTransfer.ts index c0dff5aab..ab81d89a4 100644 --- a/src/tokenTransfer.ts +++ b/src/tokenTransfer.ts @@ -51,7 +51,11 @@ export class TokenTransfer { return this.fungibleFromBigInteger(tokenIdentifier, amountAsBigInteger, numDecimals); } - static fungibleFromBigInteger(tokenIdentifier: string, amountAsBigInteger: BigNumber.Value, numDecimals: number = 0) { + static fungibleFromBigInteger( + tokenIdentifier: string, + amountAsBigInteger: BigNumber.Value, + numDecimals: number = 0, + ) { return new TokenTransfer({ tokenIdentifier, nonce: 0, @@ -83,7 +87,12 @@ export class TokenTransfer { return this.metaEsdtFromBigInteger(tokenIdentifier, nonce, amountAsBigInteger, numDecimals); } - static metaEsdtFromBigInteger(tokenIdentifier: string, nonce: number, amountAsBigInteger: BigNumber.Value, numDecimals = 0) { + static metaEsdtFromBigInteger( + tokenIdentifier: string, + nonce: number, + amountAsBigInteger: BigNumber.Value, + numDecimals = 0, + ) { return new TokenTransfer({ tokenIdentifier, nonce, @@ -129,4 +138,4 @@ export class TokenPayment extends TokenTransfer { numDecimals, }); } -}; +} diff --git a/src/tokenTransferBuilders.spec.ts b/src/tokenTransferBuilders.spec.ts index f9ff0152c..abddcb375 100644 --- a/src/tokenTransferBuilders.spec.ts +++ b/src/tokenTransferBuilders.spec.ts @@ -1,7 +1,11 @@ import { assert } from "chai"; import { Address } from "./address"; import { TokenTransfer } from "./tokenTransfer"; -import { ESDTNFTTransferPayloadBuilder, ESDTTransferPayloadBuilder, MultiESDTNFTTransferPayloadBuilder } from "./tokenTransferBuilders"; +import { + ESDTNFTTransferPayloadBuilder, + ESDTTransferPayloadBuilder, + MultiESDTNFTTransferPayloadBuilder, +} from "./tokenTransferBuilders"; describe("test token transfer builders", () => { it("should work with ESDT transfers", () => { @@ -17,7 +21,10 @@ describe("test token transfer builders", () => { .setDestination(new Address("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx")) .build(); - assert.equal(payload.toString(), "ESDTNFTTransfer@4552444a532d333866323439@01@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8"); + assert.equal( + payload.toString(), + "ESDTNFTTransfer@4552444a532d333866323439@01@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8", + ); }); it("should work with ESDTNFT transfers (SFT)", () => { @@ -28,7 +35,10 @@ describe("test token transfer builders", () => { .setDestination(new Address("erd1testnlersh4z0wsv8kjx39me4rmnvjkwu8dsaea7ukdvvc9z396qykv7z7")) .build(); - assert.equal(payload.toString(), "ESDTNFTTransfer@53454d492d396566643066@01@05@5e60b9ff2385ea27ba0c3da4689779a8f7364acee1db0ee7bee59ac660a28974"); + assert.equal( + payload.toString(), + "ESDTNFTTransfer@53454d492d396566643066@01@05@5e60b9ff2385ea27ba0c3da4689779a8f7364acee1db0ee7bee59ac660a28974", + ); }); it("should work with Multi ESDTNFT transfers", () => { @@ -39,6 +49,9 @@ describe("test token transfer builders", () => { .setDestination(new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")) .build(); - assert.equal(payload.toString(), "MultiESDTNFTTransfer@0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1@02@4552444a532d333866323439@01@01@4241522d633830643239@@8ac7230489e80000"); + assert.equal( + payload.toString(), + "MultiESDTNFTTransfer@0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1@02@4552444a532d333866323439@01@01@4241522d633830643239@@8ac7230489e80000", + ); }); }); diff --git a/src/tokens.ts b/src/tokens.ts index b0020339c..e6d18c28b 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -22,7 +22,7 @@ export class NextTokenTransfer { } export class TokenComputer { - constructor() { } + constructor() {} isFungible(token: Token): boolean { return token.nonce === 0; @@ -72,7 +72,7 @@ export class TokenComputer { if (randomSequence.length !== TOKEN_RANDOM_SEQUENCE_LENGTH) { throw new ErrInvalidTokenIdentifier( - "The identifier is not valid. The random sequence does not have the right length" + "The identifier is not valid. The random sequence does not have the right length", ); } } @@ -83,7 +83,7 @@ export class TokenComputer { if (ticker.length < MIN_TICKER_LENGTH || ticker.length > MAX_TICKER_LENGTH) { throw new ErrInvalidTokenIdentifier( - `The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters` + `The token ticker should be between ${MIN_TICKER_LENGTH} and ${MAX_TICKER_LENGTH} characters`, ); } diff --git a/src/utils.ts b/src/utils.ts index 7b1a78b52..dd72af659 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -37,19 +37,19 @@ export function guardLength(withLength: { length?: number }, expectedLength: num } } -export function guardNotEmpty(value: { isEmpty?: () => boolean, length?: number }, what: string) { +export function guardNotEmpty(value: { isEmpty?: () => boolean; length?: number }, what: string) { if (isEmpty(value)) { throw new errors.ErrInvariantFailed(`${what} is empty`); } } -export function guardEmpty(value: { isEmpty?: () => boolean, length?: number }, what: string) { +export function guardEmpty(value: { isEmpty?: () => boolean; length?: number }, what: string) { if (!isEmpty(value)) { throw new errors.ErrInvariantFailed(`${what} is not empty`); } } -export function isEmpty(value: { isEmpty?: () => boolean, length?: number }): boolean { +export function isEmpty(value: { isEmpty?: () => boolean; length?: number }): boolean { if (value.isEmpty) { return value.isEmpty(); } From 75a131c9ae2fb6a9d4c17242ca8f4a17527c1b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 2 Feb 2024 12:59:49 +0200 Subject: [PATCH 077/275] Add editor config. --- .editorconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..25437d3b4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# See: https://EditorConfig.org +# VSCode plugin: https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 From c3c1a2f357658bdd71da1eb6958057a1ac45f125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 2 Feb 2024 13:38:29 +0200 Subject: [PATCH 078/275] Disable eslint formatting rules (prettier wins). --- .eslintrc.js | 28 ++---- .vscode/settings.json | 10 +- package-lock.json | 97 ++++--------------- package.json | 5 +- src/tokenOperations/tokenOperationsFactory.ts | 10 +- 5 files changed, 44 insertions(+), 106 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b822dafbf..c2294fc7d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,23 +5,12 @@ module.exports = { sourceType: "module", }, plugins: ["@typescript-eslint/eslint-plugin"], - extends: [ - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "prettier" - ], + extends: ["plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "prettier"], root: true, env: { - node: true + node: true, }, - ignorePatterns: [ - ".eslintrc.js", - "node_modules", - "out", - "out-tests", - "out-browser", - "out-browser-tests", - ], + ignorePatterns: [".eslintrc.js", "node_modules", "out", "out-tests", "out-browser", "out-browser-tests"], rules: { "@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/explicit-function-return-type": "off", @@ -34,10 +23,13 @@ module.exports = { "@typescript-eslint/no-namespace": "warn", "@typescript-eslint/no-var-requires": "warn", "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-unused-vars": ["warn", { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_" - }], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + }, + ], "prefer-const": "off", }, }; diff --git a/.vscode/settings.json b/.vscode/settings.json index 7a73a41bf..e5c7eee47 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,2 +1,10 @@ { -} \ No newline at end of file + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/package-lock.json b/package-lock.json index 51031e87c..5430da97c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,11 +33,10 @@ "browserify": "17.0.0", "chai": "4.2.0", "eslint": "8.28.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-prettier": "3.4.1", + "eslint-config-prettier": "9.1.0", "esmify": "2.1.1", "mocha": "9.2.2", - "prettier": "2.2.1", + "prettier": "3.2.4", "ts-node": "9.1.1", "typescript": "4.1.2" } @@ -2561,9 +2560,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -2572,27 +2571,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -2911,12 +2889,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4608,27 +4580,18 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" + "node": ">=14" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/process": { @@ -7801,21 +7764,12 @@ } }, "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "requires": {} }, - "eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -7954,12 +7908,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, "fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -9237,20 +9185,11 @@ "dev": true }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", diff --git a/package.json b/package.json index 4bc332721..83fcc1c63 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,7 @@ "@typescript-eslint/eslint-plugin": "5.44.0", "@typescript-eslint/parser": "5.44.0", "eslint": "8.28.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-prettier": "3.4.1", - "prettier": "2.2.1" + "eslint-config-prettier": "9.1.0", + "prettier": "3.2.4" } } diff --git a/src/tokenOperations/tokenOperationsFactory.ts b/src/tokenOperations/tokenOperationsFactory.ts index a55371b98..a4a4ffc52 100644 --- a/src/tokenOperations/tokenOperationsFactory.ts +++ b/src/tokenOperations/tokenOperationsFactory.ts @@ -63,7 +63,7 @@ interface IIssueSemiFungibleArgs extends IBaseArgs { canAddSpecialRoles: boolean; } -interface IIssueNonFungibleArgs extends IIssueSemiFungibleArgs { } +interface IIssueNonFungibleArgs extends IIssueSemiFungibleArgs {} interface IRegisterMetaESDT extends IIssueSemiFungibleArgs { numDecimals: number; @@ -210,7 +210,7 @@ export class TokenOperationsFactory { utf8ToHex("canUpgrade"), args.canUpgrade ? this.trueAsHex : this.falseAsHex, utf8ToHex("canAddSpecialRoles"), - args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex + args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return this.createTransaction({ @@ -254,7 +254,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG utf8ToHex("canUpgrade"), args.canUpgrade ? this.trueAsHex : this.falseAsHex, utf8ToHex("canAddSpecialRoles"), - args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex + args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return this.createTransaction({ @@ -289,7 +289,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG utf8ToHex("canUpgrade"), args.canUpgrade ? this.trueAsHex : this.falseAsHex, utf8ToHex("canAddSpecialRoles"), - args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex + args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return this.createTransaction({ @@ -325,7 +325,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG utf8ToHex("canUpgrade"), args.canUpgrade ? this.trueAsHex : this.falseAsHex, utf8ToHex("canAddSpecialRoles"), - args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex + args.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; return this.createTransaction({ From eb8e8400f54a6ba6aad779937e50f656a788deee Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Wed, 7 Feb 2024 13:39:56 +0200 Subject: [PATCH 079/275] refactoring draftTransaction to TransactionNext --- .../delegationTransactionsFactory.ts | 78 ++++++++------ .../transactionNextBuilder.ts | 101 ++++++++++++++++++ 2 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 src/transactionsFactories/transactionNextBuilder.ts diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index fe7133a01..e0a00e069 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,11 +1,11 @@ import { IAddress } from "../interface"; import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { DraftTransaction } from "../draftTransaction"; -import { DraftTransactionBuilder } from "./draftTransactionBuilder"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; +import { TransactionNext } from "../transaction"; interface Config { chainID: string; @@ -26,9 +26,11 @@ interface IValidatorPublicKey { export class DelegationTransactionsFactory { private readonly config: Config; + private readonly chainID: Config; - constructor(config: Config) { + constructor(config: Config, chainID: Config) { this.config = config; + this.chainID = chainID; } createTransactionForNewDelegationContract(options: { @@ -36,7 +38,7 @@ export class DelegationTransactionsFactory { totalDelegationCap: BigNumber.Value, serviceFee: BigNumber.Value, amount: BigNumber.Value - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), @@ -45,13 +47,14 @@ export class DelegationTransactionsFactory { const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), dataParts: dataParts, gasLimit: executionGasLimit, addDataMovementGas: true, + chainID: this.chainID.toString(), amount: options.amount }).build(); } @@ -61,7 +64,7 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[], signedMessages: Uint8Array[] - }): DraftTransaction { + }): TransactionNext { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } @@ -73,11 +76,12 @@ export class DelegationTransactionsFactory { dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -87,7 +91,7 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): DraftTransaction { + }): TransactionNext { const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { @@ -96,11 +100,12 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -110,7 +115,7 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): DraftTransaction { + }): TransactionNext { let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { @@ -123,11 +128,12 @@ export class DelegationTransactionsFactory { this.config.gasLimitDelegationOperations ); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -137,7 +143,7 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): DraftTransaction { + }): TransactionNext { let dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { @@ -150,11 +156,12 @@ export class DelegationTransactionsFactory { this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -164,7 +171,7 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): DraftTransaction { + }): TransactionNext { let dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { @@ -177,11 +184,12 @@ export class DelegationTransactionsFactory { this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -191,7 +199,7 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] - }): DraftTransaction { + }): TransactionNext { const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { @@ -200,11 +208,12 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -214,17 +223,18 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, serviceFee: BigNumber.Value - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -234,17 +244,18 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress, delegationCap: BigNumber.Value - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -253,17 +264,18 @@ export class DelegationTransactionsFactory { createTransactionForSettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setAutomaticActivation", utf8ToHex("true") ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -272,17 +284,18 @@ export class DelegationTransactionsFactory { createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setAutomaticActivation", utf8ToHex("false") ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -291,17 +304,18 @@ export class DelegationTransactionsFactory { createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -310,17 +324,18 @@ export class DelegationTransactionsFactory { createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -332,7 +347,7 @@ export class DelegationTransactionsFactory { name: string, website: string, identifier: string - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setMetaData", utf8ToHex(options.name), @@ -340,11 +355,12 @@ export class DelegationTransactionsFactory { utf8ToHex(options.identifier) ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, + chainID: this.chainID.toString(), gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts new file mode 100644 index 000000000..10f46afca --- /dev/null +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -0,0 +1,101 @@ +import { BigNumber } from "bignumber.js"; +import { IAddress, ITransactionPayload } from "../interface"; +import { ARGUMENTS_SEPARATOR, TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "../constants"; +import { TransactionPayload } from "../transactionPayload"; +import { TransactionNext } from "../transaction"; + +interface Config { + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; +} + +export class TransactionNextBuilder { + private config: Config; + private sender: IAddress; + private receiver: IAddress; + private dataParts: string[]; + private providedGasLimit: BigNumber; + private addDataMovementGas: boolean; + private amount?: BigNumber.Value; + private nonce?: BigNumber.Value; + private value?: BigNumber.Value; + private senderUsername?: string; + private receiverUsername?: string; + private gasPrice?: BigNumber.Value; + private chainID: string; + private version?: number; + private options?: number; + private guardian?: string; + + constructor(options: { + config: Config, + nonce?: BigNumber.Value; + value?: BigNumber.Value; + sender: IAddress, + receiver: IAddress, + senderUsername?: string; + receiverUsername?: string; + gasPrice?: BigNumber.Value; + gasLimit: BigNumber.Value, + dataParts: string[], + chainID: string; + version?: number; + options?: number; + guardian?: string; + addDataMovementGas: boolean, + amount?: BigNumber.Value + }) { + this.config = options.config; + this.nonce = options.nonce; + this.value = options.value || new BigNumber(0);; + this.sender = options.sender; + this.receiver = options.receiver; + this.senderUsername = options.senderUsername || ""; + this.receiverUsername = options.receiverUsername || ""; + this.gasPrice = options.gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE); + this.dataParts = options.dataParts; + this.chainID = options.chainID; + this.version = options.version || TRANSACTION_VERSION_DEFAULT; + this.options = options.options || TRANSACTION_OPTIONS_DEFAULT; + this.guardian = options.guardian || ""; + this.providedGasLimit = new BigNumber(options.gasLimit); + this.addDataMovementGas = options.addDataMovementGas; + this.amount = options.amount; + } + + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); + return gasLimit; + } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + build(): TransactionNext { + const data = this.buildTransactionPayload() + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + nonce: this.nonce || 0, + value: this.amount || 0, + sender: this.sender.bech32(), + receiver: this.receiver.bech32(), + senderUsername: this.senderUsername || "", + receiverUsername: this.receiverUsername || "", + gasPrice: this.gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE), + gasLimit: gasLimit, + data: data.valueOf(), + chainID: this.chainID, + version: this.version || TRANSACTION_VERSION_DEFAULT, + options: this.options || TRANSACTION_OPTIONS_DEFAULT, + guardian: this.guardian || "" + }) + } +} From 732ddde020ba5d35ced230299e06675e6671807b Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Wed, 7 Feb 2024 14:27:01 +0200 Subject: [PATCH 080/275] refactoring draftTransaction to TransactionNext --- .../delegationTransactionsFactory.ts | 32 +++++---- .../draftTransactionBuilder.ts | 66 ------------------- .../transactionNextBuilder.ts | 45 ++----------- 3 files changed, 22 insertions(+), 121 deletions(-) delete mode 100644 src/transactionsFactories/draftTransactionBuilder.ts diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index e0a00e069..6042423bb 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -26,11 +26,9 @@ interface IValidatorPublicKey { export class DelegationTransactionsFactory { private readonly config: Config; - private readonly chainID: Config; - constructor(config: Config, chainID: Config) { + constructor(config: Config) { this.config = config; - this.chainID = chainID; } createTransactionForNewDelegationContract(options: { @@ -54,7 +52,7 @@ export class DelegationTransactionsFactory { dataParts: dataParts, gasLimit: executionGasLimit, addDataMovementGas: true, - chainID: this.chainID.toString(), + chainID: this.config.chainID, amount: options.amount }).build(); } @@ -81,7 +79,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -105,7 +103,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -133,7 +131,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -161,7 +159,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -189,7 +187,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -213,7 +211,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -234,7 +232,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -255,7 +253,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -275,7 +273,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -295,7 +293,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -315,7 +313,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -335,7 +333,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -360,7 +358,7 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.chainID.toString(), + chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); diff --git a/src/transactionsFactories/draftTransactionBuilder.ts b/src/transactionsFactories/draftTransactionBuilder.ts deleted file mode 100644 index 99d57c5a1..000000000 --- a/src/transactionsFactories/draftTransactionBuilder.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { BigNumber } from "bignumber.js"; -import { IAddress, ITransactionPayload } from "../interface"; -import { ARGUMENTS_SEPARATOR } from "../constants"; -import { TransactionPayload } from "../transactionPayload"; -import { DraftTransaction } from "../draftTransaction"; - -interface Config { - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; -} - -export class DraftTransactionBuilder { - private config: Config; - private sender: IAddress; - private receiver: IAddress; - private dataParts: string[]; - private providedGasLimit: BigNumber; - private addDataMovementGas: boolean; - private amount?: BigNumber.Value; - - constructor(options: { - config: Config, - sender: IAddress, - receiver: IAddress, - dataParts: string[], - gasLimit: BigNumber.Value, - addDataMovementGas: boolean, - amount?: BigNumber.Value - }) { - this.config = options.config; - this.sender = options.sender; - this.receiver = options.receiver; - this.dataParts = options.dataParts; - this.providedGasLimit = new BigNumber(options.gasLimit); - this.addDataMovementGas = options.addDataMovementGas; - this.amount = options.amount; - } - - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { - if (!this.addDataMovementGas) { - return this.providedGasLimit; - } - - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); - return gasLimit; - } - - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } - - build(): DraftTransaction { - const data = this.buildTransactionPayload() - const gasLimit = this.computeGasLimit(data); - - return new DraftTransaction({ - sender: this.sender.bech32(), - receiver: this.receiver.bech32(), - gasLimit: gasLimit, - value: this.amount || 0, - data: data.valueOf() - }) - } -} diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index 10f46afca..a0b359a1e 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -1,6 +1,6 @@ import { BigNumber } from "bignumber.js"; import { IAddress, ITransactionPayload } from "../interface"; -import { ARGUMENTS_SEPARATOR, TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "../constants"; +import { ARGUMENTS_SEPARATOR } from "../constants"; import { TransactionPayload } from "../transactionPayload"; import { TransactionNext } from "../transaction"; @@ -17,50 +17,26 @@ export class TransactionNextBuilder { private providedGasLimit: BigNumber; private addDataMovementGas: boolean; private amount?: BigNumber.Value; - private nonce?: BigNumber.Value; - private value?: BigNumber.Value; - private senderUsername?: string; - private receiverUsername?: string; - private gasPrice?: BigNumber.Value; private chainID: string; - private version?: number; - private options?: number; - private guardian?: string; constructor(options: { config: Config, - nonce?: BigNumber.Value; - value?: BigNumber.Value; sender: IAddress, receiver: IAddress, - senderUsername?: string; - receiverUsername?: string; - gasPrice?: BigNumber.Value; - gasLimit: BigNumber.Value, dataParts: string[], - chainID: string; - version?: number; - options?: number; - guardian?: string; + gasLimit: BigNumber.Value, addDataMovementGas: boolean, - amount?: BigNumber.Value + amount?: BigNumber.Value, + chainID: string; }) { this.config = options.config; - this.nonce = options.nonce; - this.value = options.value || new BigNumber(0);; this.sender = options.sender; this.receiver = options.receiver; - this.senderUsername = options.senderUsername || ""; - this.receiverUsername = options.receiverUsername || ""; - this.gasPrice = options.gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE); this.dataParts = options.dataParts; - this.chainID = options.chainID; - this.version = options.version || TRANSACTION_VERSION_DEFAULT; - this.options = options.options || TRANSACTION_OPTIONS_DEFAULT; - this.guardian = options.guardian || ""; this.providedGasLimit = new BigNumber(options.gasLimit); this.addDataMovementGas = options.addDataMovementGas; this.amount = options.amount; + this.chainID = options.chainID; } private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { @@ -83,19 +59,12 @@ export class TransactionNextBuilder { const gasLimit = this.computeGasLimit(data); return new TransactionNext({ - nonce: this.nonce || 0, - value: this.amount || 0, sender: this.sender.bech32(), receiver: this.receiver.bech32(), - senderUsername: this.senderUsername || "", - receiverUsername: this.receiverUsername || "", - gasPrice: this.gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE), gasLimit: gasLimit, + value: this.amount || 0, data: data.valueOf(), - chainID: this.chainID, - version: this.version || TRANSACTION_VERSION_DEFAULT, - options: this.options || TRANSACTION_OPTIONS_DEFAULT, - guardian: this.guardian || "" + chainID: this.chainID }) } } From 15d216e082a41c0c25786296e81c5bcaf6c212ee Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Wed, 7 Feb 2024 15:08:31 +0200 Subject: [PATCH 081/275] refactoring all --- .../delegationTransactionsFactory.ts | 14 --- .../smartContractTransactionsFactory.ts | 16 ++-- .../tokenManagementTransactionsFactory.ts | 96 ++++++++++--------- .../transactionNextBuilder.ts | 6 +- .../transferTransactionsFactory.ts | 16 ++-- 5 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 6042423bb..23e1cde8e 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -52,7 +52,6 @@ export class DelegationTransactionsFactory { dataParts: dataParts, gasLimit: executionGasLimit, addDataMovementGas: true, - chainID: this.config.chainID, amount: options.amount }).build(); } @@ -79,7 +78,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -103,7 +101,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -131,7 +128,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -159,7 +155,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -187,7 +182,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: executionGasLimit, addDataMovementGas: true }).build(); @@ -211,7 +205,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), addDataMovementGas: true }).build(); @@ -232,7 +225,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -253,7 +245,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -273,7 +264,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -293,7 +283,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -313,7 +302,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -333,7 +321,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); @@ -358,7 +345,6 @@ export class DelegationTransactionsFactory { sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - chainID: this.config.chainID, gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), addDataMovementGas: true }).build(); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 143913adf..5f0e98be5 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -1,15 +1,15 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; -import { DraftTransaction } from "../draftTransaction"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; -import { DraftTransactionBuilder } from "./draftTransactionBuilder"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; +import { TransactionNext } from "../transaction"; interface Config { chainID: string; @@ -50,7 +50,7 @@ export class SmartContractTransactionsFactory { isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; - }): DraftTransaction { + }): TransactionNext { const nativeTransferAmount = options.nativeTransferAmount ?? 0; const isUpgradeable = options.isUpgradeable ?? true; @@ -66,7 +66,7 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), @@ -85,7 +85,7 @@ export class SmartContractTransactionsFactory { args?: any[]; nativeTransferAmount?: BigNumber.Value; tokenTransfers?: NextTokenTransfer[]; - }): DraftTransaction { + }): TransactionNext { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; const nativeTransferAmount = options.nativeTransferAmount ?? 0; @@ -115,7 +115,7 @@ export class SmartContractTransactionsFactory { dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: receiver, @@ -137,7 +137,7 @@ export class SmartContractTransactionsFactory { isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; - }): DraftTransaction { + }): TransactionNext { const nativeTransferAmount = options.nativeTransferAmount ?? 0; const isUpgradeable = options.isUpgradeable ?? true; @@ -153,7 +153,7 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.contract, diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index d4580b721..0820cf30e 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,11 +1,11 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; -import { DraftTransaction } from "../draftTransaction"; import { IAddress } from "../interface"; import { Logger } from "../logger"; import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { DraftTransactionBuilder } from "./draftTransactionBuilder"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; +import { TransactionNext } from "../transaction"; interface Config { chainID: string; @@ -52,7 +52,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): DraftTransaction { + }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -75,7 +75,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -97,7 +97,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): DraftTransaction { + }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -120,7 +120,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -142,7 +142,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): DraftTransaction { + }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -165,7 +165,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -188,7 +188,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): DraftTransaction { + }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -212,7 +212,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -229,7 +229,7 @@ export class TokenManagementTransactionsFactory { tokenTicker: string; tokenType: RegisterAndSetAllRolesTokenType; numDecimals: BigNumber.Value; - }): DraftTransaction { + }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -240,7 +240,7 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.numDecimals), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -254,10 +254,10 @@ export class TokenManagementTransactionsFactory { createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -270,10 +270,10 @@ export class TokenManagementTransactionsFactory { createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -289,7 +289,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; addRoleLocalMint: boolean; addRoleLocalBurn: boolean; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -298,7 +298,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -316,7 +316,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -327,7 +327,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -345,7 +345,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): DraftTransaction { + }): TransactionNext { return this.createTransactionForSettingSpecialRoleOnSemiFungibleToken(options); } @@ -358,7 +358,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTUpdateAttributes: boolean; addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -370,7 +370,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -389,7 +389,7 @@ export class TokenManagementTransactionsFactory { hash: string; attributes: Uint8Array; uris: string[]; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), @@ -405,7 +405,7 @@ export class TokenManagementTransactionsFactory { const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -415,10 +415,13 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): DraftTransaction { + createTransactionForPausing(options: { + sender: IAddress; + tokenIdentifier: string + }): TransactionNext { const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -428,10 +431,13 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): DraftTransaction { + createTransactionForUnpausing(options: { + sender: IAddress; + tokenIdentifier: string + }): TransactionNext { const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -445,10 +451,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -462,10 +468,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -479,10 +485,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -496,10 +502,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; supplyToMint: BigNumber.Value; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -513,10 +519,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; supplyToBurn: BigNumber.Value; - }): DraftTransaction { + }): TransactionNext { const dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -531,7 +537,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: BigNumber.Value; attributes: Uint8Array; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), @@ -539,7 +545,7 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -554,7 +560,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), @@ -562,7 +568,7 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.quantityToAdd), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -577,7 +583,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value; - }): DraftTransaction { + }): TransactionNext { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), @@ -585,7 +591,7 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.quantityToBurn), ]; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index a0b359a1e..3861f9fc1 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -5,6 +5,7 @@ import { TransactionPayload } from "../transactionPayload"; import { TransactionNext } from "../transaction"; interface Config { + chainID: string; minGasLimit: BigNumber.Value; gasLimitPerByte: BigNumber.Value; } @@ -17,7 +18,6 @@ export class TransactionNextBuilder { private providedGasLimit: BigNumber; private addDataMovementGas: boolean; private amount?: BigNumber.Value; - private chainID: string; constructor(options: { config: Config, @@ -27,7 +27,6 @@ export class TransactionNextBuilder { gasLimit: BigNumber.Value, addDataMovementGas: boolean, amount?: BigNumber.Value, - chainID: string; }) { this.config = options.config; this.sender = options.sender; @@ -36,7 +35,6 @@ export class TransactionNextBuilder { this.providedGasLimit = new BigNumber(options.gasLimit); this.addDataMovementGas = options.addDataMovementGas; this.amount = options.amount; - this.chainID = options.chainID; } private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { @@ -64,7 +62,7 @@ export class TransactionNextBuilder { gasLimit: gasLimit, value: this.amount || 0, data: data.valueOf(), - chainID: this.chainID + chainID: this.config.toString() }) } } diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 3f52930ba..b5290436e 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,10 +1,10 @@ import BigNumber from "bignumber.js"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { IAddress } from "../interface"; -import { DraftTransaction } from "../draftTransaction"; -import { DraftTransactionBuilder } from "./draftTransactionBuilder"; import { NextTokenTransfer, Token } from "../tokens"; import { ErrBadUsage } from "../errors"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; +import { TransactionNext } from "../transaction"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -38,9 +38,9 @@ export class NextTransferTransactionsFactory { receiver: IAddress; nativeAmount: BigNumber.Value; data?: string; - }): DraftTransaction { + }): TransactionNext { const data = options.data || ""; - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.receiver, @@ -55,7 +55,7 @@ export class NextTransferTransactionsFactory { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; - }): DraftTransaction { + }): TransactionNext { const numberOfTransfers = options.tokenTransfers.length; if (numberOfTransfers === 0) { @@ -75,7 +75,7 @@ export class NextTransferTransactionsFactory { .multipliedBy(new BigNumber(numberOfTransfers)) .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -89,7 +89,7 @@ export class NextTransferTransactionsFactory { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; - }): DraftTransaction { + }): TransactionNext { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; let extraGasForTransfer = new BigNumber(0); @@ -108,7 +108,7 @@ export class NextTransferTransactionsFactory { receiver = options.sender; } - return new DraftTransactionBuilder({ + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: receiver, From 0e8a0eebdf7043f9d658a3f58aca413343aab302 Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Wed, 7 Feb 2024 16:37:54 +0200 Subject: [PATCH 082/275] Removed transactionNextBuilder --- .../smartContractTransactionsFactory.ts | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 5f0e98be5..d85f58602 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -2,14 +2,14 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; +import { ARGUMENTS_SEPARATOR, CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; import { Address } from "../address"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionNext } from "../transaction"; +import { TransactionPayload } from "../transactionPayload"; interface Config { chainID: string; @@ -32,6 +32,7 @@ export class SmartContractTransactionsFactory { private readonly abiRegistry?: Abi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; + private dataParts!: string[]; constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { this.config = config; @@ -52,29 +53,26 @@ export class SmartContractTransactionsFactory { isPayableBySmartContract?: boolean; }): TransactionNext { const nativeTransferAmount = options.nativeTransferAmount ?? 0; - const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; const isPayableBySmartContract = options.isPayableBySmartContract ?? true; - const args = options.args || []; - const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); - parts = parts.concat(preparedArgs); + this.dataParts = parts.concat(preparedArgs); - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), - dataParts: parts, + const data = this.buildTransactionPayload() + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + data: data.valueOf(), gasLimit: options.gasLimit, - addDataMovementGas: false, - amount: nativeTransferAmount, - }).build(); + value: nativeTransferAmount, + chainID: this.config.chainID + }); } createTransactionForExecute(options: { @@ -113,17 +111,17 @@ export class SmartContractTransactionsFactory { } dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); - dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); + this.dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); + const data = this.buildTransactionPayload() - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: receiver, - dataParts: dataParts, + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + data: data.valueOf(), gasLimit: options.gasLimit, - addDataMovementGas: false, - amount: nativeTransferAmount, - }).build(); + value: nativeTransferAmount, + chainID: this.config.chainID + }); } createTransactionForUpgrade(options: { @@ -152,16 +150,18 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); + this.dataParts = parts.concat(preparedArgs); + + const data = this.buildTransactionPayload() - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.contract, - dataParts: parts, + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + data: data.valueOf(), gasLimit: options.gasLimit, - addDataMovementGas: false, - amount: nativeTransferAmount, - }).build(); + value: nativeTransferAmount, + chainID: this.config.chainID + }); } private argsToDataParts(args: any[], endpoint?: EndpointDefinition): string[] { @@ -185,4 +185,9 @@ export class SmartContractTransactionsFactory { } return true; } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } } From 19f3ae520d4cd3e1c57195f903de4475ab529f2b Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Thu, 8 Feb 2024 16:24:05 +0200 Subject: [PATCH 083/275] refactoring + removed draft transactions + updated tests --- src/draftTransaction.ts | 23 - src/smartcontracts/smartContract.ts | 18 +- src/transaction.spec.ts | 22 - src/transaction.ts | 15 - .../delegationTransactionsFactory.spec.ts | 202 +++---- .../delegationTransactionsFactory.ts | 358 +++++++----- .../smartContractTransactionsFactory.spec.ts | 148 ++--- .../smartContractTransactionsFactory.ts | 12 +- ...anagementTransactionIntentsFactory.spec.ts | 86 +-- .../tokenManagementTransactionsFactory.ts | 517 ++++++++++-------- .../transactionNextBuilder.ts | 68 --- .../transferTransactionsFactory.spec.ts | 10 +- .../transferTransactionsFactory.ts | 100 ++-- 13 files changed, 812 insertions(+), 767 deletions(-) delete mode 100644 src/draftTransaction.ts delete mode 100644 src/transactionsFactories/transactionNextBuilder.ts diff --git a/src/draftTransaction.ts b/src/draftTransaction.ts deleted file mode 100644 index 25dcfc0d5..000000000 --- a/src/draftTransaction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { BigNumber } from "bignumber.js"; - -export class DraftTransaction { - public sender: string; - public receiver: string; - public gasLimit: BigNumber.Value; - public value: BigNumber.Value; - public data: Uint8Array; - - public constructor(options: { - sender: string, - receiver: string, - gasLimit: BigNumber.Value, - value?: BigNumber.Value, - data?: Uint8Array - }) { - this.sender = options.sender; - this.receiver = options.receiver; - this.gasLimit = options.gasLimit; - this.value = options.value ?? 0; - this.data = options.data ?? new Uint8Array(); - } -} diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index b70aaf480..788c9d541 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -118,7 +118,7 @@ export class SmartContract implements ISmartContract { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scDraftTransactionFactory = new SmartContractTransactionsFactory({ + const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -127,7 +127,7 @@ export class SmartContract implements ISmartContract { const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const draftTx = scDraftTransactionFactory.createTransactionForDeploy({ + const nextTx = scNextTransactionFactory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: gasLimit.valueOf(), @@ -138,7 +138,7 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }); - const transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -178,7 +178,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scDraftTransactionFactory = new SmartContractTransactionsFactory({ + const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -187,7 +187,7 @@ export class SmartContract implements ISmartContract { const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const draftTx = scDraftTransactionFactory.createTransactionForUpgrade({ + const nextTx = scNextTransactionFactory.createTransactionForUpgrade({ sender: caller, contract: this.getAddress(), bytecode: bytecode, @@ -199,7 +199,7 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }) - const transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -216,7 +216,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig(chainID.valueOf()); - const scDraftTransactionFactory = new SmartContractTransactionsFactory({ + const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -225,7 +225,7 @@ export class SmartContract implements ISmartContract { args = args || []; value = value || 0; - const draftTx = scDraftTransactionFactory.createTransactionForExecute({ + const nextTx = scNextTransactionFactory.createTransactionForExecute({ sender: caller, contract: receiver ? receiver : this.getAddress(), functionName: func.toString(), @@ -233,7 +233,7 @@ export class SmartContract implements ISmartContract { args: args }) - const transaction = Transaction.fromDraft(draftTx); + const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 161bb7132..988c8f418 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -6,7 +6,6 @@ import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; import { Transaction, TransactionNext } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; -import { DraftTransaction } from "./draftTransaction"; import { TRANSACTION_MIN_GAS_PRICE } from "./constants"; @@ -19,27 +18,6 @@ describe("test transaction construction", async () => { wallets = await loadTestWallets(); }); - it("create transaction from draft transaction", async () => { - const draftTransaction = new DraftTransaction({ - sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - gasLimit: 56000, - value: "1000000000000000000", - data: Buffer.from("test") - }); - - const transaction = Transaction.fromDraft(draftTransaction); - assert.deepEqual(transaction.getSender(), Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")); - assert.deepEqual(transaction.getReceiver(), Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx")); - assert.equal(transaction.getGasLimit().valueOf(), 56000); - assert.equal(transaction.getValue().toString(), "1000000000000000000"); - assert.equal(transaction.getData().toString(), "test"); - assert.equal(transaction.getChainID().valueOf(), ""); - assert.equal(transaction.getNonce().valueOf(), 0); - assert.equal(transaction.getGasPrice().valueOf(), TRANSACTION_MIN_GAS_PRICE); - assert.deepEqual(transaction.getSignature(), Buffer.from([])); - }); - it("create transaction from transaction next", async () => { const plainTransactionNextObject = { sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", diff --git a/src/transaction.ts b/src/transaction.ts index 019cab3b0..9518e31aa 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -2,7 +2,6 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { Compatibility } from "./compatibility"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; -import { DraftTransaction } from "./draftTransaction"; import * as errors from "./errors"; import { Hash } from "./hash"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; @@ -422,20 +421,6 @@ export class Transaction { return feeForMove.plus(processingFee); } - /** - * Creates a new Transaction object from a DraftTransaction. - */ - static fromDraft(draft: DraftTransaction): Transaction { - return new Transaction({ - sender: Address.fromBech32(draft.sender), - receiver: Address.fromBech32(draft.receiver), - gasLimit: new BigNumber(draft.gasLimit).toNumber(), - chainID: "", - value: draft.value, - data: new TransactionPayload(Buffer.from(draft.data)) - }) - } - /** * Creates a new Transaction object from a TransactionNext object. */ diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index c45faa798..7e62bdc76 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -10,28 +10,28 @@ describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig("D"); const delegationFactory = new DelegationTransactionsFactory(config); - it("should create draft transaction for new delegation contract", async function () { + it("should create next transaction for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delagationCap = "5000000000000000000000"; const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); - const draft = delegationFactory.createTransactionForNewDelegationContract({ + const next = delegationFactory.createTransactionForNewDelegationContract({ sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, amount: value }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, DELEGATION_MANAGER_SC_ADDRESS); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); - assert.equal(draft.gasLimit.valueOf(), 60126500); - assert.equal(draft.value, value); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, DELEGATION_MANAGER_SC_ADDRESS); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); + assert.equal(next.gasLimit.valueOf(), 60126500); + assert.equal(next.value, value); }); - it("should create draft transaction for adding nodes", async function () { + it("should create next transaction for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); @@ -40,21 +40,21 @@ describe("test delegation transactions factory", function () { getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") } - const draft = delegationFactory.createTransactionForAddingNodes({ + const next = delegationFactory.createTransactionForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], signedMessages: [mockMessage.getSignature()] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); + assert.equal(next.value, 0); }); - it("should create draft transaction for removing nodes", async function () { + it("should create next transaction for removing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -64,20 +64,20 @@ describe("test delegation transactions factory", function () { } }; - const draft = delegationFactory.createTransactionForRemovingNodes({ + const next = delegationFactory.createTransactionForRemovingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("removeNodes@61626261")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("removeNodes@61626261")); + assert.equal(next.value, 0); }); - it("should create draft transaction for staking nodes", async function () { + it("should create next transaction for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -87,20 +87,20 @@ describe("test delegation transactions factory", function () { } }; - const draft = delegationFactory.createTransactionForStakingNodes({ + const next = delegationFactory.createTransactionForStakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("stakeNodes@61626261")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("stakeNodes@61626261")); + assert.equal(next.value, 0); }); - it("should create draft transaction for unbonding nodes", async function () { + it("should create next transaction for unbonding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -110,21 +110,21 @@ describe("test delegation transactions factory", function () { } }; - const draft = delegationFactory.createTransactionForUnbondingNodes({ + const next = delegationFactory.createTransactionForUnbondingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("unBondNodes@61626261")); - assert.equal(draft.value, 0); - assert.equal(draft.gasLimit.valueOf(), 12080000); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("unBondNodes@61626261")); + assert.equal(next.value, 0); + assert.equal(next.gasLimit.valueOf(), 12080000); }); - it("should create draft transaction for unstaking nodes", async function () { + it("should create next transaction for unstaking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -134,21 +134,21 @@ describe("test delegation transactions factory", function () { } }; - const draft = delegationFactory.createTransactionForUnstakingNodes({ + const next = delegationFactory.createTransactionForUnstakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("unStakeNodes@61626261")); - assert.equal(draft.value, 0); - assert.equal(draft.gasLimit.valueOf(), 12081500); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("unStakeNodes@61626261")); + assert.equal(next.value, 0); + assert.equal(next.gasLimit.valueOf(), 12081500); }); - it("should create draft transaction for unjailing nodes", async function () { + it("should create next transaction for unjailing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -158,124 +158,124 @@ describe("test delegation transactions factory", function () { } }; - const draft = delegationFactory.createTransactionForUnjailingNodes({ + const next = delegationFactory.createTransactionForUnjailingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("unJailNodes@61626261")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("unJailNodes@61626261")); + assert.equal(next.value, 0); }); - it("should create draft transaction for changing service fee", async function () { + it("should create next transaction for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const draft = delegationFactory.createTransactionForChangingServiceFee({ + const next = delegationFactory.createTransactionForChangingServiceFee({ sender: sender, delegationContract: delegationContract, serviceFee: serviceFee }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("changeServiceFee@0a")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("changeServiceFee@0a")); + assert.equal(next.value, 0); }); - it("should create draft transaction for changing delegation cap", async function () { + it("should create next transaction for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const draft = delegationFactory.createTransactionForModifyingDelegationCap({ + const next = delegationFactory.createTransactionForModifyingDelegationCap({ sender: sender, delegationContract: delegationContract, delegationCap: delegationCap }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); + assert.equal(next.value, 0); }); - it("should create draft transaction for setting automatic activation", async function () { + it("should create next transaction for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const draft = delegationFactory.createTransactionForSettingAutomaticActivation({ + const next = delegationFactory.createTransactionForSettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("setAutomaticActivation@74727565")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("setAutomaticActivation@74727565")); + assert.equal(next.value, 0); }); - it("should create draft transaction for unsetting automatic activation", async function () { + it("should create next transaction for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const draft = delegationFactory.createTransactionForUnsettingAutomaticActivation({ + const next = delegationFactory.createTransactionForUnsettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("setAutomaticActivation@66616c7365")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("setAutomaticActivation@66616c7365")); + assert.equal(next.value, 0); }); - it("should create draft transaction for setting cap check on redelegate rewards", async function () { + it("should create next transaction for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const draft = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ + const next = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); + assert.equal(next.value, 0); }); - it("should create draft transaction for unsetting cap check on redelegate rewards", async function () { + it("should create next transaction for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const draft = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ + const next = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); + assert.equal(next.value, 0); }); - it("should create draft transaction for setting metadata", async function () { + it("should create next transaction for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const draft = delegationFactory.createTransactionForSettingMetadata({ + const next = delegationFactory.createTransactionForSettingMetadata({ sender: sender, delegationContract: delegationContract, name: "name", @@ -283,10 +283,10 @@ describe("test delegation transactions factory", function () { identifier: "identifier" }); - assert.equal(draft.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(draft.data); - assert.deepEqual(draft.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); - assert.equal(draft.value, 0); + assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(next.data); + assert.deepEqual(next.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); + assert.equal(next.value, 0); }); }); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 23e1cde8e..0528333f3 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,11 +1,11 @@ -import { IAddress } from "../interface"; +import { IAddress, ITransactionPayload } from "../interface"; import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Address } from "../address"; -import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; +import { ARGUMENTS_SEPARATOR, DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; import { TransactionNext } from "../transaction"; +import { TransactionPayload } from "../transactionPayload"; interface Config { chainID: string; @@ -26,6 +26,9 @@ interface IValidatorPublicKey { export class DelegationTransactionsFactory { private readonly config: Config; + private dataParts!: string[]; + private addDataMovementGas!: boolean; + private providedGasLimit!: BigNumber; constructor(config: Config) { this.config = config; @@ -37,23 +40,26 @@ export class DelegationTransactionsFactory { serviceFee: BigNumber.Value, amount: BigNumber.Value }): TransactionNext { - const dataParts = [ + this.dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), numberToPaddedHex(options.serviceFee.toString()) ]; - const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), - dataParts: dataParts, - gasLimit: executionGasLimit, - addDataMovementGas: true, - amount: options.amount - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: options.amount, + chainID: this.config.chainID + }); } createTransactionForAddingNodes(options: { @@ -68,19 +74,22 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; - const dataParts = ["addNodes"]; + this.dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); + this.dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForRemovingNodes(options: { @@ -88,22 +97,25 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - const dataParts = ["removeNodes"]; + this.dataParts = ["removeNodes"]; for (const key of options.publicKeys) { - dataParts.push(key.hex()); + this.dataParts.push(key.hex()); } + const data = this.buildTransactionPayload(); const numNodes = options.publicKeys.length; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true - }).build(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForStakingNodes(options: { @@ -111,26 +123,28 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts = ["stakeNodes"]; + this.dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + this.dataParts = this.dataParts.concat(key.hex()); } + const data = this.buildTransactionPayload(); const numNodes = options.publicKeys.length; const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); - const executionGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( + this.addDataMovementGas = true; + this.providedGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( this.config.gasLimitDelegationOperations ); - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: executionGasLimit, - addDataMovementGas: true - }).build(); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnbondingNodes(options: { @@ -138,26 +152,28 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts = ["unBondNodes"]; + this.dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + this.dataParts = this.dataParts.concat(key.hex()); } + const data = this.buildTransactionPayload(); const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes).multipliedBy( + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: executionGasLimit, - addDataMovementGas: true - }).build(); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnstakingNodes(options: { @@ -165,26 +181,28 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts = ["unStakeNodes"]; + this.dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + this.dataParts = this.dataParts.concat(key.hex()); } + const data = this.buildTransactionPayload(); const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes).multipliedBy( + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: executionGasLimit, - addDataMovementGas: true - }).build(); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnjailingNodes(options: { @@ -192,22 +210,25 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - const dataParts = ["unJailNodes"]; + this.dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { - dataParts.push(key.hex()); + this.dataParts.push(key.hex()); } const numNodes = options.publicKeys.length; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForChangingServiceFee(options: { @@ -215,19 +236,23 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, serviceFee: BigNumber.Value }): TransactionNext { - const dataParts = [ + this.dataParts = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForModifyingDelegationCap(options: { @@ -235,95 +260,115 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, delegationCap: BigNumber.Value }): TransactionNext { - const dataParts = [ + this.dataParts = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setAutomaticActivation", utf8ToHex("true") ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setAutomaticActivation", utf8ToHex("false") ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingMetadata(options: { @@ -333,25 +378,44 @@ export class DelegationTransactionsFactory { website: string, identifier: string }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setMetaData", utf8ToHex(options.name), utf8ToHex(options.website), utf8ToHex(options.identifier) ]; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.delegationContract, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.delegationContract.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); + return gasLimit; + } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 67777156b..e22418362 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -52,48 +52,48 @@ describe("test smart contract transactions factory", function () { ); }); - it("should create draft transaction for deploy", async function () { + it("should create next transaction for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployDraft = factory.createTransactionForDeploy({ + const deployNext = factory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args, }); - const abiDeployDraft = abiAwareFactory.createTransactionForDeploy({ + const abiDeployNext = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args, }); - assert.equal(deployDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(deployDraft.receiver, CONTRACT_DEPLOY_ADDRESS); - expect(deployDraft.data.length).to.be.greaterThan(0); - assert.equal(deployDraft.gasLimit.valueOf(), gasLimit); - assert.equal(deployDraft.value, 0); + assert.equal(deployNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(deployNext.receiver, CONTRACT_DEPLOY_ADDRESS); + expect(deployNext.data.length).to.be.greaterThan(0); + assert.equal(deployNext.gasLimit.valueOf(), gasLimit); + assert.equal(deployNext.value, 0); - assert.deepEqual(deployDraft, abiDeployDraft); + assert.deepEqual(deployNext, abiDeployNext); }); - it("should create draft transaction for execute without transfer", async function () { + it("should create next transaction for execute without transfer", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; const gasLimit = 6000000; const args = [new U32Value(7)]; - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, gasLimit: gasLimit, args: args, }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -101,23 +101,23 @@ describe("test smart contract transactions factory", function () { args: args, }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value, 0); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(executeNext.data, Buffer.from("add@07")); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value, 0); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for execute and transfer native token", async function () { + it("should create next transaction for execute and transfer native token", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; const gasLimit = 6000000; const egldAmount = new BigNumber("1000000000000000000"); - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -125,7 +125,7 @@ describe("test smart contract transactions factory", function () { args: [new U32Value(7)], nativeTransferAmount: egldAmount, }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -134,16 +134,16 @@ describe("test smart contract transactions factory", function () { nativeTransferAmount: egldAmount, }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeDraft.data, Buffer.from("add@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value.valueOf(), "1000000000000000000"); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(executeNext.data, Buffer.from("add@07")); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value.valueOf(), "1000000000000000000"); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for execute and transfer single esdt", async function () { + it("should create next transaction for execute and transfer single esdt", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -152,7 +152,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("FOO-6ce17b", 0); const transfer = new NextTokenTransfer(token, 10); - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -160,7 +160,7 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [transfer], }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -169,16 +169,16 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [transfer], }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeDraft.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value.valueOf(), "0"); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(executeNext.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value.valueOf(), "0"); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for execute and transfer multiple esdts", async function () { + it("should create next transaction for execute and transfer multiple esdts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); const func = "add"; @@ -190,7 +190,7 @@ describe("test smart contract transactions factory", function () { const barToken = new Token("BAR-5bc08f", 0); const barTransfer = new NextTokenTransfer(barToken, 3140); - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -198,7 +198,7 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [fooTransfer, barTransfer], }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -207,23 +207,23 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [fooTransfer, barTransfer], }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.deepEqual( - executeDraft.data, + executeNext.data, Buffer.from( "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07" ) ); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value.valueOf(), "0"); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value.valueOf(), "0"); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for execute and transfer single nft", async function () { + it("should create next transaction for execute and transfer single nft", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -233,7 +233,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("NFT-123456", 1); const transfer = new NextTokenTransfer(token, 1); - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -241,7 +241,7 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [transfer], }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -250,24 +250,24 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [transfer], }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.isDefined(executeDraft.data); + assert.isDefined(executeNext.data); assert.deepEqual( - executeDraft.data, + executeNext.data, Buffer.from( "ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07" ) ); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value.valueOf(), "0"); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value.valueOf(), "0"); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for execute and transfer multiple nfts", async function () { + it("should create next transaction for execute and transfer multiple nfts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -279,7 +279,7 @@ describe("test smart contract transactions factory", function () { const secondToken = new Token("NFT-123456", 42); const secondTransfer = new NextTokenTransfer(secondToken, 1); - const executeDraft = factory.createTransactionForExecute({ + const executeNext = factory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -287,7 +287,7 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [firstTransfer, secondTransfer], }); - const abiExecuteDraft = abiAwareFactory.createTransactionForExecute({ + const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -296,30 +296,30 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [firstTransfer, secondTransfer], }); - assert.equal(executeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeDraft.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.isDefined(executeDraft.data); + assert.isDefined(executeNext.data); assert.deepEqual( - executeDraft.data, + executeNext.data, Buffer.from( "MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07" ) ); - assert.equal(executeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(executeDraft.value.valueOf(), "0"); + assert.equal(executeNext.gasLimit.valueOf(), gasLimit); + assert.equal(executeNext.value.valueOf(), "0"); - assert.deepEqual(executeDraft, abiExecuteDraft); + assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create draft transaction for upgrade", async function () { + it("should create next transaction for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000; const args = [new U32Value(0)]; - const upgradeDraft = factory.createTransactionForUpgrade({ + const upgradeNext = factory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -327,7 +327,7 @@ describe("test smart contract transactions factory", function () { args: args, }); - const abiUpgradeDraft = abiAwareFactory.createTransactionForUpgrade({ + const abiUpgradeNext = abiAwareFactory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -335,12 +335,12 @@ describe("test smart contract transactions factory", function () { args: args, }); - assert.equal(upgradeDraft.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(upgradeDraft.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isTrue(Buffer.from(upgradeDraft.data!).toString().startsWith("upgradeContract@")); - assert.equal(upgradeDraft.gasLimit.valueOf(), gasLimit); - assert.equal(upgradeDraft.value, 0); + assert.equal(upgradeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(upgradeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.isTrue(Buffer.from(upgradeNext.data!).toString().startsWith("upgradeContract@")); + assert.equal(upgradeNext.gasLimit.valueOf(), gasLimit); + assert.equal(upgradeNext.value, 0); - assert.deepEqual(upgradeDraft, abiUpgradeDraft); + assert.deepEqual(upgradeNext, abiUpgradeNext); }); }); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d85f58602..d8d1e8d30 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -62,8 +62,7 @@ export class SmartContractTransactionsFactory { let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); this.dataParts = parts.concat(preparedArgs); - - const data = this.buildTransactionPayload() + const data = this.buildTransactionPayload(); return new TransactionNext({ sender: options.sender.bech32(), @@ -112,11 +111,11 @@ export class SmartContractTransactionsFactory { dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); this.dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); - const data = this.buildTransactionPayload() + const data = this.buildTransactionPayload(); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + receiver: receiver.bech32(), data: data.valueOf(), gasLimit: options.gasLimit, value: nativeTransferAmount, @@ -151,12 +150,11 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); this.dataParts = parts.concat(preparedArgs); - - const data = this.buildTransactionPayload() + const data = this.buildTransactionPayload(); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + receiver: options.contract.bech32(), data: data.valueOf(), gasLimit: options.gasLimit, value: nativeTransferAmount, diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index bdd6ffcb1..3694b7683 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -16,8 +16,8 @@ describe("test token management transactions factory", () => { factory = new TokenManagementTransactionsFactory(config); }); - it("should create draft transaction for registering and setting roles", () => { - const draft = factory.createTransactionForRegisteringAndSettingRoles({ + it("should create next transaction for registering and setting roles", () => { + const next = factory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", tokenTicker: "TEST", @@ -25,15 +25,15 @@ describe("test token management transactions factory", () => { numDecimals: 2 }); - assert.deepEqual(draft.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); - assert.deepEqual(draft.value, config.issueCost); - assert.deepEqual(draft.gasLimit, new BigNumber("60125000")); + assert.deepEqual(next.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); + assert.deepEqual(next.value, config.issueCost); + assert.deepEqual(next.gasLimit, new BigNumber("60125000")); }); - it("should create draft transaction for issuing fungible token", () => { - const draft = factory.createTransactionForIssuingFungible({ + it("should create next transaction for issuing fungible token", () => { + const next = factory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -47,14 +47,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(draft.value, config.issueCost); + assert.deepEqual(next.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(next.value, config.issueCost); }); - it("should create draft transaction for issuing semi-fungible token", () => { - const draft = factory.createTransactionForIssuingSemiFungible({ + it("should create next transaction for issuing semi-fungible token", () => { + const next = factory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -67,14 +67,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(draft.value, config.issueCost); + assert.deepEqual(next.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(next.value, config.issueCost); }); - it("should create draft transaction for issuing non-fungible token", () => { - const draft = factory.createTransactionForIssuingNonFungible({ + it("should create next transaction for issuing non-fungible token", () => { + const next = factory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -87,14 +87,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(draft.value, config.issueCost); + assert.deepEqual(next.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(next.value, config.issueCost); }); - it("should create draft transaction for registering metaEsdt", () => { - const draft = factory.createTransactionForRegisteringMetaESDT({ + it("should create next transaction for registering metaEsdt", () => { + const next = factory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -108,14 +108,14 @@ describe("test token management transactions factory", () => { canAddSpecialRoles: false }); - assert.deepEqual(draft.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(draft.value, config.issueCost); + assert.deepEqual(next.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(next.value, config.issueCost); }); - it("should create draft transaction for setting spcial role on non-fungible token", () => { - const draft = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ + it("should create next transaction for setting spcial role on non-fungible token", () => { + const next = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, tokenIdentifier: "FRANK-11ce3e", @@ -126,14 +126,14 @@ describe("test token management transactions factory", () => { addRoleESDTTransferRole: false }); - assert.deepEqual(draft.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); - assert.equal(draft.sender, frank.address.toString()); - assert.equal(draft.receiver, ESDT_CONTRACT_ADDRESS); - assert.equal(draft.value, 0); + assert.deepEqual(next.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); + assert.equal(next.sender, frank.address.toString()); + assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); + assert.equal(next.value, 0); }); - it("should create draft transaction for creating nft", () => { - const draft = factory.createTransactionForCreatingNFT({ + it("should create next transaction for creating nft", () => { + const next = factory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, @@ -144,9 +144,9 @@ describe("test token management transactions factory", () => { uris: ["a", "b"] }); - assert.deepEqual(draft.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); - assert.equal(draft.sender, grace.address.toString()); - assert.equal(draft.receiver, grace.address.toString()); - assert.equal(draft.value, 0); + assert.deepEqual(next.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); + assert.equal(next.sender, grace.address.toString()); + assert.equal(next.receiver, grace.address.toString()); + assert.equal(next.value, 0); }); }); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 0820cf30e..b8d219e81 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,11 +1,11 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; -import { ESDT_CONTRACT_ADDRESS } from "../constants"; -import { IAddress } from "../interface"; +import { ARGUMENTS_SEPARATOR, ESDT_CONTRACT_ADDRESS } from "../constants"; +import { IAddress, ITransactionPayload } from "../interface"; import { Logger } from "../logger"; import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; +import { TransactionPayload } from "../transactionPayload"; interface Config { chainID: string; @@ -33,6 +33,9 @@ export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly trueAsHex: string; private readonly falseAsHex: string; + private dataParts!: string[]; + private addDataMovementGas!: boolean; + private providedGasLimit!: BigNumber; constructor(config: Config) { this.config = config; @@ -55,7 +58,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ + this.dataParts = [ "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -74,16 +77,19 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitIssue, - addDataMovementGas: true, - amount: this.config.issueCost, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: this.config.issueCost, + chainID: this.config.chainID + }); } createTransactionForIssuingSemiFungible(options: { @@ -100,7 +106,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ + this.dataParts = [ "issueSemiFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -119,16 +125,19 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitIssue, - addDataMovementGas: true, - amount: this.config.issueCost, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: this.config.issueCost, + chainID: this.config.chainID + }); } createTransactionForIssuingNonFungible(options: { @@ -145,7 +154,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ + this.dataParts = [ "issueNonFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -164,16 +173,19 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitIssue, - addDataMovementGas: true, - amount: this.config.issueCost, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: this.config.issueCost, + chainID: this.config.chainID + }); } createTransactionForRegisteringMetaESDT(options: { @@ -191,7 +203,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ + this.dataParts = [ "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -211,16 +223,19 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitIssue, - addDataMovementGas: true, - amount: this.config.issueCost, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: this.config.issueCost, + chainID: this.config.chainID + }); } createTransactionForRegisteringAndSettingRoles(options: { @@ -232,55 +247,64 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ + this.dataParts = [ "registerAndSetAllRoles", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), bigIntToHex(options.numDecimals), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitIssue, - addDataMovementGas: true, - amount: this.config.issueCost, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: this.config.issueCost, + chainID: this.config.chainID + }); } createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitToggleBurnRoleGlobally, - addDataMovementGas: true, - }).build(); + this.dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitToggleBurnRoleGlobally, - addDataMovementGas: true, - }).build(); + this.dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingSpecialRoleOnFungibleToken(options: { @@ -290,22 +314,25 @@ export class TokenManagementTransactionsFactory { addRoleLocalMint: boolean; addRoleLocalBurn: boolean; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), ...(options.addRoleLocalMint ? [utf8ToHex("ESDTRoleLocalMint")] : []), ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingSpecialRoleOnSemiFungibleToken(options: { @@ -317,7 +344,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -326,15 +353,18 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddQuantity ? [utf8ToHex("ESDTRoleNFTAddQuantity")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForSettingSpecialRoleOnMetaESDT(options: { @@ -359,7 +389,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -369,15 +399,18 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddURI ? [utf8ToHex("ESDTRoleNFTAddURI")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), - dataParts: dataParts, - gasLimit: this.config.gasLimitSetSpecialRole, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForCreatingNFT(options: { @@ -390,7 +423,7 @@ export class TokenManagementTransactionsFactory { attributes: Uint8Array; uris: string[]; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.initialQuantity), @@ -400,51 +433,60 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ...options.uris.map(utf8ToHex), ]; + const data = this.buildTransactionPayload(); // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit), - addDataMovementGas: true, - }).build(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { - const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitPausing, - addDataMovementGas: true, - }).build(); + this.dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { - const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitPausing, - addDataMovementGas: true, - }).build(); + this.dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForFreezing(options: { @@ -452,16 +494,19 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitFreezing, - addDataMovementGas: true, - }).build(); + this.dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUnfreezing(options: { @@ -469,16 +514,19 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitFreezing, - addDataMovementGas: true, - }).build(); + this.dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForWiping(options: { @@ -486,16 +534,19 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitWiping, - addDataMovementGas: true, - }).build(); + this.dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitWiping); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForLocalMint(options: { @@ -503,16 +554,19 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToMint: BigNumber.Value; }): TransactionNext { - const dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitEsdtLocalMint, - addDataMovementGas: true, - }).build(); + this.dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtLocalMint); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForLocalBurning(options: { @@ -520,16 +574,19 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToBurn: BigNumber.Value; }): TransactionNext { - const dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitEsdtLocalBurn, - addDataMovementGas: true, - }).build(); + this.dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtLocalBurn); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForUpdatingAttributes(options: { @@ -538,21 +595,24 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; attributes: Uint8Array; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), byteArrayToHex(options.attributes), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitEsdtNftUpdateAttributes, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForAddingQuantity(options: { @@ -561,21 +621,24 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToAdd), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitEsdtNftAddQuantity, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } createTransactionForBurningQuantity(options: { @@ -584,21 +647,24 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value; }): TransactionNext { - const dataParts = [ + this.dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToBurn), ]; - - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: dataParts, - gasLimit: this.config.gasLimitEsdtNftBurn, - addDataMovementGas: true, - }).build(); + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftBurn); + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } private notifyAboutUnsettingBurnRoleGlobally() { @@ -609,4 +675,19 @@ IMPORTANT! You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); + return gasLimit; + } } diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts deleted file mode 100644 index 3861f9fc1..000000000 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { BigNumber } from "bignumber.js"; -import { IAddress, ITransactionPayload } from "../interface"; -import { ARGUMENTS_SEPARATOR } from "../constants"; -import { TransactionPayload } from "../transactionPayload"; -import { TransactionNext } from "../transaction"; - -interface Config { - chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; -} - -export class TransactionNextBuilder { - private config: Config; - private sender: IAddress; - private receiver: IAddress; - private dataParts: string[]; - private providedGasLimit: BigNumber; - private addDataMovementGas: boolean; - private amount?: BigNumber.Value; - - constructor(options: { - config: Config, - sender: IAddress, - receiver: IAddress, - dataParts: string[], - gasLimit: BigNumber.Value, - addDataMovementGas: boolean, - amount?: BigNumber.Value, - }) { - this.config = options.config; - this.sender = options.sender; - this.receiver = options.receiver; - this.dataParts = options.dataParts; - this.providedGasLimit = new BigNumber(options.gasLimit); - this.addDataMovementGas = options.addDataMovementGas; - this.amount = options.amount; - } - - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { - if (!this.addDataMovementGas) { - return this.providedGasLimit; - } - - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); - return gasLimit; - } - - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } - - build(): TransactionNext { - const data = this.buildTransactionPayload() - const gasLimit = this.computeGasLimit(data); - - return new TransactionNext({ - sender: this.sender.bech32(), - receiver: this.receiver.bech32(), - gasLimit: gasLimit, - value: this.amount || 0, - data: data.valueOf(), - chainID: this.config.toString() - }) - } -} diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index b4b06da38..510f68e0f 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -28,7 +28,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create draft transaction for native token transfer without data", async () => { + it("should create next transaction for native token transfer without data", async () => { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -42,7 +42,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, new Uint8Array()); }); - it("should create draft transaction for native token transfer with data", async () => { + it("should create next transaction for native token transfer with data", async () => { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -57,7 +57,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, Buffer.from("test data")); }); - it("should create draft transaction for esdt transfer", async () => { + it("should create next transaction for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0); const transfer = new NextTokenTransfer(fooToken, 1000000); @@ -74,7 +74,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); - it("should create draft transaction for nft transfer", async () => { + it("should create next transaction for nft transfer", async () => { const nft = new Token("NFT-123456", 10); const transfer = new NextTokenTransfer(nft, 1); @@ -94,7 +94,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create draft transaction for multiple nft transfers", async () => { + it("should create next transaction for multiple nft transfers", async () => { const firstNft = new Token("NFT-123456", 10); const firstTransfer = new NextTokenTransfer(firstNft, 1); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index b5290436e..1954c553a 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,10 +1,11 @@ import BigNumber from "bignumber.js"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; -import { IAddress } from "../interface"; +import { IAddress, ITransactionPayload } from "../interface"; import { NextTokenTransfer, Token } from "../tokens"; import { ErrBadUsage } from "../errors"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; +import { TransactionPayload } from "../transactionPayload"; +import { ARGUMENTS_SEPARATOR } from "../constants"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -26,6 +27,9 @@ export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; private readonly tokenComputer: TokenComputer; + private dataParts!: string[]; + private addDataMovementGas!: boolean; + private providedGasLimit!: BigNumber; constructor(config: IConfig, tokenComputer: TokenComputer) { this.config = config; @@ -39,16 +43,22 @@ export class NextTransferTransactionsFactory { nativeAmount: BigNumber.Value; data?: string; }): TransactionNext { - const data = options.data || ""; - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.receiver, - dataParts: [data], - gasLimit: 0, - addDataMovementGas: true, - amount: options.nativeAmount, - }).build(); + const d = options.data || ""; + this.dataParts = [d]; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + this.providedGasLimit = new BigNumber(0); + const gasLimit = this.computeGasLimit(data); + + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.receiver.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + value: options.nativeAmount, + chainID: this.config.chainID + }); } createTransactionForESDTTokenTransfer(options: { @@ -63,58 +73,78 @@ export class NextTransferTransactionsFactory { } if (numberOfTransfers === 1) { - return this.createSingleESDTTransferDraft(options); + return this.createSingleESDTTransferNext(options); } - const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + this.dataParts = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers ); + const data = this.buildTransactionPayload(); - const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + this.providedGasLimit = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + this.addDataMovementGas = true; + const gasLimit = this.computeGasLimit(data); - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: options.sender, - dataParts: transferArgs, - gasLimit: extraGasForTransfer, - addDataMovementGas: true, - }).build(); + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: options.sender.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); } - private createSingleESDTTransferDraft(options: { + private createSingleESDTTransferNext(options: { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; }): TransactionNext { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; - let extraGasForTransfer = new BigNumber(0); let receiver = options.receiver; if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( + this.providedGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) ); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + this.providedGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) ); receiver = options.sender; } - return new TransactionNextBuilder({ - config: this.config, - sender: options.sender, - receiver: receiver, - dataParts: transferArgs, - gasLimit: extraGasForTransfer, - addDataMovementGas: true, - }).build(); + this.dataParts = transferArgs; + const data = this.buildTransactionPayload(); + this.addDataMovementGas = true; + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: options.sender.bech32(), + receiver: receiver.bech32(), + data: data.valueOf(), + gasLimit: gasLimit, + chainID: this.config.chainID + }); + } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); + return gasLimit; } } From 39cbfa1a69a3f343bfe2f44191525003299765ad Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Thu, 8 Feb 2024 17:30:04 +0200 Subject: [PATCH 084/275] refactoring after review --- .../delegationTransactionsFactory.ts | 168 +++++++------ .../smartContractTransactionsFactory.ts | 18 +- .../tokenManagementTransactionsFactory.ts | 225 +++++++++--------- .../transferTransactionsFactory.ts | 49 ++-- 4 files changed, 225 insertions(+), 235 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 0528333f3..605b5dbd2 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -26,9 +26,6 @@ interface IValidatorPublicKey { export class DelegationTransactionsFactory { private readonly config: Config; - private dataParts!: string[]; - private addDataMovementGas!: boolean; - private providedGasLimit!: BigNumber; constructor(config: Config) { this.config = config; @@ -40,16 +37,16 @@ export class DelegationTransactionsFactory { serviceFee: BigNumber.Value, amount: BigNumber.Value }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), numberToPaddedHex(options.serviceFee.toString()) ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ @@ -74,14 +71,14 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; - this.dataParts = ["addNodes"]; + let dataParts: string[] = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - this.dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); + dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -97,17 +94,16 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - this.dataParts = ["removeNodes"]; - + let dataParts: string[] = ["removeNodes"]; for (const key of options.publicKeys) { - this.dataParts.push(key.hex()); + dataParts.push(key.hex()); } - const data = this.buildTransactionPayload(); + const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(data); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -123,20 +119,20 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - this.dataParts = ["stakeNodes"]; + let dataParts: string[] = ["stakeNodes"]; for (const key of options.publicKeys) { - this.dataParts = this.dataParts.concat(key.hex()); + dataParts = dataParts.concat(key.hex()); } - const data = this.buildTransactionPayload(); + const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); - this.addDataMovementGas = true; - this.providedGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( this.config.gasLimitDelegationOperations ); - const gasLimit = this.computeGasLimit(data); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -152,20 +148,20 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - this.dataParts = ["unBondNodes"]; + let dataParts: string[] = ["unBondNodes"]; for (const key of options.publicKeys) { - this.dataParts = this.dataParts.concat(key.hex()); + dataParts = dataParts.concat(key.hex()); } - const data = this.buildTransactionPayload(); + const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(numNodes).multipliedBy( + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -181,20 +177,20 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - this.dataParts = ["unStakeNodes"]; + let dataParts: string[] = ["unStakeNodes"]; for (const key of options.publicKeys) { - this.dataParts = this.dataParts.concat(key.hex()); + dataParts = dataParts.concat(key.hex()); } - const data = this.buildTransactionPayload(); + const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(numNodes).multipliedBy( + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -210,17 +206,17 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - this.dataParts = ["unJailNodes"]; + let dataParts: string[] = ["unJailNodes"]; for (const key of options.publicKeys) { - this.dataParts.push(key.hex()); + dataParts.push(key.hex()); } const numNodes = options.publicKeys.length; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -236,15 +232,15 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, serviceFee: BigNumber.Value }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -260,15 +256,15 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, delegationCap: BigNumber.Value }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -283,15 +279,15 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setAutomaticActivation", utf8ToHex("true") ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -306,15 +302,15 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setAutomaticActivation", utf8ToHex("false") ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -329,15 +325,15 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -352,15 +348,15 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -378,17 +374,17 @@ export class DelegationTransactionsFactory { website: string, identifier: string }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setMetaData", utf8ToHex(options.name), utf8ToHex(options.website), utf8ToHex(options.identifier) ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -404,18 +400,18 @@ export class DelegationTransactionsFactory { return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + private buildTransactionPayload(dataParts: string[]): TransactionPayload { + const data = dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { - if (!this.addDataMovementGas) { - return this.providedGasLimit; + private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { + if (!addDataMovementGas) { + return providedGasLimit; } const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); + const gasLimit = dataMovementGas.plus(providedGasLimit); return gasLimit; } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d8d1e8d30..eef2b8220 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -32,7 +32,7 @@ export class SmartContractTransactionsFactory { private readonly abiRegistry?: Abi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - private dataParts!: string[]; + //private dataParts!: string[]; constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { this.config = config; @@ -61,8 +61,8 @@ export class SmartContractTransactionsFactory { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); - this.dataParts = parts.concat(preparedArgs); - const data = this.buildTransactionPayload(); + let dataParts: string[] = parts.concat(preparedArgs); + const data = this.buildTransactionPayload(dataParts); return new TransactionNext({ sender: options.sender.bech32(), @@ -110,8 +110,8 @@ export class SmartContractTransactionsFactory { } dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); - this.dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); - const data = this.buildTransactionPayload(); + dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); + const data = this.buildTransactionPayload(dataParts); return new TransactionNext({ sender: options.sender.bech32(), @@ -149,8 +149,8 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); - this.dataParts = parts.concat(preparedArgs); - const data = this.buildTransactionPayload(); + let dataParts: string[] = parts.concat(preparedArgs); + const data = this.buildTransactionPayload(dataParts); return new TransactionNext({ sender: options.sender.bech32(), @@ -184,8 +184,8 @@ export class SmartContractTransactionsFactory { return true; } - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + private buildTransactionPayload(dataParts: string[]): TransactionPayload { + const data = dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } } diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index b8d219e81..ce49c6760 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -33,9 +33,6 @@ export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly trueAsHex: string; private readonly falseAsHex: string; - private dataParts!: string[]; - private addDataMovementGas!: boolean; - private providedGasLimit!: BigNumber; constructor(config: Config) { this.config = config; @@ -58,7 +55,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - this.dataParts = [ + let dataParts: string[] = [ "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -77,10 +74,10 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -106,7 +103,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - this.dataParts = [ + let dataParts: string[] = [ "issueSemiFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -125,10 +122,10 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -154,7 +151,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - this.dataParts = [ + let dataParts: string[] = [ "issueNonFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -173,10 +170,10 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -203,7 +200,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - this.dataParts = [ + let dataParts: string[] = [ "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -223,10 +220,10 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -247,17 +244,17 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - this.dataParts = [ + let dataParts: string[] = [ "registerAndSetAllRoles", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), bigIntToHex(options.numDecimals), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -273,11 +270,11 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - this.dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -292,11 +289,11 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - this.dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -314,17 +311,17 @@ export class TokenManagementTransactionsFactory { addRoleLocalMint: boolean; addRoleLocalBurn: boolean; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), ...(options.addRoleLocalMint ? [utf8ToHex("ESDTRoleLocalMint")] : []), ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -344,7 +341,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -353,10 +350,10 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddQuantity ? [utf8ToHex("ESDTRoleNFTAddQuantity")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -389,7 +386,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -399,10 +396,10 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddURI ? [utf8ToHex("ESDTRoleNFTAddURI")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -423,7 +420,7 @@ export class TokenManagementTransactionsFactory { attributes: Uint8Array; uris: string[]; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.initialQuantity), @@ -433,14 +430,14 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ...options.uris.map(utf8ToHex), ]; - const data = this.buildTransactionPayload(); + const data = this.buildTransactionPayload(dataParts); // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); - const gasLimit = this.computeGasLimit(data); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -455,11 +452,11 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string }): TransactionNext { - this.dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["pause", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -474,11 +471,11 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string }): TransactionNext { - this.dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["unPause", utf8ToHex(options.tokenIdentifier)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -494,11 +491,11 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - this.dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -514,11 +511,11 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - this.dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -534,11 +531,11 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - this.dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitWiping); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitWiping); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -554,11 +551,11 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToMint: BigNumber.Value; }): TransactionNext { - this.dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtLocalMint); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalMint); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -574,11 +571,11 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToBurn: BigNumber.Value; }): TransactionNext { - this.dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtLocalBurn); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalBurn); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -595,16 +592,16 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; attributes: Uint8Array; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), byteArrayToHex(options.attributes), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -621,16 +618,16 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToAdd), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -647,16 +644,16 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value; }): TransactionNext { - this.dataParts = [ + let dataParts: string[] = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToBurn), ]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(this.config.gasLimitEsdtNftBurn); - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftBurn); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -676,18 +673,18 @@ You are about to issue (register) a new token. This will set the role "ESDTRoleB Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); } - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + private buildTransactionPayload(dataParts: string[]): TransactionPayload { + const data = dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { - if (!this.addDataMovementGas) { - return this.providedGasLimit; + private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { + if (!addDataMovementGas) { + return providedGasLimit; } const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); + const gasLimit = dataMovementGas.plus(providedGasLimit); return gasLimit; } } diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 1954c553a..14a4045f2 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -27,9 +27,6 @@ export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; private readonly tokenComputer: TokenComputer; - private dataParts!: string[]; - private addDataMovementGas!: boolean; - private providedGasLimit!: BigNumber; constructor(config: IConfig, tokenComputer: TokenComputer) { this.config = config; @@ -44,11 +41,11 @@ export class NextTransferTransactionsFactory { data?: string; }): TransactionNext { const d = options.data || ""; - this.dataParts = [d]; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - this.providedGasLimit = new BigNumber(0); - const gasLimit = this.computeGasLimit(data); + let dataParts: string[] = [d]; + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(0); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ @@ -76,17 +73,16 @@ export class NextTransferTransactionsFactory { return this.createSingleESDTTransferNext(options); } - this.dataParts = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + let dataParts: string[] = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers ); - const data = this.buildTransactionPayload(); - - this.providedGasLimit = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + const data = this.buildTransactionPayload(dataParts); + const addDataMovementGas: boolean = true; + const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); - this.addDataMovementGas = true; - const gasLimit = this.computeGasLimit(data); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -105,24 +101,25 @@ export class NextTransferTransactionsFactory { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; let receiver = options.receiver; + const addDataMovementGas: boolean = true; + let providedGasLimit: BigNumber = new BigNumber(0); + if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - this.providedGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( + providedGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) ); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - this.providedGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + providedGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) ); receiver = options.sender; } - this.dataParts = transferArgs; - const data = this.buildTransactionPayload(); - this.addDataMovementGas = true; - const gasLimit = this.computeGasLimit(data); + const data = this.buildTransactionPayload(transferArgs); + const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -133,18 +130,18 @@ export class NextTransferTransactionsFactory { }); } - private buildTransactionPayload(): TransactionPayload { - const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + private buildTransactionPayload(dataParts: string[]): TransactionPayload { + const data = dataParts.join(ARGUMENTS_SEPARATOR); return new TransactionPayload(data); } - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { - if (!this.addDataMovementGas) { - return this.providedGasLimit; + private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { + if (!addDataMovementGas) { + return providedGasLimit; } const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); + const gasLimit = dataMovementGas.plus(providedGasLimit); return gasLimit; } } From 7beb8799bf70a56b413c16b868fb71ad4ec7fc73 Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Fri, 9 Feb 2024 15:01:26 +0200 Subject: [PATCH 085/275] Fixes after review. --- .../delegationTransactionsFactory.spec.ts | 28 +-- .../delegationTransactionsFactory.ts | 106 +++++------ .../smartContractTransactionsFactory.spec.ts | 16 +- .../smartContractTransactionsFactory.ts | 8 +- ...anagementTransactionIntentsFactory.spec.ts | 14 +- .../tokenManagementTransactionsFactory.ts | 174 ++++++++---------- .../transferTransactionsFactory.spec.ts | 10 +- .../transferTransactionsFactory.ts | 32 ++-- 8 files changed, 165 insertions(+), 223 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 7e62bdc76..81a276c40 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -10,7 +10,7 @@ describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig("D"); const delegationFactory = new DelegationTransactionsFactory(config); - it("should create next transaction for new delegation contract", async function () { + it("should create 'TransactionNext' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delagationCap = "5000000000000000000000"; const serviceFee = 10; @@ -31,7 +31,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, value); }); - it("should create next transaction for adding nodes", async function () { + it("should create 'TransactionNext' for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); @@ -54,7 +54,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for removing nodes", async function () { + it("should create 'TransactionNext' for removing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -77,7 +77,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for staking nodes", async function () { + it("should create 'TransactionNext' for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -100,7 +100,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for unbonding nodes", async function () { + it("should create 'TransactionNext' for unbonding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -124,7 +124,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.gasLimit.valueOf(), 12080000); }); - it("should create next transaction for unstaking nodes", async function () { + it("should create 'TransactionNext' for unstaking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -148,7 +148,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.gasLimit.valueOf(), 12081500); }); - it("should create next transaction for unjailing nodes", async function () { + it("should create 'TransactionNext' for unjailing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -171,7 +171,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for changing service fee", async function () { + it("should create 'TransactionNext' for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); @@ -189,7 +189,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for changing delegation cap", async function () { + it("should create 'TransactionNext' for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); @@ -207,7 +207,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for setting automatic activation", async function () { + it("should create 'TransactionNext' for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -223,7 +223,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for unsetting automatic activation", async function () { + it("should create 'TransactionNext' for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -239,7 +239,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for setting cap check on redelegate rewards", async function () { + it("should create 'TransactionNext' for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -255,7 +255,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for unsetting cap check on redelegate rewards", async function () { + it("should create 'TransactionNext' for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -271,7 +271,7 @@ describe("test delegation transactions factory", function () { assert.equal(next.value, 0); }); - it("should create next transaction for setting metadata", async function () { + it("should create 'TransactionNext' for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 605b5dbd2..686562cfd 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,7 +1,6 @@ import { IAddress, ITransactionPayload } from "../interface"; import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { Address } from "../address"; import { ARGUMENTS_SEPARATOR, DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; import { TransactionNext } from "../transaction"; @@ -37,21 +36,19 @@ export class DelegationTransactionsFactory { serviceFee: BigNumber.Value, amount: BigNumber.Value }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), numberToPaddedHex(options.serviceFee.toString()) ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); - + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS).bech32(), + receiver: DELEGATION_MANAGER_SC_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: options.amount, @@ -71,14 +68,13 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; - let dataParts: string[] = ["addNodes"]; + const dataParts: string[] = ["addNodes"]; for (let i = 0; i < numNodes; i++) { dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -94,16 +90,15 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts: string[] = ["removeNodes"]; + const dataParts: string[] = ["removeNodes"]; for (const key of options.publicKeys) { dataParts.push(key.hex()); } const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -122,17 +117,16 @@ export class DelegationTransactionsFactory { let dataParts: string[] = ["stakeNodes"]; for (const key of options.publicKeys) { - dataParts = dataParts.concat(key.hex()); + dataParts = dataParts.concat(key.hex()); } const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( + const extraGasLimit: BigNumber= additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( this.config.gasLimitDelegationOperations ); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -156,12 +150,11 @@ export class DelegationTransactionsFactory { const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( + const extraGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -185,12 +178,11 @@ export class DelegationTransactionsFactory { const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( + const extraGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -206,7 +198,7 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts: string[] = ["unJailNodes"]; + const dataParts: string[] = ["unJailNodes"]; for (const key of options.publicKeys) { dataParts.push(key.hex()); @@ -214,9 +206,8 @@ export class DelegationTransactionsFactory { const numNodes = options.publicKeys.length; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -232,15 +223,14 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, serviceFee: BigNumber.Value }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -256,15 +246,14 @@ export class DelegationTransactionsFactory { delegationContract: IAddress, delegationCap: BigNumber.Value }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -279,15 +268,14 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setAutomaticActivation", utf8ToHex("true") ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -302,15 +290,14 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setAutomaticActivation", utf8ToHex("false") ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -325,15 +312,14 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -348,15 +334,14 @@ export class DelegationTransactionsFactory { sender: IAddress, delegationContract: IAddress }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -374,7 +359,7 @@ export class DelegationTransactionsFactory { website: string, identifier: string }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setMetaData", utf8ToHex(options.name), utf8ToHex(options.website), @@ -382,9 +367,8 @@ export class DelegationTransactionsFactory { ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -405,13 +389,9 @@ export class DelegationTransactionsFactory { return new TransactionPayload(data); } - private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - if (!addDataMovementGas) { - return providedGasLimit; - } - + private computeGasLimit(extraGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(providedGasLimit); + const gasLimit = dataMovementGas.plus(extraGasLimit); return gasLimit; } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index e22418362..eeaeb406d 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -52,7 +52,7 @@ describe("test smart contract transactions factory", function () { ); }); - it("should create next transaction for deploy", async function () { + it("should create 'TransactionNext' for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000; const args = [new U32Value(0)]; @@ -79,7 +79,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(deployNext, abiDeployNext); }); - it("should create next transaction for execute without transfer", async function () { + it("should create 'TransactionNext' for execute without transfer", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -110,7 +110,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for execute and transfer native token", async function () { + it("should create 'TransactionNext' for execute and transfer native token", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -143,7 +143,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for execute and transfer single esdt", async function () { + it("should create 'TransactionNext' for execute and transfer single esdt", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -178,7 +178,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for execute and transfer multiple esdts", async function () { + it("should create 'TransactionNext' for execute and transfer multiple esdts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); const func = "add"; @@ -223,7 +223,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for execute and transfer single nft", async function () { + it("should create 'TransactionNext' for execute and transfer single nft", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -267,7 +267,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for execute and transfer multiple nfts", async function () { + it("should create 'TransactionNext' for execute and transfer multiple nfts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -313,7 +313,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(executeNext, abiExecuteNext); }); - it("should create next transaction for upgrade", async function () { + it("should create 'TransactionNext' for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index eef2b8220..a7abf0b8d 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -5,7 +5,6 @@ import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { ARGUMENTS_SEPARATOR, CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; -import { Address } from "../address"; import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionNext } from "../transaction"; @@ -32,7 +31,6 @@ export class SmartContractTransactionsFactory { private readonly abiRegistry?: Abi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - //private dataParts!: string[]; constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { this.config = config; @@ -61,12 +59,12 @@ export class SmartContractTransactionsFactory { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); - let dataParts: string[] = parts.concat(preparedArgs); + const dataParts: string[] = parts.concat(preparedArgs); const data = this.buildTransactionPayload(dataParts); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS).bech32(), + receiver: CONTRACT_DEPLOY_ADDRESS, data: data.valueOf(), gasLimit: options.gasLimit, value: nativeTransferAmount, @@ -149,7 +147,7 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); parts = parts.concat(preparedArgs); - let dataParts: string[] = parts.concat(preparedArgs); + const dataParts: string[] = parts.concat(preparedArgs); const data = this.buildTransactionPayload(dataParts); return new TransactionNext({ diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 3694b7683..021601824 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -16,7 +16,7 @@ describe("test token management transactions factory", () => { factory = new TokenManagementTransactionsFactory(config); }); - it("should create next transaction for registering and setting roles", () => { + it("should create 'TransactionNext' for registering and setting roles", () => { const next = factory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", @@ -32,7 +32,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(next.gasLimit, new BigNumber("60125000")); }); - it("should create next transaction for issuing fungible token", () => { + it("should create 'TransactionNext' for issuing fungible token", () => { const next = factory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", @@ -53,7 +53,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(next.value, config.issueCost); }); - it("should create next transaction for issuing semi-fungible token", () => { + it("should create 'TransactionNext' for issuing semi-fungible token", () => { const next = factory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", @@ -73,7 +73,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(next.value, config.issueCost); }); - it("should create next transaction for issuing non-fungible token", () => { + it("should create 'TransactionNext' for issuing non-fungible token", () => { const next = factory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", @@ -93,7 +93,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(next.value, config.issueCost); }); - it("should create next transaction for registering metaEsdt", () => { + it("should create 'TransactionNext' for registering metaEsdt", () => { const next = factory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", @@ -114,7 +114,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(next.value, config.issueCost); }); - it("should create next transaction for setting spcial role on non-fungible token", () => { + it("should create 'TransactionNext' for setting spcial role on non-fungible token", () => { const next = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, @@ -132,7 +132,7 @@ describe("test token management transactions factory", () => { assert.equal(next.value, 0); }); - it("should create next transaction for creating nft", () => { + it("should create 'TransactionNext' for creating nft", () => { const next = factory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index ce49c6760..3b044c005 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,5 +1,4 @@ import BigNumber from "bignumber.js"; -import { Address } from "../address"; import { ARGUMENTS_SEPARATOR, ESDT_CONTRACT_ADDRESS } from "../constants"; import { IAddress, ITransactionPayload } from "../interface"; import { Logger } from "../logger"; @@ -55,7 +54,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - let dataParts: string[] = [ + const dataParts: string[] = [ "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -75,13 +74,12 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: this.config.issueCost, @@ -103,7 +101,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - let dataParts: string[] = [ + const dataParts: string[] = [ "issueSemiFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -123,13 +121,12 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: this.config.issueCost, @@ -151,7 +148,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - let dataParts: string[] = [ + const dataParts: string[] = [ "issueNonFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -171,13 +168,12 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: this.config.issueCost, @@ -200,7 +196,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - let dataParts: string[] = [ + const dataParts: string[] = [ "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -221,13 +217,12 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: this.config.issueCost, @@ -244,7 +239,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - let dataParts: string[] = [ + const dataParts: string[] = [ "registerAndSetAllRoles", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -252,13 +247,12 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.numDecimals), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, value: this.config.issueCost, @@ -270,15 +264,14 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - let dataParts: string[] = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const dataParts: string[] = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, chainID: this.config.chainID @@ -289,15 +282,14 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - let dataParts: string[] = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const dataParts: string[] = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, chainID: this.config.chainID @@ -311,7 +303,7 @@ export class TokenManagementTransactionsFactory { addRoleLocalMint: boolean; addRoleLocalBurn: boolean; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -319,13 +311,12 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, chainID: this.config.chainID @@ -341,7 +332,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -351,13 +342,12 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, chainID: this.config.chainID @@ -386,7 +376,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -397,13 +387,12 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), - receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS).bech32(), + receiver: ESDT_CONTRACT_ADDRESS, data: data.valueOf(), gasLimit: gasLimit, chainID: this.config.chainID @@ -420,7 +409,7 @@ export class TokenManagementTransactionsFactory { attributes: Uint8Array; uris: string[]; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.initialQuantity), @@ -435,9 +424,8 @@ export class TokenManagementTransactionsFactory { // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -452,11 +440,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string }): TransactionNext { - let dataParts: string[] = ["pause", utf8ToHex(options.tokenIdentifier)]; + const dataParts: string[] = ["pause", utf8ToHex(options.tokenIdentifier)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -471,11 +458,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string }): TransactionNext { - let dataParts: string[] = ["unPause", utf8ToHex(options.tokenIdentifier)]; + const dataParts: string[] = ["unPause", utf8ToHex(options.tokenIdentifier)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -491,11 +477,10 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - let dataParts: string[] = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts: string[] = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -511,11 +496,10 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - let dataParts: string[] = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts: string[] = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -531,11 +515,10 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - let dataParts: string[] = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts: string[] = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitWiping); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitWiping); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -551,11 +534,10 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToMint: BigNumber.Value; }): TransactionNext { - let dataParts: string[] = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; + const dataParts: string[] = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalMint); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalMint); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -571,11 +553,10 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToBurn: BigNumber.Value; }): TransactionNext { - let dataParts: string[] = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; + const dataParts: string[] = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalBurn); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalBurn); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -592,16 +573,15 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; attributes: Uint8Array; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), byteArrayToHex(options.attributes), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -618,16 +598,15 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToAdd), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -644,16 +623,15 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value; }): TransactionNext { - let dataParts: string[] = [ + const dataParts: string[] = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToBurn), ]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftBurn); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftBurn); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -678,11 +656,7 @@ Once the token is registered, you can unset this role by calling "unsetBurnRoleG return new TransactionPayload(data); } - private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - if (!addDataMovementGas) { - return providedGasLimit; - } - + private computeGasLimit(providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); const gasLimit = dataMovementGas.plus(providedGasLimit); return gasLimit; diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 510f68e0f..2e4be25bd 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -28,7 +28,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create next transaction for native token transfer without data", async () => { + it("should create 'TransactionNext' for native token transfer without data", async () => { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -42,7 +42,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, new Uint8Array()); }); - it("should create next transaction for native token transfer with data", async () => { + it("should create 'TransactionNext' for native token transfer with data", async () => { const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -57,7 +57,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, Buffer.from("test data")); }); - it("should create next transaction for esdt transfer", async () => { + it("should create 'TransactionNext' for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0); const transfer = new NextTokenTransfer(fooToken, 1000000); @@ -74,7 +74,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); - it("should create next transaction for nft transfer", async () => { + it("should create 'TransactionNext' for nft transfer", async () => { const nft = new Token("NFT-123456", 10); const transfer = new NextTokenTransfer(nft, 1); @@ -94,7 +94,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create next transaction for multiple nft transfers", async () => { + it("should create 'TransactionNext' for multiple nft transfers", async () => { const firstNft = new Token("NFT-123456", 10); const firstTransfer = new NextTokenTransfer(firstNft, 1); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 14a4045f2..878c9fd17 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -40,13 +40,10 @@ export class NextTransferTransactionsFactory { nativeAmount: BigNumber.Value; data?: string; }): TransactionNext { - const d = options.data || ""; - let dataParts: string[] = [d]; + const dataParts = [options.data || ""]; const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(0); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); - + const extraGasLimit: BigNumber = new BigNumber(0); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -73,16 +70,15 @@ export class NextTransferTransactionsFactory { return this.createSingleESDTTransferNext(options); } - let dataParts: string[] = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + const dataParts: string[] = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers ); const data = this.buildTransactionPayload(dataParts); - const addDataMovementGas: boolean = true; - const providedGasLimit: BigNumber = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) .multipliedBy(new BigNumber(numberOfTransfers)) .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -101,25 +97,23 @@ export class NextTransferTransactionsFactory { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; let receiver = options.receiver; - const addDataMovementGas: boolean = true; - let providedGasLimit: BigNumber = new BigNumber(0); + let extraGasLimit: BigNumber = new BigNumber(0); - if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - providedGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( + extraGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) ); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - providedGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + extraGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) ); receiver = options.sender; } const data = this.buildTransactionPayload(transferArgs); - const gasLimit = this.computeGasLimit(addDataMovementGas, providedGasLimit, data); + const gasLimit = this.computeGasLimit(extraGasLimit, data); return new TransactionNext({ sender: options.sender.bech32(), @@ -135,11 +129,7 @@ export class NextTransferTransactionsFactory { return new TransactionPayload(data); } - private computeGasLimit(addDataMovementGas: boolean, providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - if (!addDataMovementGas) { - return providedGasLimit; - } - + private computeGasLimit(providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); const gasLimit = dataMovementGas.plus(providedGasLimit); return gasLimit; From 30195c20bbe3699d11d68b8f9e7667489e6c0121 Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Mon, 12 Feb 2024 13:42:47 +0200 Subject: [PATCH 086/275] refactoring all + transactionNextBuilder --- .../delegationTransactionsFactory.ts | 360 +++++-------- .../smartContractTransactionsFactory.ts | 67 ++- .../tokenManagementTransactionsFactory.ts | 506 ++++++++---------- .../transactionNextBuilder.ts | 69 +++ .../transferTransactionsFactory.ts | 99 ++-- 5 files changed, 513 insertions(+), 588 deletions(-) create mode 100644 src/transactionsFactories/transactionNextBuilder.ts diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 686562cfd..354cb8804 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,11 +1,11 @@ -import { IAddress, ITransactionPayload } from "../interface"; +import { IAddress } from "../interface"; import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { ARGUMENTS_SEPARATOR, DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; +import { Address } from "../address"; +import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; import { TransactionNext } from "../transaction"; -import { TransactionPayload } from "../transactionPayload"; - interface Config { chainID: string; minGasLimit: BigNumber.Value; @@ -18,44 +18,36 @@ interface Config { additionalGasLimitPerValidatorNode: BigNumber.Value; additionalGasLimitForDelegationOperations: BigNumber.Value; } - interface IValidatorPublicKey { hex(): string; } - export class DelegationTransactionsFactory { private readonly config: Config; - constructor(config: Config) { this.config = config; } - createTransactionForNewDelegationContract(options: { sender: IAddress, totalDelegationCap: BigNumber.Value, serviceFee: BigNumber.Value, amount: BigNumber.Value }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), numberToPaddedHex(options.serviceFee.toString()) ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: DELEGATION_MANAGER_SC_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: options.amount, - chainID: this.config.chainID - }); + const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), + dataParts: dataParts, + gasLimit: executionGasLimit, + addDataMovementGas: true, + amount: options.amount + }).build(); } - createTransactionForAddingNodes(options: { sender: IAddress, delegationContract: IAddress, @@ -65,293 +57,231 @@ export class DelegationTransactionsFactory { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } - const numNodes = options.publicKeys.length; - - const dataParts: string[] = ["addNodes"]; + const dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); + dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true + }).build(); } - createTransactionForRemovingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - const dataParts: string[] = ["removeNodes"]; + const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { dataParts.push(key.hex()); } - - const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true + }).build(); } - createTransactionForStakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts: string[] = ["stakeNodes"]; - + let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - - const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); - const extraGasLimit: BigNumber= additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( + const executionGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( this.config.gasLimitDelegationOperations ); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: executionGasLimit, + addDataMovementGas: true + }).build(); } - createTransactionForUnbondingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts: string[] = ["unBondNodes"]; - + let dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - - const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const extraGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( + const executionGasLimit = new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnbond ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: executionGasLimit, + addDataMovementGas: true + }).build(); } - createTransactionForUnstakingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - let dataParts: string[] = ["unStakeNodes"]; - + let dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } - - const data = this.buildTransactionPayload(dataParts); const numNodes = options.publicKeys.length; - const extraGasLimit: BigNumber= new BigNumber(numNodes).multipliedBy( + const executionGasLimit = new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode).plus( this.config.gasLimitUnstake ).plus(this.config.gasLimitDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: executionGasLimit, + addDataMovementGas: true + }).build(); } - createTransactionForUnjailingNodes(options: { sender: IAddress, delegationContract: IAddress, publicKeys: IValidatorPublicKey[] }): TransactionNext { - const dataParts: string[] = ["unJailNodes"]; - + const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { dataParts.push(key.hex()); } - const numNodes = options.publicKeys.length; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.computeExecutionGasLimitForNodesManagement(numNodes)); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), + addDataMovementGas: true + }).build(); } - createTransactionForChangingServiceFee(options: { sender: IAddress, delegationContract: IAddress, serviceFee: BigNumber.Value }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "changeServiceFee", numberToPaddedHex(options.serviceFee) ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForModifyingDelegationCap(options: { sender: IAddress, delegationContract: IAddress, delegationCap: BigNumber.Value }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap) ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForSettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setAutomaticActivation", utf8ToHex("true") ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setAutomaticActivation", utf8ToHex("false") ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("true") ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress, delegationContract: IAddress }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setCheckCapOnReDelegateRewards", utf8ToHex("false") ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber= new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - createTransactionForSettingMetadata(options: { sender: IAddress, delegationContract: IAddress, @@ -359,39 +289,23 @@ export class DelegationTransactionsFactory { website: string, identifier: string }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setMetaData", utf8ToHex(options.name), utf8ToHex(options.website), utf8ToHex(options.identifier) ]; - - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.delegationContract.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.delegationContract, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), + addDataMovementGas: true + }).build(); } - private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } - - private buildTransactionPayload(dataParts: string[]): TransactionPayload { - const data = dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } - - private computeGasLimit(extraGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(extraGasLimit); - return gasLimit; - } -} +} \ No newline at end of file diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index a7abf0b8d..1726d7585 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -2,13 +2,15 @@ import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { ARGUMENTS_SEPARATOR, CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; +import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Err, ErrBadUsage } from "../errors"; +import { Address } from "../address"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionNext } from "../transaction"; -import { TransactionPayload } from "../transactionPayload"; + interface Config { chainID: string; @@ -59,17 +61,17 @@ export class SmartContractTransactionsFactory { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); - const dataParts: string[] = parts.concat(preparedArgs); - const data = this.buildTransactionPayload(dataParts); + parts = parts.concat(preparedArgs); - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: CONTRACT_DEPLOY_ADDRESS, - data: data.valueOf(), + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), + dataParts: parts, gasLimit: options.gasLimit, - value: nativeTransferAmount, - chainID: this.config.chainID - }); + addDataMovementGas: false, + amount: nativeTransferAmount, + }).build(); } createTransactionForExecute(options: { @@ -109,16 +111,16 @@ export class SmartContractTransactionsFactory { dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); - const data = this.buildTransactionPayload(dataParts); - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: receiver.bech32(), - data: data.valueOf(), + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: receiver, + dataParts: dataParts, gasLimit: options.gasLimit, - value: nativeTransferAmount, - chainID: this.config.chainID - }); + addDataMovementGas: false, + amount: nativeTransferAmount, + }).build(); } createTransactionForUpgrade(options: { @@ -146,18 +148,19 @@ export class SmartContractTransactionsFactory { let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); + parts = parts.concat(preparedArgs); - const dataParts: string[] = parts.concat(preparedArgs); - const data = this.buildTransactionPayload(dataParts); - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.contract.bech32(), - data: data.valueOf(), + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.contract, + dataParts: parts, gasLimit: options.gasLimit, - value: nativeTransferAmount, - chainID: this.config.chainID - }); + addDataMovementGas: false, + amount: nativeTransferAmount, + }).build(); } private argsToDataParts(args: any[], endpoint?: EndpointDefinition): string[] { @@ -169,7 +172,6 @@ export class SmartContractTransactionsFactory { if (this.areArgsOfTypedValue(args)) { return new ArgSerializer().valuesToStrings(args); } - throw new Err("Can't convert args to TypedValues"); } @@ -181,9 +183,4 @@ export class SmartContractTransactionsFactory { } return true; } - - private buildTransactionPayload(dataParts: string[]): TransactionPayload { - const data = dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } -} +} \ No newline at end of file diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 3b044c005..9ac161a2d 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,10 +1,12 @@ import BigNumber from "bignumber.js"; -import { ARGUMENTS_SEPARATOR, ESDT_CONTRACT_ADDRESS } from "../constants"; -import { IAddress, ITransactionPayload } from "../interface"; +import { Address } from "../address"; +import { ESDT_CONTRACT_ADDRESS } from "../constants"; +import { IAddress } from "../interface"; import { Logger } from "../logger"; import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; -import { TransactionPayload } from "../transactionPayload"; + interface Config { chainID: string; @@ -54,7 +56,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts: string[] = [ + const dataParts = [ "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -73,18 +75,17 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: this.config.issueCost, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, + amount: this.config.issueCost, + }).build(); } createTransactionForIssuingSemiFungible(options: { @@ -101,7 +102,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts: string[] = [ + const dataParts = [ "issueSemiFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -120,18 +121,17 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: this.config.issueCost, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, + amount: this.config.issueCost, + }).build(); } createTransactionForIssuingNonFungible(options: { @@ -148,7 +148,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts: string[] = [ + const dataParts = [ "issueNonFungible", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -167,18 +167,17 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: this.config.issueCost, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, + amount: this.config.issueCost, + }).build(); } createTransactionForRegisteringMetaESDT(options: { @@ -196,7 +195,7 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts: string[] = [ + const dataParts = [ "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), @@ -216,18 +215,17 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: this.config.issueCost, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, + amount: this.config.issueCost, + }).build(); } createTransactionForRegisteringAndSettingRoles(options: { @@ -239,61 +237,56 @@ export class TokenManagementTransactionsFactory { }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts: string[] = [ + const dataParts = [ "registerAndSetAllRoles", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), bigIntToHex(options.numDecimals), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitIssue); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - value: this.config.issueCost, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitIssue, + addDataMovementGas: true, + amount: this.config.issueCost, + }).build(); } createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts: string[] = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitToggleBurnRoleGlobally, + addDataMovementGas: true, + }).build(); } createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts: string[] = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitToggleBurnRoleGlobally); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitToggleBurnRoleGlobally, + addDataMovementGas: true, + }).build(); } createTransactionForSettingSpecialRoleOnFungibleToken(options: { @@ -303,24 +296,23 @@ export class TokenManagementTransactionsFactory { addRoleLocalMint: boolean; addRoleLocalBurn: boolean; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), ...(options.addRoleLocalMint ? [utf8ToHex("ESDTRoleLocalMint")] : []), ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true, + }).build(); } createTransactionForSettingSpecialRoleOnSemiFungibleToken(options: { @@ -332,7 +324,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -341,17 +333,16 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddQuantity ? [utf8ToHex("ESDTRoleNFTAddQuantity")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true, + }).build(); } createTransactionForSettingSpecialRoleOnMetaESDT(options: { @@ -376,7 +367,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), addressToHex(options.user), @@ -386,17 +377,16 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleNFTAddURI ? [utf8ToHex("ESDTRoleNFTAddURI")] : []), ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitSetSpecialRole); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: ESDT_CONTRACT_ADDRESS, - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), + dataParts: dataParts, + gasLimit: this.config.gasLimitSetSpecialRole, + addDataMovementGas: true, + }).build(); } createTransactionForCreatingNFT(options: { @@ -409,7 +399,7 @@ export class TokenManagementTransactionsFactory { attributes: Uint8Array; uris: string[]; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.initialQuantity), @@ -419,57 +409,53 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ...options.uris.map(utf8ToHex), ]; - const data = this.buildTransactionPayload(dataParts); + // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit), + addDataMovementGas: true, + }).build(); } createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { - const dataParts: string[] = ["pause", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitPausing, + addDataMovementGas: true, + }).build(); } createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { - const dataParts: string[] = ["unPause", utf8ToHex(options.tokenIdentifier)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitPausing); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitPausing, + addDataMovementGas: true, + }).build(); } createTransactionForFreezing(options: { @@ -477,18 +463,16 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts: string[] = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitFreezing, + addDataMovementGas: true, + }).build(); } createTransactionForUnfreezing(options: { @@ -496,18 +480,16 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts: string[] = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitFreezing); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitFreezing, + addDataMovementGas: true, + }).build(); } createTransactionForWiping(options: { @@ -515,18 +497,16 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): TransactionNext { - const dataParts: string[] = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitWiping); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitWiping, + addDataMovementGas: true, + }).build(); } createTransactionForLocalMint(options: { @@ -534,18 +514,16 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToMint: BigNumber.Value; }): TransactionNext { - const dataParts: string[] = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalMint); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitEsdtLocalMint, + addDataMovementGas: true, + }).build(); } createTransactionForLocalBurning(options: { @@ -553,18 +531,16 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; supplyToBurn: BigNumber.Value; }): TransactionNext { - const dataParts: string[] = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtLocalBurn); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + const dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitEsdtLocalBurn, + addDataMovementGas: true, + }).build(); } createTransactionForUpdatingAttributes(options: { @@ -573,23 +549,22 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; attributes: Uint8Array; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), byteArrayToHex(options.attributes), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftUpdateAttributes); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitEsdtNftUpdateAttributes, + addDataMovementGas: true, + }).build(); } createTransactionForAddingQuantity(options: { @@ -598,23 +573,22 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToAdd: BigNumber.Value; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToAdd), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftAddQuantity); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitEsdtNftAddQuantity, + addDataMovementGas: true, + }).build(); } createTransactionForBurningQuantity(options: { @@ -623,23 +597,22 @@ export class TokenManagementTransactionsFactory { tokenNonce: BigNumber.Value; quantityToBurn: BigNumber.Value; }): TransactionNext { - const dataParts: string[] = [ + const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.tokenNonce), bigIntToHex(options.quantityToBurn), ]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitEsdtNftBurn); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: dataParts, + gasLimit: this.config.gasLimitEsdtNftBurn, + addDataMovementGas: true, + }).build(); } private notifyAboutUnsettingBurnRoleGlobally() { @@ -650,15 +623,4 @@ IMPORTANT! You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); } - - private buildTransactionPayload(dataParts: string[]): TransactionPayload { - const data = dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } - - private computeGasLimit(providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(providedGasLimit); - return gasLimit; - } -} +} \ No newline at end of file diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts new file mode 100644 index 000000000..36d2200bf --- /dev/null +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -0,0 +1,69 @@ +import { BigNumber } from "bignumber.js"; +import { IAddress, ITransactionPayload } from "../interface"; +import { ARGUMENTS_SEPARATOR } from "../constants"; +import { TransactionPayload } from "../transactionPayload"; +import { TransactionNext } from "../transaction"; + + +interface Config { + chainID: string; + minGasLimit: BigNumber.Value; + gasLimitPerByte: BigNumber.Value; +} + +export class TransactionNextBuilder { + private config: Config; + private sender: IAddress; + private receiver: IAddress; + private dataParts: string[]; + private providedGasLimit: BigNumber; + private addDataMovementGas: boolean; + private amount?: BigNumber.Value; + + constructor(options: { + config: Config, + sender: IAddress, + receiver: IAddress, + dataParts: string[], + gasLimit: BigNumber.Value, + addDataMovementGas: boolean, + amount?: BigNumber.Value, + }) { + this.config = options.config; + this.sender = options.sender; + this.receiver = options.receiver; + this.dataParts = options.dataParts; + this.providedGasLimit = new BigNumber(options.gasLimit); + this.addDataMovementGas = options.addDataMovementGas; + this.amount = options.amount; + } + + private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + if (!this.addDataMovementGas) { + return this.providedGasLimit; + } + + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const gasLimit = dataMovementGas.plus(this.providedGasLimit); + return gasLimit; + } + + private buildTransactionPayload(): TransactionPayload { + const data = this.dataParts.join(ARGUMENTS_SEPARATOR); + return new TransactionPayload(data); + } + + build(): TransactionNext { + const data = this.buildTransactionPayload() + const gasLimit = this.computeGasLimit(data); + + return new TransactionNext({ + sender: this.sender.bech32(), + receiver: this.receiver.bech32(), + gasLimit: gasLimit, + value: this.amount || 0, + data: data.valueOf(), + chainID: this.config.toString() + }) + } +} \ No newline at end of file diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 878c9fd17..1de3c6b13 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,11 +1,11 @@ import BigNumber from "bignumber.js"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; -import { IAddress, ITransactionPayload } from "../interface"; +import { IAddress } from "../interface"; import { NextTokenTransfer, Token } from "../tokens"; import { ErrBadUsage } from "../errors"; +import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; -import { TransactionPayload } from "../transactionPayload"; -import { ARGUMENTS_SEPARATOR } from "../constants"; + const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -40,19 +40,17 @@ export class NextTransferTransactionsFactory { nativeAmount: BigNumber.Value; data?: string; }): TransactionNext { - const dataParts = [options.data || ""]; - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(0); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.receiver.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - value: options.nativeAmount, - chainID: this.config.chainID - }); + const data = options.data || ""; + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.receiver, + dataParts: [data], + gasLimit: 0, + addDataMovementGas: true, + amount: options.nativeAmount, + }).build(); } createTransactionForESDTTokenTransfer(options: { @@ -67,71 +65,56 @@ export class NextTransferTransactionsFactory { } if (numberOfTransfers === 1) { - return this.createSingleESDTTransferNext(options); + return this.createSingleESDTTransferDraft(options); } - const dataParts: string[] = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers - ); - const data = this.buildTransactionPayload(dataParts); - const extraGasLimit: BigNumber = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) - .multipliedBy(new BigNumber(numberOfTransfers)) - .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: options.sender.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); + ) + + const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer).multipliedBy(new BigNumber(numberOfTransfers)).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: options.sender, + dataParts: transferArgs, + gasLimit: extraGasForTransfer, + addDataMovementGas: true, + }).build(); } - private createSingleESDTTransferNext(options: { + private createSingleESDTTransferDraft(options: { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; }): TransactionNext { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; + let extraGasForTransfer = new BigNumber(0); let receiver = options.receiver; - let extraGasLimit: BigNumber = new BigNumber(0); - + if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasLimit = new BigNumber(this.config.gasLimitESDTTransfer).plus( + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) ); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasLimit = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( + extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) ); receiver = options.sender; } - const data = this.buildTransactionPayload(transferArgs); - const gasLimit = this.computeGasLimit(extraGasLimit, data); - - return new TransactionNext({ - sender: options.sender.bech32(), - receiver: receiver.bech32(), - data: data.valueOf(), - gasLimit: gasLimit, - chainID: this.config.chainID - }); - } - - private buildTransactionPayload(dataParts: string[]): TransactionPayload { - const data = dataParts.join(ARGUMENTS_SEPARATOR); - return new TransactionPayload(data); - } - - private computeGasLimit(providedGasLimit: BigNumber, payload: ITransactionPayload): BigNumber.Value { - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); - const gasLimit = dataMovementGas.plus(providedGasLimit); - return gasLimit; + return new TransactionNextBuilder({ + config: this.config, + sender: options.sender, + receiver: receiver, + dataParts: transferArgs, + gasLimit: extraGasForTransfer, + addDataMovementGas: true, + }).build(); } } From 599fd4923f5e3223d5e615f072f508a189de6371 Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Mon, 12 Feb 2024 17:03:09 +0200 Subject: [PATCH 087/275] fixes after review --- .../delegationTransactionsFactory.spec.ts | 30 ++++----- .../delegationTransactionsFactory.ts | 2 +- .../smartContractTransactionsFactory.spec.ts | 22 +++---- .../smartContractTransactionsFactory.ts | 2 +- ...anagementTransactionIntentsFactory.spec.ts | 18 +++--- .../tokenManagementTransactionsFactory.ts | 4 +- .../transactionNextBuilder.ts | 2 +- .../transferTransactionsFactory.spec.ts | 64 +++++++++---------- .../transferTransactionsFactory.ts | 2 +- 9 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 81a276c40..ff4fb4ae8 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -8,7 +8,7 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig("D"); - const delegationFactory = new DelegationTransactionsFactory(config); + const transaction = new DelegationTransactionsFactory(config); it("should create 'TransactionNext' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); @@ -16,7 +16,7 @@ describe("test delegation transactions factory", function () { const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); - const next = delegationFactory.createTransactionForNewDelegationContract({ + const next = transaction.createTransactionForNewDelegationContract({ sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, @@ -40,7 +40,7 @@ describe("test delegation transactions factory", function () { getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") } - const next = delegationFactory.createTransactionForAddingNodes({ + const next = transaction.createTransactionForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], @@ -64,7 +64,7 @@ describe("test delegation transactions factory", function () { } }; - const next = delegationFactory.createTransactionForRemovingNodes({ + const next = transaction.createTransactionForRemovingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -87,7 +87,7 @@ describe("test delegation transactions factory", function () { } }; - const next = delegationFactory.createTransactionForStakingNodes({ + const next = transaction.createTransactionForStakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -110,7 +110,7 @@ describe("test delegation transactions factory", function () { } }; - const next = delegationFactory.createTransactionForUnbondingNodes({ + const next = transaction.createTransactionForUnbondingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -134,7 +134,7 @@ describe("test delegation transactions factory", function () { } }; - const next = delegationFactory.createTransactionForUnstakingNodes({ + const next = transaction.createTransactionForUnstakingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -158,7 +158,7 @@ describe("test delegation transactions factory", function () { } }; - const next = delegationFactory.createTransactionForUnjailingNodes({ + const next = transaction.createTransactionForUnjailingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey] @@ -176,7 +176,7 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const next = delegationFactory.createTransactionForChangingServiceFee({ + const next = transaction.createTransactionForChangingServiceFee({ sender: sender, delegationContract: delegationContract, serviceFee: serviceFee @@ -194,7 +194,7 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const next = delegationFactory.createTransactionForModifyingDelegationCap({ + const next = transaction.createTransactionForModifyingDelegationCap({ sender: sender, delegationContract: delegationContract, delegationCap: delegationCap @@ -211,7 +211,7 @@ describe("test delegation transactions factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = delegationFactory.createTransactionForSettingAutomaticActivation({ + const next = transaction.createTransactionForSettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); @@ -227,7 +227,7 @@ describe("test delegation transactions factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = delegationFactory.createTransactionForUnsettingAutomaticActivation({ + const next = transaction.createTransactionForUnsettingAutomaticActivation({ sender: sender, delegationContract: delegationContract }); @@ -243,7 +243,7 @@ describe("test delegation transactions factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ + const next = transaction.createTransactionForSettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); @@ -259,7 +259,7 @@ describe("test delegation transactions factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ + const next = transaction.createTransactionForUnsettingCapCheckOnRedelegateRewards({ sender: sender, delegationContract: delegationContract }); @@ -275,7 +275,7 @@ describe("test delegation transactions factory", function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = delegationFactory.createTransactionForSettingMetadata({ + const next = transaction.createTransactionForSettingMetadata({ sender: sender, delegationContract: delegationContract, name: "name", diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 354cb8804..0882a0872 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -308,4 +308,4 @@ export class DelegationTransactionsFactory { const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } -} \ No newline at end of file +} diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index eeaeb406d..e535164e5 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -13,13 +13,13 @@ import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); - let factory: SmartContractTransactionsFactory; + let transaction: SmartContractTransactionsFactory; let abiAwareFactory: SmartContractTransactionsFactory; let adderByteCode: Code; let abiRegistry: AbiRegistry; before(async function () { - factory = new SmartContractTransactionsFactory({ + transaction = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer(), }); @@ -41,7 +41,7 @@ describe("test smart contract transactions factory", function () { assert.throws( () => - factory.createTransactionForDeploy({ + transaction.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -57,7 +57,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployNext = factory.createTransactionForDeploy({ + const deployNext = transaction.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -86,7 +86,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -117,7 +117,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const egldAmount = new BigNumber("1000000000000000000"); - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -152,7 +152,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("FOO-6ce17b", 0); const transfer = new NextTokenTransfer(token, 10); - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -190,7 +190,7 @@ describe("test smart contract transactions factory", function () { const barToken = new Token("BAR-5bc08f", 0); const barTransfer = new NextTokenTransfer(barToken, 3140); - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -233,7 +233,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("NFT-123456", 1); const transfer = new NextTokenTransfer(token, 1); - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -279,7 +279,7 @@ describe("test smart contract transactions factory", function () { const secondToken = new Token("NFT-123456", 42); const secondTransfer = new NextTokenTransfer(secondToken, 1); - const executeNext = factory.createTransactionForExecute({ + const executeNext = transaction.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -319,7 +319,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const upgradeNext = factory.createTransactionForUpgrade({ + const upgradeNext = transaction.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 1726d7585..d02789b6d 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -183,4 +183,4 @@ export class SmartContractTransactionsFactory { } return true; } -} \ No newline at end of file +} diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 021601824..d56301cbf 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -7,17 +7,17 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test token management transactions factory", () => { let frank: TestWallet, grace: TestWallet; - let factory: TokenManagementTransactionsFactory; + let transaction: TokenManagementTransactionsFactory; let config: TransactionsFactoryConfig; before(async function () { ({ frank, grace } = await loadTestWallets()); config = new TransactionsFactoryConfig("T"); - factory = new TokenManagementTransactionsFactory(config); + transaction = new TokenManagementTransactionsFactory(config); }); it("should create 'TransactionNext' for registering and setting roles", () => { - const next = factory.createTransactionForRegisteringAndSettingRoles({ + const next = transaction.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", tokenTicker: "TEST", @@ -33,7 +33,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for issuing fungible token", () => { - const next = factory.createTransactionForIssuingFungible({ + const next = transaction.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -54,7 +54,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for issuing semi-fungible token", () => { - const next = factory.createTransactionForIssuingSemiFungible({ + const next = transaction.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -74,7 +74,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for issuing non-fungible token", () => { - const next = factory.createTransactionForIssuingNonFungible({ + const next = transaction.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -94,7 +94,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for registering metaEsdt", () => { - const next = factory.createTransactionForRegisteringMetaESDT({ + const next = transaction.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -115,7 +115,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for setting spcial role on non-fungible token", () => { - const next = factory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ + const next = transaction.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, tokenIdentifier: "FRANK-11ce3e", @@ -133,7 +133,7 @@ describe("test token management transactions factory", () => { }); it("should create 'TransactionNext' for creating nft", () => { - const next = factory.createTransactionForCreatingNFT({ + const next = transaction.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 9ac161a2d..ac5b9bebe 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -121,7 +121,7 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - + return new TransactionNextBuilder({ config: this.config, @@ -623,4 +623,4 @@ IMPORTANT! You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); } -} \ No newline at end of file +} diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index 36d2200bf..2a7194f24 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -66,4 +66,4 @@ export class TransactionNextBuilder { chainID: this.config.toString() }) } -} \ No newline at end of file +} diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 2e4be25bd..7b0ad4ef5 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -7,7 +7,7 @@ import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); - const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); + const transaction = new NextTransferTransactionsFactory(config, new TokenComputer()); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); @@ -17,7 +17,7 @@ describe("test transfer transcations factory", function () { assert.throw( () => { - factory.createTransactionForESDTTokenTransfer({ + transaction.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: transfers, @@ -29,67 +29,67 @@ describe("test transfer transcations factory", function () { }); it("should create 'TransactionNext' for native token transfer without data", async () => { - const transaction = factory.createTransactionForNativeTokenTransfer({ + const next = transaction.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: "1000000000000000000", }); - assert.equal(transaction.sender, alice.bech32()); - assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "1000000000000000000"); - assert.equal(transaction.gasLimit.valueOf(), "50000"); - assert.deepEqual(transaction.data, new Uint8Array()); + assert.equal(next.sender, alice.bech32()); + assert.equal(next.receiver, bob.bech32()); + assert.equal(next.value.valueOf(), "1000000000000000000"); + assert.equal(next.gasLimit.valueOf(), "50000"); + assert.deepEqual(next.data, new Uint8Array()); }); it("should create 'TransactionNext' for native token transfer with data", async () => { - const transaction = factory.createTransactionForNativeTokenTransfer({ + const next = transaction.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: "1000000000000000000", data: "test data", }); - assert.equal(transaction.sender, alice.bech32()); - assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "1000000000000000000"); - assert.equal(transaction.gasLimit.valueOf(), "63500"); - assert.deepEqual(transaction.data, Buffer.from("test data")); + assert.equal(next.sender, alice.bech32()); + assert.equal(next.receiver, bob.bech32()); + assert.equal(next.value.valueOf(), "1000000000000000000"); + assert.equal(next.gasLimit.valueOf(), "63500"); + assert.deepEqual(next.data, Buffer.from("test data")); }); it("should create 'TransactionNext' for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0); const transfer = new NextTokenTransfer(fooToken, 1000000); - const transaction = factory.createTransactionForESDTTokenTransfer({ + const next = transaction.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], }); - assert.equal(transaction.sender, alice.bech32()); - assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "410000"); - assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); + assert.equal(next.sender, alice.bech32()); + assert.equal(next.receiver, bob.bech32()); + assert.equal(next.value.valueOf(), "0"); + assert.equal(next.gasLimit.valueOf(), "410000"); + assert.deepEqual(next.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); it("should create 'TransactionNext' for nft transfer", async () => { const nft = new Token("NFT-123456", 10); const transfer = new NextTokenTransfer(nft, 1); - const transaction = factory.createTransactionForESDTTokenTransfer({ + const next = transaction.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], }); - assert.equal(transaction.sender, alice.bech32()); - assert.equal(transaction.receiver, alice.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "1210500"); + assert.equal(next.sender, alice.bech32()); + assert.equal(next.receiver, alice.bech32()); + assert.equal(next.value.valueOf(), "0"); + assert.equal(next.gasLimit.valueOf(), "1210500"); assert.deepEqual( - transaction.data.toString(), + next.data.toString(), "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8" ); }); @@ -101,18 +101,18 @@ describe("test transfer transcations factory", function () { const secondNft = new Token("TEST-987654", 1); const secondTransfer = new NextTokenTransfer(secondNft, 1); - const transaction = factory.createTransactionForESDTTokenTransfer({ + const next = transaction.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [firstTransfer, secondTransfer], }); - assert.equal(transaction.sender, alice.bech32()); - assert.equal(transaction.receiver, alice.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "1466000"); + assert.equal(next.sender, alice.bech32()); + assert.equal(next.receiver, alice.bech32()); + assert.equal(next.value.valueOf(), "0"); + assert.equal(next.gasLimit.valueOf(), "1466000"); assert.deepEqual( - transaction.data.toString(), + next.data.toString(), "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01" ); }); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 1de3c6b13..a62f20f0b 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -71,7 +71,7 @@ export class NextTransferTransactionsFactory { const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers - ) + ); const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer).multipliedBy(new BigNumber(numberOfTransfers)).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); From 041a2f211f8ee388ac5e5e9fc80928dcd5750061 Mon Sep 17 00:00:00 2001 From: Ramona Lobont Date: Mon, 12 Feb 2024 17:33:15 +0200 Subject: [PATCH 088/275] + prettier --- .../delegationTransactionsFactory.spec.ts | 234 ++++++++++-------- .../delegationTransactionsFactory.ts | 206 +++++++-------- .../smartContractTransactionsFactory.spec.ts | 136 +++++----- .../smartContractTransactionsFactory.ts | 2 - ...anagementTransactionIntentsFactory.spec.ts | 112 +++++---- .../tokenManagementTransactionsFactory.ts | 26 +- .../transactionNextBuilder.ts | 25 +- .../transferTransactionsFactory.spec.ts | 70 +++--- .../transferTransactionsFactory.ts | 11 +- 9 files changed, 423 insertions(+), 399 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index ff4fb4ae8..a36a03343 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -8,7 +8,7 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig("D"); - const transaction = new DelegationTransactionsFactory(config); + const delegationFactory = new DelegationTransactionsFactory(config); it("should create 'TransactionNext' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); @@ -16,42 +16,56 @@ describe("test delegation transactions factory", function () { const serviceFee = 10; const value = new BigNumber("1250000000000000000000"); - const next = transaction.createTransactionForNewDelegationContract({ + const transaction = delegationFactory.createTransactionForNewDelegationContract({ sender: sender, totalDelegationCap: delagationCap, serviceFee: serviceFee, - amount: value + amount: value, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, DELEGATION_MANAGER_SC_ADDRESS); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); - assert.equal(next.gasLimit.valueOf(), 60126500); - assert.equal(next.value, value); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, DELEGATION_MANAGER_SC_ADDRESS); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); + assert.equal(transaction.gasLimit.valueOf(), 60126500); + assert.equal(transaction.value, value); }); it("should create 'TransactionNext' for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const publicKey = new ValidatorPublicKey(Buffer.from("e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", "hex")); + const publicKey = new ValidatorPublicKey( + Buffer.from( + "e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", + "hex", + ), + ); const mockMessage = { - getSignature: () => Buffer.from("81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", "hex") - } + getSignature: () => + Buffer.from( + "81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", + "hex", + ), + }; - const next = transaction.createTransactionForAddingNodes({ + const transaction = delegationFactory.createTransactionForAddingNodes({ sender: sender, delegationContract: delegationContract, publicKeys: [publicKey], - signedMessages: [mockMessage.getSignature()] + signedMessages: [mockMessage.getSignature()], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual( + transaction.data, + Buffer.from( + "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", + ), + ); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for removing nodes", async function () { @@ -61,20 +75,20 @@ describe("test delegation transactions factory", function () { const publicKey = { hex(): string { return Buffer.from("abba").toString("hex"); - } + }, }; - const next = transaction.createTransactionForRemovingNodes({ + const transaction = delegationFactory.createTransactionForRemovingNodes({ sender: sender, delegationContract: delegationContract, - publicKeys: [publicKey] + publicKeys: [publicKey], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("removeNodes@61626261")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("removeNodes@61626261")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for staking nodes", async function () { @@ -84,20 +98,20 @@ describe("test delegation transactions factory", function () { const publicKey = { hex(): string { return Buffer.from("abba").toString("hex"); - } + }, }; - const next = transaction.createTransactionForStakingNodes({ + const transaction = delegationFactory.createTransactionForStakingNodes({ sender: sender, delegationContract: delegationContract, - publicKeys: [publicKey] + publicKeys: [publicKey], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("stakeNodes@61626261")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("stakeNodes@61626261")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for unbonding nodes", async function () { @@ -107,21 +121,21 @@ describe("test delegation transactions factory", function () { const publicKey = { hex(): string { return Buffer.from("abba").toString("hex"); - } + }, }; - const next = transaction.createTransactionForUnbondingNodes({ + const transaction = delegationFactory.createTransactionForUnbondingNodes({ sender: sender, delegationContract: delegationContract, - publicKeys: [publicKey] + publicKeys: [publicKey], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("unBondNodes@61626261")); - assert.equal(next.value, 0); - assert.equal(next.gasLimit.valueOf(), 12080000); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("unBondNodes@61626261")); + assert.equal(transaction.value, 0); + assert.equal(transaction.gasLimit.valueOf(), 12080000); }); it("should create 'TransactionNext' for unstaking nodes", async function () { @@ -131,21 +145,21 @@ describe("test delegation transactions factory", function () { const publicKey = { hex(): string { return Buffer.from("abba").toString("hex"); - } + }, }; - const next = transaction.createTransactionForUnstakingNodes({ + const transaction = delegationFactory.createTransactionForUnstakingNodes({ sender: sender, delegationContract: delegationContract, - publicKeys: [publicKey] + publicKeys: [publicKey], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("unStakeNodes@61626261")); - assert.equal(next.value, 0); - assert.equal(next.gasLimit.valueOf(), 12081500); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("unStakeNodes@61626261")); + assert.equal(transaction.value, 0); + assert.equal(transaction.gasLimit.valueOf(), 12081500); }); it("should create 'TransactionNext' for unjailing nodes", async function () { @@ -155,20 +169,20 @@ describe("test delegation transactions factory", function () { const publicKey = { hex(): string { return Buffer.from("abba").toString("hex"); - } + }, }; - const next = transaction.createTransactionForUnjailingNodes({ + const transaction = delegationFactory.createTransactionForUnjailingNodes({ sender: sender, delegationContract: delegationContract, - publicKeys: [publicKey] + publicKeys: [publicKey], }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("unJailNodes@61626261")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("unJailNodes@61626261")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for changing service fee", async function () { @@ -176,17 +190,17 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = new BigNumber(10); - const next = transaction.createTransactionForChangingServiceFee({ + const transaction = delegationFactory.createTransactionForChangingServiceFee({ sender: sender, delegationContract: delegationContract, - serviceFee: serviceFee + serviceFee: serviceFee, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("changeServiceFee@0a")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("changeServiceFee@0a")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for changing delegation cap", async function () { @@ -194,99 +208,99 @@ describe("test delegation transactions factory", function () { const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = new BigNumber("5000000000000000000000"); - const next = transaction.createTransactionForModifyingDelegationCap({ + const transaction = delegationFactory.createTransactionForModifyingDelegationCap({ sender: sender, delegationContract: delegationContract, - delegationCap: delegationCap + delegationCap: delegationCap, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = transaction.createTransactionForSettingAutomaticActivation({ + const transaction = delegationFactory.createTransactionForSettingAutomaticActivation({ sender: sender, - delegationContract: delegationContract + delegationContract: delegationContract, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("setAutomaticActivation@74727565")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("setAutomaticActivation@74727565")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = transaction.createTransactionForUnsettingAutomaticActivation({ + const transaction = delegationFactory.createTransactionForUnsettingAutomaticActivation({ sender: sender, - delegationContract: delegationContract + delegationContract: delegationContract, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("setAutomaticActivation@66616c7365")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("setAutomaticActivation@66616c7365")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = transaction.createTransactionForSettingCapCheckOnRedelegateRewards({ + const transaction = delegationFactory.createTransactionForSettingCapCheckOnRedelegateRewards({ sender: sender, - delegationContract: delegationContract + delegationContract: delegationContract, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = transaction.createTransactionForUnsettingCapCheckOnRedelegateRewards({ + const transaction = delegationFactory.createTransactionForUnsettingCapCheckOnRedelegateRewards({ sender: sender, - delegationContract: delegationContract + delegationContract: delegationContract, }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const next = transaction.createTransactionForSettingMetadata({ + const transaction = delegationFactory.createTransactionForSettingMetadata({ sender: sender, delegationContract: delegationContract, name: "name", website: "website", - identifier: "identifier" + identifier: "identifier", }); - assert.equal(next.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - assert.isDefined(next.data); - assert.deepEqual(next.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); - assert.equal(next.value, 0); + assert.equal(transaction.sender, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); + assert.isDefined(transaction.data); + assert.deepEqual(transaction.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); + assert.equal(transaction.value, 0); }); }); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 0882a0872..a77ecaccc 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -27,17 +27,19 @@ export class DelegationTransactionsFactory { this.config = config; } createTransactionForNewDelegationContract(options: { - sender: IAddress, - totalDelegationCap: BigNumber.Value, - serviceFee: BigNumber.Value, - amount: BigNumber.Value + sender: IAddress; + totalDelegationCap: BigNumber.Value; + serviceFee: BigNumber.Value; + amount: BigNumber.Value; }): TransactionNext { const dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), - numberToPaddedHex(options.serviceFee.toString()) + numberToPaddedHex(options.serviceFee.toString()), ]; - const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus(this.config.additionalGasLimitForDelegationOperations); + const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus( + this.config.additionalGasLimitForDelegationOperations, + ); return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -45,14 +47,14 @@ export class DelegationTransactionsFactory { dataParts: dataParts, gasLimit: executionGasLimit, addDataMovementGas: true, - amount: options.amount + amount: options.amount, }).build(); } createTransactionForAddingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[], - signedMessages: Uint8Array[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; + signedMessages: Uint8Array[]; }): TransactionNext { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); @@ -68,13 +70,13 @@ export class DelegationTransactionsFactory { receiver: options.delegationContract, dataParts: dataParts, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForRemovingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; }): TransactionNext { const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { @@ -87,82 +89,84 @@ export class DelegationTransactionsFactory { receiver: options.delegationContract, dataParts: dataParts, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForStakingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } const numNodes = options.publicKeys.length; - const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy(this.config.additionalGasLimitPerValidatorNode); - const executionGasLimit = additionalGasForAllNodes.plus(this.config.gasLimitStake).plus( - this.config.gasLimitDelegationOperations + const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy( + this.config.additionalGasLimitPerValidatorNode, ); + const executionGasLimit = additionalGasForAllNodes + .plus(this.config.gasLimitStake) + .plus(this.config.gasLimitDelegationOperations); return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, gasLimit: executionGasLimit, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForUnbondingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes).multipliedBy( - this.config.additionalGasLimitPerValidatorNode).plus( - this.config.gasLimitUnbond - ).plus(this.config.gasLimitDelegationOperations); + const executionGasLimit = new BigNumber(numNodes) + .multipliedBy(this.config.additionalGasLimitPerValidatorNode) + .plus(this.config.gasLimitUnbond) + .plus(this.config.gasLimitDelegationOperations); return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, gasLimit: executionGasLimit, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForUnstakingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes).multipliedBy( - this.config.additionalGasLimitPerValidatorNode).plus( - this.config.gasLimitUnstake - ).plus(this.config.gasLimitDelegationOperations); + const executionGasLimit = new BigNumber(numNodes) + .multipliedBy(this.config.additionalGasLimitPerValidatorNode) + .plus(this.config.gasLimitUnstake) + .plus(this.config.gasLimitDelegationOperations); return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, gasLimit: executionGasLimit, - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForUnjailingNodes(options: { - sender: IAddress, - delegationContract: IAddress, - publicKeys: IValidatorPublicKey[] + sender: IAddress; + delegationContract: IAddress; + publicKeys: IValidatorPublicKey[]; }): TransactionNext { const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { @@ -175,137 +179,135 @@ export class DelegationTransactionsFactory { receiver: options.delegationContract, dataParts: dataParts, gasLimit: this.computeExecutionGasLimitForNodesManagement(numNodes), - addDataMovementGas: true + addDataMovementGas: true, }).build(); } createTransactionForChangingServiceFee(options: { - sender: IAddress, - delegationContract: IAddress, - serviceFee: BigNumber.Value + sender: IAddress; + delegationContract: IAddress; + serviceFee: BigNumber.Value; }): TransactionNext { - const dataParts = [ - "changeServiceFee", - numberToPaddedHex(options.serviceFee) - ]; + const dataParts = ["changeServiceFee", numberToPaddedHex(options.serviceFee)]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForModifyingDelegationCap(options: { - sender: IAddress, - delegationContract: IAddress, - delegationCap: BigNumber.Value + sender: IAddress; + delegationContract: IAddress; + delegationCap: BigNumber.Value; }): TransactionNext { - const dataParts = [ - "modifyTotalDelegationCap", - numberToPaddedHex(options.delegationCap) - ]; + const dataParts = ["modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap)]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForSettingAutomaticActivation(options: { - sender: IAddress, - delegationContract: IAddress + sender: IAddress; + delegationContract: IAddress; }): TransactionNext { - const dataParts = [ - "setAutomaticActivation", - utf8ToHex("true") - ]; + const dataParts = ["setAutomaticActivation", utf8ToHex("true")]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForUnsettingAutomaticActivation(options: { - sender: IAddress, - delegationContract: IAddress + sender: IAddress; + delegationContract: IAddress; }): TransactionNext { - const dataParts = [ - "setAutomaticActivation", - utf8ToHex("false") - ]; + const dataParts = ["setAutomaticActivation", utf8ToHex("false")]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForSettingCapCheckOnRedelegateRewards(options: { - sender: IAddress, - delegationContract: IAddress + sender: IAddress; + delegationContract: IAddress; }): TransactionNext { - const dataParts = [ - "setCheckCapOnReDelegateRewards", - utf8ToHex("true") - ]; + const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("true")]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { - sender: IAddress, - delegationContract: IAddress + sender: IAddress; + delegationContract: IAddress; }): TransactionNext { - const dataParts = [ - "setCheckCapOnReDelegateRewards", - utf8ToHex("false") - ]; + const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("false")]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } createTransactionForSettingMetadata(options: { - sender: IAddress, - delegationContract: IAddress, - name: string, - website: string, - identifier: string + sender: IAddress; + delegationContract: IAddress; + name: string; + website: string; + identifier: string; }): TransactionNext { const dataParts = [ "setMetaData", utf8ToHex(options.name), utf8ToHex(options.website), - utf8ToHex(options.identifier) + utf8ToHex(options.identifier), ]; return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus(this.config.additionalGasLimitForDelegationOperations), - addDataMovementGas: true + gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ), + addDataMovementGas: true, }).build(); } private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { - const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy(numNodes); + const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy( + numNodes, + ); return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index e535164e5..d4ab3c621 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -13,13 +13,13 @@ import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); - let transaction: SmartContractTransactionsFactory; + let smartContractFactory: SmartContractTransactionsFactory; let abiAwareFactory: SmartContractTransactionsFactory; let adderByteCode: Code; let abiRegistry: AbiRegistry; before(async function () { - transaction = new SmartContractTransactionsFactory({ + smartContractFactory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer(), }); @@ -41,14 +41,14 @@ describe("test smart contract transactions factory", function () { assert.throws( () => - transaction.createTransactionForDeploy({ + smartContractFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, args: args, }), Err, - "Can't convert args to TypedValues" + "Can't convert args to TypedValues", ); }); @@ -57,7 +57,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const deployNext = transaction.createTransactionForDeploy({ + const transaction = smartContractFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -70,13 +70,13 @@ describe("test smart contract transactions factory", function () { args: args, }); - assert.equal(deployNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(deployNext.receiver, CONTRACT_DEPLOY_ADDRESS); - expect(deployNext.data.length).to.be.greaterThan(0); - assert.equal(deployNext.gasLimit.valueOf(), gasLimit); - assert.equal(deployNext.value, 0); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, CONTRACT_DEPLOY_ADDRESS); + expect(transaction.data.length).to.be.greaterThan(0); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value, 0); - assert.deepEqual(deployNext, abiDeployNext); + assert.deepEqual(transaction, abiDeployNext); }); it("should create 'TransactionNext' for execute without transfer", async function () { @@ -86,7 +86,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -101,13 +101,13 @@ describe("test smart contract transactions factory", function () { args: args, }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeNext.data, Buffer.from("add@07")); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value, 0); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(transaction.data, Buffer.from("add@07")); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value, 0); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for execute and transfer native token", async function () { @@ -117,7 +117,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const egldAmount = new BigNumber("1000000000000000000"); - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -134,13 +134,13 @@ describe("test smart contract transactions factory", function () { nativeTransferAmount: egldAmount, }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeNext.data, Buffer.from("add@07")); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(transaction.data, Buffer.from("add@07")); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value.valueOf(), "1000000000000000000"); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for execute and transfer single esdt", async function () { @@ -152,7 +152,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("FOO-6ce17b", 0); const transfer = new NextTokenTransfer(token, 10); - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -169,13 +169,13 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [transfer], }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.deepEqual(executeNext.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value.valueOf(), "0"); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.deepEqual(transaction.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value.valueOf(), "0"); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for execute and transfer multiple esdts", async function () { @@ -190,7 +190,7 @@ describe("test smart contract transactions factory", function () { const barToken = new Token("BAR-5bc08f", 0); const barTransfer = new NextTokenTransfer(barToken, 3140); - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -207,20 +207,20 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [fooTransfer, barTransfer], }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.deepEqual( - executeNext.data, + transaction.data, Buffer.from( - "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07" - ) + "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07", + ), ); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value.valueOf(), "0"); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for execute and transfer single nft", async function () { @@ -233,7 +233,7 @@ describe("test smart contract transactions factory", function () { const token = new Token("NFT-123456", 1); const transfer = new NextTokenTransfer(token, 1); - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -250,21 +250,21 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [transfer], }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.isDefined(executeNext.data); + assert.isDefined(transaction.data); assert.deepEqual( - executeNext.data, + transaction.data, Buffer.from( - "ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07" - ) + "ESDTNFTTransfer@4e46542d313233343536@01@01@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@616464@07", + ), ); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value.valueOf(), "0"); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for execute and transfer multiple nfts", async function () { @@ -279,7 +279,7 @@ describe("test smart contract transactions factory", function () { const secondToken = new Token("NFT-123456", 42); const secondTransfer = new NextTokenTransfer(secondToken, 1); - const executeNext = transaction.createTransactionForExecute({ + const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -296,21 +296,21 @@ describe("test smart contract transactions factory", function () { tokenTransfers: [firstTransfer, secondTransfer], }); - assert.equal(executeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(executeNext.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.isDefined(executeNext.data); + assert.isDefined(transaction.data); assert.deepEqual( - executeNext.data, + transaction.data, Buffer.from( - "MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07" - ) + "MultiESDTNFTTransfer@00000000000000000500b9353fe8407f87310c87e12fa1ac807f0485da39d152@02@4e46542d313233343536@01@01@4e46542d313233343536@2a@01@616464@07", + ), ); - assert.equal(executeNext.gasLimit.valueOf(), gasLimit); - assert.equal(executeNext.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value.valueOf(), "0"); - assert.deepEqual(executeNext, abiExecuteNext); + assert.deepEqual(transaction, abiExecuteNext); }); it("should create 'TransactionNext' for upgrade", async function () { @@ -319,7 +319,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(0)]; - const upgradeNext = transaction.createTransactionForUpgrade({ + const transaction = smartContractFactory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -335,12 +335,12 @@ describe("test smart contract transactions factory", function () { args: args, }); - assert.equal(upgradeNext.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - assert.equal(upgradeNext.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - assert.isTrue(Buffer.from(upgradeNext.data!).toString().startsWith("upgradeContract@")); - assert.equal(upgradeNext.gasLimit.valueOf(), gasLimit); - assert.equal(upgradeNext.value, 0); + assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); + assert.isTrue(Buffer.from(transaction.data!).toString().startsWith("upgradeContract@")); + assert.equal(transaction.gasLimit.valueOf(), gasLimit); + assert.equal(transaction.value, 0); - assert.deepEqual(upgradeNext, abiUpgradeNext); + assert.deepEqual(transaction, abiUpgradeNext); }); }); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d02789b6d..d784cc89f 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -11,7 +11,6 @@ import { Token, NextTokenTransfer } from "../tokens"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionNext } from "../transaction"; - interface Config { chainID: string; minGasLimit: BigNumber.Value; @@ -151,7 +150,6 @@ export class SmartContractTransactionsFactory { parts = parts.concat(preparedArgs); - return new TransactionNextBuilder({ config: this.config, sender: options.sender, diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index d56301cbf..b675e0ce1 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -7,33 +7,33 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test token management transactions factory", () => { let frank: TestWallet, grace: TestWallet; - let transaction: TokenManagementTransactionsFactory; + let tokenManagementFactory: TokenManagementTransactionsFactory; let config: TransactionsFactoryConfig; before(async function () { ({ frank, grace } = await loadTestWallets()); config = new TransactionsFactoryConfig("T"); - transaction = new TokenManagementTransactionsFactory(config); + tokenManagementFactory = new TokenManagementTransactionsFactory(config); }); it("should create 'TransactionNext' for registering and setting roles", () => { - const next = transaction.createTransactionForRegisteringAndSettingRoles({ + const transaction = tokenManagementFactory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", tokenTicker: "TEST", tokenType: "FNG", - numDecimals: 2 + numDecimals: 2, }); - assert.deepEqual(next.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); - assert.deepEqual(next.value, config.issueCost); - assert.deepEqual(next.gasLimit, new BigNumber("60125000")); + assert.deepEqual(transaction.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); + assert.deepEqual(transaction.value, config.issueCost); + assert.deepEqual(transaction.gasLimit, new BigNumber("60125000")); }); it("should create 'TransactionNext' for issuing fungible token", () => { - const next = transaction.createTransactionForIssuingFungible({ + const next = tokenManagementFactory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -44,17 +44,22 @@ describe("test token management transactions factory", () => { canPause: true, canChangeOwner: true, canUpgrade: false, - canAddSpecialRoles: false + canAddSpecialRoles: false, }); - assert.deepEqual(next.data, Buffer.from("issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); + assert.deepEqual( + next.data, + Buffer.from( + "issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + ), + ); assert.equal(next.sender, frank.address.toString()); assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); assert.deepEqual(next.value, config.issueCost); }); it("should create 'TransactionNext' for issuing semi-fungible token", () => { - const next = transaction.createTransactionForIssuingSemiFungible({ + const transaction = tokenManagementFactory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -64,17 +69,22 @@ describe("test token management transactions factory", () => { canTransferNFTCreateRole: true, canChangeOwner: true, canUpgrade: false, - canAddSpecialRoles: false + canAddSpecialRoles: false, }); - assert.deepEqual(next.data, Buffer.from("issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(next.value, config.issueCost); + assert.deepEqual( + transaction.data, + Buffer.from( + "issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + ), + ); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(transaction.value, config.issueCost); }); it("should create 'TransactionNext' for issuing non-fungible token", () => { - const next = transaction.createTransactionForIssuingNonFungible({ + const transaction = tokenManagementFactory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -84,17 +94,22 @@ describe("test token management transactions factory", () => { canTransferNFTCreateRole: true, canChangeOwner: true, canUpgrade: false, - canAddSpecialRoles: false + canAddSpecialRoles: false, }); - assert.deepEqual(next.data, Buffer.from("issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(next.value, config.issueCost); + assert.deepEqual( + transaction.data, + Buffer.from( + "issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + ), + ); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(transaction.value, config.issueCost); }); it("should create 'TransactionNext' for registering metaEsdt", () => { - const next = transaction.createTransactionForRegisteringMetaESDT({ + const transaction = tokenManagementFactory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -105,17 +120,22 @@ describe("test token management transactions factory", () => { canTransferNFTCreateRole: true, canChangeOwner: true, canUpgrade: false, - canAddSpecialRoles: false + canAddSpecialRoles: false, }); - assert.deepEqual(next.data, Buffer.from("registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365")); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(next.value, config.issueCost); + assert.deepEqual( + transaction.data, + Buffer.from( + "registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + ), + ); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(transaction.value, config.issueCost); }); it("should create 'TransactionNext' for setting spcial role on non-fungible token", () => { - const next = transaction.createTransactionForSettingSpecialRoleOnNonFungibleToken({ + const transaction = tokenManagementFactory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, tokenIdentifier: "FRANK-11ce3e", @@ -123,17 +143,22 @@ describe("test token management transactions factory", () => { addRoleNFTBurn: false, addRoleNFTUpdateAttributes: true, addRoleNFTAddURI: true, - addRoleESDTTransferRole: false + addRoleESDTTransferRole: false, }); - assert.deepEqual(next.data, Buffer.from("setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249")); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); - assert.equal(next.value, 0); + assert.deepEqual( + transaction.data, + Buffer.from( + "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249", + ), + ); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); + assert.equal(transaction.value, 0); }); it("should create 'TransactionNext' for creating nft", () => { - const next = transaction.createTransactionForCreatingNFT({ + const transaction = tokenManagementFactory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", initialQuantity: 1, @@ -141,12 +166,15 @@ describe("test token management transactions factory", () => { royalties: 1000, hash: "abba", attributes: Buffer.from("test"), - uris: ["a", "b"] + uris: ["a", "b"], }); - assert.deepEqual(next.data, Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62")); - assert.equal(next.sender, grace.address.toString()); - assert.equal(next.receiver, grace.address.toString()); - assert.equal(next.value, 0); + assert.deepEqual( + transaction.data, + Buffer.from("ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62"), + ); + assert.equal(transaction.sender, grace.address.toString()); + assert.equal(transaction.receiver, grace.address.toString()); + assert.equal(transaction.value, 0); }); }); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index ac5b9bebe..508c1e289 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -7,7 +7,6 @@ import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.c import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; - interface Config { chainID: string; minGasLimit: BigNumber.Value; @@ -76,7 +75,6 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -121,8 +119,7 @@ export class TokenManagementTransactionsFactory { utf8ToHex("canAddSpecialRoles"), options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - - + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -168,7 +165,6 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -216,7 +212,6 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -245,7 +240,6 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.numDecimals), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -304,7 +298,6 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -334,7 +327,6 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -378,7 +370,6 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -410,12 +401,10 @@ export class TokenManagementTransactionsFactory { ...options.uris.map(utf8ToHex), ]; - // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -426,10 +415,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForPausing(options: { - sender: IAddress; - tokenIdentifier: string - }): TransactionNext { + createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; return new TransactionNextBuilder({ @@ -442,10 +428,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForUnpausing(options: { - sender: IAddress; - tokenIdentifier: string - }): TransactionNext { + createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; return new TransactionNextBuilder({ @@ -556,7 +539,6 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -580,7 +562,6 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.quantityToAdd), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -604,7 +585,6 @@ export class TokenManagementTransactionsFactory { bigIntToHex(options.quantityToBurn), ]; - return new TransactionNextBuilder({ config: this.config, sender: options.sender, diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index 2a7194f24..c4b440f6d 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -4,7 +4,6 @@ import { ARGUMENTS_SEPARATOR } from "../constants"; import { TransactionPayload } from "../transactionPayload"; import { TransactionNext } from "../transaction"; - interface Config { chainID: string; minGasLimit: BigNumber.Value; @@ -21,13 +20,13 @@ export class TransactionNextBuilder { private amount?: BigNumber.Value; constructor(options: { - config: Config, - sender: IAddress, - receiver: IAddress, - dataParts: string[], - gasLimit: BigNumber.Value, - addDataMovementGas: boolean, - amount?: BigNumber.Value, + config: Config; + sender: IAddress; + receiver: IAddress; + dataParts: string[]; + gasLimit: BigNumber.Value; + addDataMovementGas: boolean; + amount?: BigNumber.Value; }) { this.config = options.config; this.sender = options.sender; @@ -43,7 +42,9 @@ export class TransactionNextBuilder { return this.providedGasLimit; } - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus(new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length())); + const dataMovementGas = new BigNumber(this.config.minGasLimit).plus( + new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length()), + ); const gasLimit = dataMovementGas.plus(this.providedGasLimit); return gasLimit; } @@ -54,7 +55,7 @@ export class TransactionNextBuilder { } build(): TransactionNext { - const data = this.buildTransactionPayload() + const data = this.buildTransactionPayload(); const gasLimit = this.computeGasLimit(data); return new TransactionNext({ @@ -63,7 +64,7 @@ export class TransactionNextBuilder { gasLimit: gasLimit, value: this.amount || 0, data: data.valueOf(), - chainID: this.config.toString() - }) + chainID: this.config.toString(), + }); } } diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 7b0ad4ef5..2f6091593 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -7,7 +7,7 @@ import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); - const transaction = new NextTransferTransactionsFactory(config, new TokenComputer()); + const nextTransferFactory = new NextTransferTransactionsFactory(config, new TokenComputer()); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); @@ -17,80 +17,80 @@ describe("test transfer transcations factory", function () { assert.throw( () => { - transaction.createTransactionForESDTTokenTransfer({ + nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: transfers, }); }, ErrBadUsage, - "No token transfer has been provided" + "No token transfer has been provided", ); }); it("should create 'TransactionNext' for native token transfer without data", async () => { - const next = transaction.createTransactionForNativeTokenTransfer({ + const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: "1000000000000000000", }); - assert.equal(next.sender, alice.bech32()); - assert.equal(next.receiver, bob.bech32()); - assert.equal(next.value.valueOf(), "1000000000000000000"); - assert.equal(next.gasLimit.valueOf(), "50000"); - assert.deepEqual(next.data, new Uint8Array()); + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.gasLimit.valueOf(), "50000"); + assert.deepEqual(transaction.data, new Uint8Array()); }); it("should create 'TransactionNext' for native token transfer with data", async () => { - const next = transaction.createTransactionForNativeTokenTransfer({ + const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: "1000000000000000000", data: "test data", }); - assert.equal(next.sender, alice.bech32()); - assert.equal(next.receiver, bob.bech32()); - assert.equal(next.value.valueOf(), "1000000000000000000"); - assert.equal(next.gasLimit.valueOf(), "63500"); - assert.deepEqual(next.data, Buffer.from("test data")); + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.gasLimit.valueOf(), "63500"); + assert.deepEqual(transaction.data, Buffer.from("test data")); }); it("should create 'TransactionNext' for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0); const transfer = new NextTokenTransfer(fooToken, 1000000); - const next = transaction.createTransactionForESDTTokenTransfer({ + const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], }); - assert.equal(next.sender, alice.bech32()); - assert.equal(next.receiver, bob.bech32()); - assert.equal(next.value.valueOf(), "0"); - assert.equal(next.gasLimit.valueOf(), "410000"); - assert.deepEqual(next.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, bob.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "410000"); + assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); it("should create 'TransactionNext' for nft transfer", async () => { const nft = new Token("NFT-123456", 10); const transfer = new NextTokenTransfer(nft, 1); - const next = transaction.createTransactionForESDTTokenTransfer({ + const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], }); - assert.equal(next.sender, alice.bech32()); - assert.equal(next.receiver, alice.bech32()); - assert.equal(next.value.valueOf(), "0"); - assert.equal(next.gasLimit.valueOf(), "1210500"); + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, alice.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "1210500"); assert.deepEqual( - next.data.toString(), - "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8" + transaction.data.toString(), + "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8", ); }); @@ -101,19 +101,19 @@ describe("test transfer transcations factory", function () { const secondNft = new Token("TEST-987654", 1); const secondTransfer = new NextTokenTransfer(secondNft, 1); - const next = transaction.createTransactionForESDTTokenTransfer({ + const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [firstTransfer, secondTransfer], }); - assert.equal(next.sender, alice.bech32()); - assert.equal(next.receiver, alice.bech32()); - assert.equal(next.value.valueOf(), "0"); - assert.equal(next.gasLimit.valueOf(), "1466000"); + assert.equal(transaction.sender, alice.bech32()); + assert.equal(transaction.receiver, alice.bech32()); + assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit.valueOf(), "1466000"); assert.deepEqual( - next.data.toString(), - "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01" + transaction.data.toString(), + "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01", ); }); }); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index a62f20f0b..ad606c652 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -6,7 +6,6 @@ import { ErrBadUsage } from "../errors"; import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; - const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -70,10 +69,12 @@ export class NextTransferTransactionsFactory { const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( options.receiver, - options.tokenTransfers + options.tokenTransfers, ); - const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer).multipliedBy(new BigNumber(numberOfTransfers)).plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) + .multipliedBy(new BigNumber(numberOfTransfers)) + .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); return new TransactionNextBuilder({ config: this.config, @@ -98,12 +99,12 @@ export class NextTransferTransactionsFactory { if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER) + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER), ); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER) + new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER), ); receiver = options.sender; } From 097384d78c193c06b3b549d15632850e08baa23e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 13 Feb 2024 12:05:41 +0200 Subject: [PATCH 089/275] fix: add empty lines and run prettier --- .../delegationTransactionsFactory.ts | 96 +++++++++++++++---- .../relayedTransactionsFactory.spec.ts | 22 ++--- .../relayedTransactionsFactory.ts | 4 +- .../smartContractTransactionsFactory.ts | 2 - .../tokenTransfersDataBuilder.ts | 4 +- 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index a77ecaccc..9e389ab69 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -6,6 +6,7 @@ import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; import { TransactionNext } from "../transaction"; + interface Config { chainID: string; minGasLimit: BigNumber.Value; @@ -18,14 +19,18 @@ interface Config { additionalGasLimitPerValidatorNode: BigNumber.Value; additionalGasLimitForDelegationOperations: BigNumber.Value; } + interface IValidatorPublicKey { hex(): string; } + export class DelegationTransactionsFactory { private readonly config: Config; + constructor(config: Config) { this.config = config; } + createTransactionForNewDelegationContract(options: { sender: IAddress; totalDelegationCap: BigNumber.Value; @@ -37,9 +42,11 @@ export class DelegationTransactionsFactory { numberToPaddedHex(options.totalDelegationCap.toString()), numberToPaddedHex(options.serviceFee.toString()), ]; + const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus( this.config.additionalGasLimitForDelegationOperations, ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -50,6 +57,7 @@ export class DelegationTransactionsFactory { amount: options.amount, }).build(); } + createTransactionForAddingNodes(options: { sender: IAddress; delegationContract: IAddress; @@ -59,11 +67,14 @@ export class DelegationTransactionsFactory { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } + const numNodes = options.publicKeys.length; const dataParts = ["addNodes"]; + for (let i = 0; i < numNodes; i++) { dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -73,15 +84,18 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForRemovingNodes(options: { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; }): TransactionNext { const dataParts = ["removeNodes"]; + for (const key of options.publicKeys) { dataParts.push(key.hex()); } + const numNodes = options.publicKeys.length; return new TransactionNextBuilder({ config: this.config, @@ -92,22 +106,27 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForStakingNodes(options: { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["stakeNodes"]; + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } + const numNodes = options.publicKeys.length; const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy( this.config.additionalGasLimitPerValidatorNode, ); + const executionGasLimit = additionalGasForAllNodes .plus(this.config.gasLimitStake) .plus(this.config.gasLimitDelegationOperations); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -117,20 +136,24 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForUnbondingNodes(options: { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["unBondNodes"]; + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } + const numNodes = options.publicKeys.length; const executionGasLimit = new BigNumber(numNodes) .multipliedBy(this.config.additionalGasLimitPerValidatorNode) .plus(this.config.gasLimitUnbond) .plus(this.config.gasLimitDelegationOperations); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -140,20 +163,24 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForUnstakingNodes(options: { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; }): TransactionNext { let dataParts = ["unStakeNodes"]; + for (const key of options.publicKeys) { dataParts = dataParts.concat(key.hex()); } + const numNodes = options.publicKeys.length; const executionGasLimit = new BigNumber(numNodes) .multipliedBy(this.config.additionalGasLimitPerValidatorNode) .plus(this.config.gasLimitUnstake) .plus(this.config.gasLimitDelegationOperations); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, @@ -163,15 +190,18 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForUnjailingNodes(options: { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; }): TransactionNext { const dataParts = ["unJailNodes"]; + for (const key of options.publicKeys) { dataParts.push(key.hex()); } + const numNodes = options.publicKeys.length; return new TransactionNextBuilder({ config: this.config, @@ -182,104 +212,123 @@ export class DelegationTransactionsFactory { addDataMovementGas: true, }).build(); } + createTransactionForChangingServiceFee(options: { sender: IAddress; delegationContract: IAddress; serviceFee: BigNumber.Value; }): TransactionNext { const dataParts = ["changeServiceFee", numberToPaddedHex(options.serviceFee)]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForModifyingDelegationCap(options: { sender: IAddress; delegationContract: IAddress; delegationCap: BigNumber.Value; }): TransactionNext { const dataParts = ["modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap)]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForSettingAutomaticActivation(options: { sender: IAddress; delegationContract: IAddress; }): TransactionNext { const dataParts = ["setAutomaticActivation", utf8ToHex("true")]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress; delegationContract: IAddress; }): TransactionNext { const dataParts = ["setAutomaticActivation", utf8ToHex("false")]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress; delegationContract: IAddress; }): TransactionNext { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("true")]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress; delegationContract: IAddress; }): TransactionNext { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("false")]; + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + createTransactionForSettingMetadata(options: { sender: IAddress; delegationContract: IAddress; @@ -293,21 +342,26 @@ export class DelegationTransactionsFactory { utf8ToHex(options.website), utf8ToHex(options.identifier), ]; + + const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( + this.config.additionalGasLimitForDelegationOperations, + ); + return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ), + gasLimit: gasLimit, addDataMovementGas: true, }).build(); } + private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy( numNodes, ); + return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); } } diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 50be725c2..daa36d93a 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -62,11 +62,11 @@ describe("test relayed v1 transaction builder", function () { assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2272525455544858677a4273496e4f6e454b6b7869642b354e66524d486e33534948314673746f577352434c434b3258514c41614f4e704449346531476173624c5150616130566f364144516d4f2b52446b6f364a43413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a327d" + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2272525455544858677a4273496e4f6e454b6b7869642b354e66524d486e33534948314673746f577352434c434b3258514c41614f4e704449346531476173624c5150616130566f364144516d4f2b52446b6f364a43413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a327d", ); assert.equal( Buffer.from(relayedTransaction.signature).toString("hex"), - "128e7cdc14c2b9beee2f3ff7a7fa5d1f5ef31a654a0c92e223c90ab28265fa277d306f23a06536248cf9573e828017004fb639617fade4d68a37524aafca710d" + "128e7cdc14c2b9beee2f3ff7a7fa5d1f5ef31a654a0c92e223c90ab28265fa277d306f23a06536248cf9573e828017004fb639617fade4d68a37524aafca710d", ); }); @@ -96,11 +96,11 @@ describe("test relayed v1 transaction builder", function () { assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a226a33427a6469554144325963517473576c65707663664a6f75657a48573063316b735a424a4d6339573167435450512b6870636759457858326f6f367a4b5654347464314b4b6f79783841526a346e336474576c44413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d" + "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a226a33427a6469554144325963517473576c65707663664a6f75657a48573063316b735a424a4d6339573167435450512b6870636759457858326f6f367a4b5654347464314b4b6f79783841526a346e336474576c44413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d", ); assert.equal( Buffer.from(relayedTransaction.signature).toString("hex"), - "3787d640e5a579e7977a4a1bcdd435ad11855632fa4a414a06fbf8355692d1a58d76ef0adbdd6ccd6bd3c329f36bd53c180d4873ec1a6c558e659aeb9ab92d00" + "3787d640e5a579e7977a4a1bcdd435ad11855632fa4a414a06fbf8355692d1a58d76ef0adbdd6ccd6bd3c329f36bd53c180d4873ec1a6c558e659aeb9ab92d00", ); }); @@ -130,11 +130,11 @@ describe("test relayed v1 transaction builder", function () { assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313939393939393030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22594661677972512f726d614c7333766e7159307657553858415a7939354b4e31725738347a4f764b62376c7a3773576e2f566a546d68704378774d682b7261314e444832574d6f3965507648304f79427453776a44773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d" + "relayedTx@7b226e6f6e6365223a3230382c2273656e646572223a227371455656633553486b6c45344a717864556e59573068397a536249533141586f3534786f32634969626f3d222c227265636569766572223a2241546c484c76396f686e63616d433877673970645168386b77704742356a6949496f3349484b594e6165453d222c2276616c7565223a313939393939393030303030303030303030303030303030302c226761735072696365223a313030303030303030302c226761734c696d6974223a35303030302c2264617461223a22222c227369676e6174757265223a22594661677972512f726d614c7333766e7159307657553858415a7939354b4e31725738347a4f764b62376c7a3773576e2f566a546d68704378774d682b7261314e444832574d6f3965507648304f79427453776a44773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c22736e64557365724e616d65223a22593246796232773d222c22726376557365724e616d65223a22595778705932553d227d", ); assert.equal( Buffer.from(relayedTransaction.signature).toString("hex"), - "c0fb5cf8c0a413d6988ba35dc279c63f8849572c5f23b1cab36dcc50952dc3ed9da01068d6ac0cbde7e14167bfc2eca5164d5c2154c89eb313c9c596e3f8b801" + "c0fb5cf8c0a413d6988ba35dc279c63f8849572c5f23b1cab36dcc50952dc3ed9da01068d6ac0cbde7e14167bfc2eca5164d5c2154c89eb313c9c596e3f8b801", ); }); @@ -166,11 +166,11 @@ describe("test relayed v1 transaction builder", function () { assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a222b5431526f4833625a792f54423177342b6a365155477258645637457577553073753948646551626453515269463953757a686d634b705463526d58595252366c534c6652394931624d7134674730436538363741513d3d227d" + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a224b4b78324f33383655725135416b4f465258307578327933446a384853334b373038487174344668377161557669424550716c45614e746e6158706a6f2f333651476d4a456934784435457a6c6f4f677a634d4442773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a222b5431526f4833625a792f54423177342b6a365155477258645637457577553073753948646551626453515269463953757a686d634b705463526d58595252366c534c6652394931624d7134674730436538363741513d3d227d", ); assert.equal( Buffer.from(relayedTransaction.signature).toString("hex"), - "39cff9d5100e290fbc7361cb6e2402261caf864257b4116f150e0c61e7869155dff8361fa5449431eb7a8ed847c01ba9b3b5ebafe5fac1a3d40c64829d827e00" + "39cff9d5100e290fbc7361cb6e2402261caf864257b4116f150e0c61e7869155dff8361fa5449431eb7a8ed847c01ba9b3b5ebafe5fac1a3d40c64829d827e00", ); }); @@ -205,11 +205,11 @@ describe("test relayed v1 transaction builder", function () { assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b546e5674596d5679222c227369676e6174757265223a223469724d4b4a656d724d375174344e7635487633544c44683775654779487045564c4371674a3677652f7a662b746a4933354975573452633458543451533433475333356158386c6a533834324a38426854645043673d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a2270424754394e674a78307539624c56796b654d78786a454865374269696c37764932324a46676f32787a6e2f496e3032463769546563356b44395045324f747065386c475335412b532f4a36417762576834446744673d3d227d" + "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414b565841323879704877692f79693741364c64504b704f68464d386958513d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b546e5674596d5679222c227369676e6174757265223a223469724d4b4a656d724d375174344e7635487633544c44683775654779487045564c4371674a3677652f7a662b746a4933354975573452633458543451533433475333356158386c6a533834324a38426854645043673d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a322c226f7074696f6e73223a322c22677561726469616e223a22486f714c61306e655733766843716f56696c70715372744c5673774939535337586d7a563868477450684d3d222c22677561726469616e5369676e6174757265223a2270424754394e674a78307539624c56796b654d78786a454865374269696c37764932324a46676f32787a6e2f496e3032463769546563356b44395045324f747065386c475335412b532f4a36417762576834446744673d3d227d", ); assert.equal( Buffer.from(relayedTransaction.signature).toString("hex"), - "8ede1bbeed96b102344dffeac12c2592c62b7313cdeb132e8c8bf11d2b1d3bb8189d257a6dbcc99e222393d9b9ec77656c349dae97a32e68bdebd636066bf706" + "8ede1bbeed96b102344dffeac12c2592c62b7313cdeb132e8c8bf11d2b1d3bb8189d257a6dbcc99e222393d9b9ec77656c349dae97a32e68bdebd636066bf706", ); }); @@ -272,7 +272,7 @@ describe("test relayed v1 transaction builder", function () { assert.equal(relayedTransaction.gasLimit.toString(), "60414500"); assert.equal( Buffer.from(relayedTransaction.data).toString(), - "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c" + "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c", ); }); }); diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 898c9e8ba..8893ccd38 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -36,7 +36,7 @@ export class RelayedTransactionsFactory { const data = `relayedTx@${Buffer.from(serializedTransaction).toString("hex")}`; const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( - new BigNumber(data.length) + new BigNumber(data.length), ); const gasLimit = new BigNumber(this.config.minGasLimit) .plus(additionalGasForDataLength) @@ -74,7 +74,7 @@ export class RelayedTransactionsFactory { const data = `relayedTxV2@${argumentsString}`; const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( - new BigNumber(data.length) + new BigNumber(data.length), ); const gasLimit = new BigNumber(options.innerTransactionGasLimit) .plus(new BigNumber(this.config.minGasLimit)) diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d784cc89f..e64e2e774 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -145,9 +145,7 @@ export class SmartContractTransactionsFactory { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); - parts = parts.concat(preparedArgs); return new TransactionNextBuilder({ diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 512cd2eb8..7804e7bd2 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -27,7 +27,7 @@ export class TokenTransfersDataBuilder { numberToPaddedHex(token.nonce), numberToPaddedHex(transfer.amount), addressToHex(receiver), - ] + ], ); return args; } @@ -38,7 +38,7 @@ export class TokenTransfersDataBuilder { for (let transfer of transfers) { const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); args.push( - ...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)] + ...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)], ); } From 0a34a8c1c0ba695ccb64c3360266c030183741ba Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 13 Feb 2024 15:23:00 +0200 Subject: [PATCH 090/275] implement message class according to specs --- src/constants.ts | 2 + src/interface.ts | 49 +++++++++++--- src/message.spec.ts | 87 ++++++++++++++++++++++++ src/message.ts | 93 ++++++++++++++++++++++++++ src/signableMessage.ts | 147 +++++++++++++++++++++-------------------- src/transaction.ts | 2 +- 6 files changed, 295 insertions(+), 85 deletions(-) create mode 100644 src/message.spec.ts create mode 100644 src/message.ts diff --git a/src/constants.ts b/src/constants.ts index c00f61a35..63784a2fd 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -14,3 +14,5 @@ export const CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq export const DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6"; export const DEFAULT_HRP = "erd"; export const ESDT_CONTRACT_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; +export const DEFAULT_MESSAGE_VERSION = 1; +export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; diff --git a/src/interface.ts b/src/interface.ts index 0fe960767..70bdae7fa 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -26,16 +26,36 @@ export interface IPlainTransactionObject { guardianSignature?: string; } -export interface ISignature { hex(): string; } -export interface IAddress { bech32(): string; } -export interface ITransactionValue { toString(): string; } -export interface IAccountBalance { toString(): string; } -export interface INonce { valueOf(): number; } -export interface IChainID { valueOf(): string; } -export interface IGasLimit { valueOf(): number; } -export interface IGasPrice { valueOf(): number; } -export interface ITransactionVersion { valueOf(): number; } -export interface ITransactionOptions { valueOf(): number; } +export interface ISignature { + hex(): string; +} +export interface IAddress { + bech32(): string; +} +export interface ITransactionValue { + toString(): string; +} +export interface IAccountBalance { + toString(): string; +} +export interface INonce { + valueOf(): number; +} +export interface IChainID { + valueOf(): string; +} +export interface IGasLimit { + valueOf(): number; +} +export interface IGasPrice { + valueOf(): number; +} +export interface ITransactionVersion { + valueOf(): number; +} +export interface ITransactionOptions { + valueOf(): number; +} export interface ITransactionPayload { length(): number; @@ -72,4 +92,11 @@ export interface ITransactionNext { guardian: string; signature: Uint8Array; guardianSignature: Uint8Array; - } +} + +export interface IMessage { + data: Uint8Array; + signature?: Uint8Array; + address?: IAddress; + version?: number; +} diff --git a/src/message.spec.ts b/src/message.spec.ts new file mode 100644 index 000000000..3abe9cef2 --- /dev/null +++ b/src/message.spec.ts @@ -0,0 +1,87 @@ +import { assert } from "chai"; +import { Message, MessageComputer } from "./message"; +import { loadTestWallets, TestWallet } from "./testutils"; +import { UserVerifier } from "@multiversx/sdk-wallet"; +import { DEFAULT_MESSAGE_VERSION } from "./constants"; + +describe("test message", () => { + let alice: TestWallet; + const messageComputer = new MessageComputer(); + + before(async function () { + ({ alice } = await loadTestWallets()); + }); + + it("should test message compute bytes for signing", async () => { + const data = Buffer.from("test message"); + + const message = new Message({ + data: data, + }); + + const serialized = messageComputer.computeBytesForSigning(message); + + assert.equal( + Buffer.from(serialized).toString("hex"), + "2162d6271208429e6d3e664139e98ba7c5f1870906fb113e8903b1d3f531004d", + ); + }); + + it("should create, sign, pack, unpack and verify message", async () => { + const data = Buffer.from("test"); + + const message = new Message({ + data: data, + address: alice.getAddress(), + }); + + message.signature = await alice.signer.sign(Buffer.from(messageComputer.computeBytesForSigning(message))); + + assert.equal( + Buffer.from(message.signature).toString("hex"), + "7aff43cd6e3d880a65033bf0a1b16274854fd7dfa9fe5faa7fa9a665ee851afd4c449310f5f1697d348e42d1819eaef69080e33e7652d7393521ed50d7427a0e", + ); + + const packedMessage = messageComputer.packMessage(message); + assert.deepEqual(packedMessage, { + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + message: "74657374", + signature: + "7aff43cd6e3d880a65033bf0a1b16274854fd7dfa9fe5faa7fa9a665ee851afd4c449310f5f1697d348e42d1819eaef69080e33e7652d7393521ed50d7427a0e", + version: 1, + }); + + const unpackedMessage = messageComputer.unpackMessage(packedMessage); + assert.deepEqual(unpackedMessage.address, alice.getAddress()); + assert.deepEqual(unpackedMessage.data, message.data); + assert.deepEqual(unpackedMessage.signature, message.signature); + assert.deepEqual(unpackedMessage.version, message.version); + + const verifier = UserVerifier.fromAddress(alice.getAddress()); + const isValid = verifier.verify( + Buffer.from(messageComputer.computeBytesForVerifying(unpackedMessage)), + Buffer.from(unpackedMessage.signature!), + ); + assert.equal(isValid, true); + }); + + it("should unpack legacy message", async () => { + const legacyMessage = { + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + message: "0x7468697320697320612074657374206d657373616765", + signature: + "0xb16847437049986f936dd4a0917c869730cbf29e40a0c0821ca70db33f44758c3d41bcbea446dee70dea13d50942343bb78e74979dc434bbb2b901e0f4fd1809", + version: 1, + signer: "ErdJS", + }; + + const message = messageComputer.unpackMessage(legacyMessage); + assert.deepEqual(message.address, alice.getAddress()); + assert.deepEqual(Buffer.from(message.data).toString(), "this is a test message"); + assert.deepEqual( + Buffer.from(message.signature!).toString("hex"), + "b16847437049986f936dd4a0917c869730cbf29e40a0c0821ca70db33f44758c3d41bcbea446dee70dea13d50942343bb78e74979dc434bbb2b901e0f4fd1809", + ); + assert.deepEqual(message.version, DEFAULT_MESSAGE_VERSION); + }); +}); diff --git a/src/message.ts b/src/message.ts new file mode 100644 index 000000000..bc0fe97fe --- /dev/null +++ b/src/message.ts @@ -0,0 +1,93 @@ +import { IAddress, IMessage } from "./interface"; +import { DEFAULT_MESSAGE_VERSION, MESSAGE_PREFIX } from "./constants"; +import { Address } from "./address"; + +const createKeccakHash = require("keccak"); + +export class Message { + /** + * Actual message being signed. + */ + public data: Uint8Array; + /** + * The message signature. + */ + public signature?: Uint8Array; + /** + * Address of the wallet that performed the signing operation. + */ + public address?: IAddress; + /** + * Number representing the message version. + */ + public version?: number; + + constructor(options: { data: Uint8Array; signature?: Uint8Array; address?: IAddress; version?: number }) { + this.data = options.data; + this.signature = options.signature; + this.address = options.address; + this.version = options.version ? options.version : DEFAULT_MESSAGE_VERSION; + } +} + +export class MessageComputer { + constructor() {} + + computeBytesForSigning(message: IMessage): Uint8Array { + const messageSize = Buffer.from(message.data.length.toString()); + const signableMessage = Buffer.concat([messageSize, message.data]); + let bytesToHash = Buffer.concat([Buffer.from(MESSAGE_PREFIX), signableMessage]); + + return createKeccakHash("keccak256").update(bytesToHash).digest(); + } + + computeBytesForVerifying(message: IMessage): Uint8Array { + return this.computeBytesForSigning(message); + } + + packMessage(message: IMessage): { + message: string; + signature: string; + address: string; + version: number; + } { + return { + message: Buffer.from(message.data).toString("hex"), + signature: message.signature ? Buffer.from(message.signature).toString("hex") : "", + address: message.address ? message.address.bech32() : "", + version: message.version ? message.version : DEFAULT_MESSAGE_VERSION, + }; + } + + unpackMessage(packedMessage: { message: string; signature?: string; address?: string; version?: number }): Message { + let dataHex = this.trimHexPrefix(packedMessage.message); + const data = Buffer.from(dataHex, "hex"); + + let signature: Uint8Array | undefined = undefined; + if (packedMessage.signature) { + let signatureHex = this.trimHexPrefix(packedMessage.signature); + signature = Buffer.from(signatureHex, "hex"); + } + + let address: Address | undefined = undefined; + if (packedMessage.address) { + address = Address.fromBech32(packedMessage.address); + } + + const version = packedMessage.version || DEFAULT_MESSAGE_VERSION; + + return new Message({ + data: data, + signature: signature, + address: address, + version: version, + }); + } + + private trimHexPrefix(data: string): string { + if (data.startsWith("0x") || data.startsWith("0X")) { + return data.slice(2); + } + return data; + } +} diff --git a/src/signableMessage.ts b/src/signableMessage.ts index 4fe82b7e0..9d22e54c0 100644 --- a/src/signableMessage.ts +++ b/src/signableMessage.ts @@ -1,80 +1,81 @@ import { Address } from "./address"; import { ISignature } from "./interface"; import { interpretSignatureAsBuffer } from "./signature"; +import { MESSAGE_PREFIX } from "./constants"; const createKeccakHash = require("keccak"); -export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; - +/** + * @deprecated Use {@link Message} instead. + */ export class SignableMessage { - - /** - * Actual message being signed. - */ - message: Buffer; - /** - * Signature obtained by a signer of type @param signer . - */ - signature: Buffer; - - /** - * Address of the wallet that performed the signing operation - */ - address: Address; - - /** - * Text representing the identifer for the application that signed the message - */ - signer: string; - - /** - * Number representing the signable message version - */ - version: number; - - public constructor(init?: Partial) { - this.message = Buffer.from([]); - this.signature = Buffer.from([]); - this.version = 1; - this.signer = "ErdJS"; - this.address = new Address(); - - Object.assign(this, init); - } - - serializeForSigning(): Buffer { - const messageSize = Buffer.from(this.message.length.toString()); - const signableMessage = Buffer.concat([messageSize, this.message]); - let bytesToHash = Buffer.concat([Buffer.from(MESSAGE_PREFIX), signableMessage]); - - return createKeccakHash("keccak256").update(bytesToHash).digest(); - } - - serializeForSigningRaw(): Buffer { - return Buffer.concat([this.getMessageSize(), this.message]); - } - - getSignature(): Buffer { - return this.signature; - } - - applySignature(signature: ISignature | Uint8Array) { - this.signature = interpretSignatureAsBuffer(signature); - } - - getMessageSize(): Buffer { - const messageSize = Buffer.alloc(4); - messageSize.writeUInt32BE(this.message.length, 0); - - return messageSize; - } - - toJSON(): object { - return { - address: this.address.bech32(), - message: "0x" + this.message.toString("hex"), - signature: "0x" + this.signature.toString("hex"), - version: this.version, - signer: this.signer, - }; - } + /** + * Actual message being signed. + */ + message: Buffer; + /** + * Signature obtained by a signer of type @param signer . + */ + signature: Buffer; + + /** + * Address of the wallet that performed the signing operation + */ + address: Address; + + /** + * Text representing the identifer for the application that signed the message + */ + signer: string; + + /** + * Number representing the signable message version + */ + version: number; + + public constructor(init?: Partial) { + this.message = Buffer.from([]); + this.signature = Buffer.from([]); + this.version = 1; + this.signer = "ErdJS"; + this.address = new Address(); + + Object.assign(this, init); + } + + serializeForSigning(): Buffer { + const messageSize = Buffer.from(this.message.length.toString()); + const signableMessage = Buffer.concat([messageSize, this.message]); + let bytesToHash = Buffer.concat([Buffer.from(MESSAGE_PREFIX), signableMessage]); + + return createKeccakHash("keccak256").update(bytesToHash).digest(); + } + + serializeForSigningRaw(): Buffer { + return Buffer.concat([this.getMessageSize(), this.message]); + } + + getSignature(): Buffer { + return this.signature; + } + + applySignature(signature: ISignature | Uint8Array) { + this.signature = interpretSignatureAsBuffer(signature); + } + + getMessageSize(): Buffer { + const messageSize = Buffer.alloc(4); + messageSize.writeUInt32BE(this.message.length, 0); + + return messageSize; + } + + toJSON(): object { + return { + address: this.address.bech32(), + message: "0x" + this.message.toString("hex"), + signature: "0x" + this.signature.toString("hex"), + version: this.version, + signer: this.signer, + }; + } } diff --git a/src/transaction.ts b/src/transaction.ts index 9518e31aa..971d1c7af 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -653,7 +653,7 @@ export class TransactionComputer { const serialized = JSON.stringify(plainTransaction); - return new Uint8Array(Buffer.from(serialized)); + return Buffer.from(serialized); } computeTransactionHash(transaction: ITransactionNext): Uint8Array { From 65230d03e6d03c3b3f029df55c22ee02ee68d9ae Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 13 Feb 2024 15:26:05 +0200 Subject: [PATCH 091/275] add empty lines --- src/interface.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/interface.ts b/src/interface.ts index 70bdae7fa..65a0099e9 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -29,30 +29,39 @@ export interface IPlainTransactionObject { export interface ISignature { hex(): string; } + export interface IAddress { bech32(): string; } + export interface ITransactionValue { toString(): string; } + export interface IAccountBalance { toString(): string; } + export interface INonce { valueOf(): number; } + export interface IChainID { valueOf(): string; } + export interface IGasLimit { valueOf(): number; } + export interface IGasPrice { valueOf(): number; } + export interface ITransactionVersion { valueOf(): number; } + export interface ITransactionOptions { valueOf(): number; } From e7e10feb50c85bca92f95c00409dec873bc24f08 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 13 Feb 2024 17:19:43 +0200 Subject: [PATCH 092/275] add short description for the transaction factories --- src/transactionsFactories/delegationTransactionsFactory.ts | 3 +++ src/transactionsFactories/relayedTransactionsFactory.ts | 3 +++ src/transactionsFactories/smartContractTransactionsFactory.ts | 3 +++ .../tokenManagementTransactionsFactory.ts | 3 +++ src/transactionsFactories/transferTransactionsFactory.ts | 3 +++ 5 files changed, 15 insertions(+) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 9e389ab69..b0b354d8d 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -24,6 +24,9 @@ interface IValidatorPublicKey { hex(): string; } +/** + * Use this class to create delegation related transactions like creating a new delegation contract or adding nodes. + */ export class DelegationTransactionsFactory { private readonly config: Config; diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 8893ccd38..5949e0dd2 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -13,6 +13,9 @@ interface IConfig { gasLimitPerByte: BigNumber.Value; } +/** + * Use this class to create both RelyedV1 and RelayedV2 transactions. + */ export class RelayedTransactionsFactory { private readonly config: IConfig; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index e64e2e774..2c328e086 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -27,6 +27,9 @@ interface TokenComputer { isFungible(token: Token): boolean; } +/** + * Use this class to create transactions to deploy, call or upgrade a smart contract. + */ export class SmartContractTransactionsFactory { private readonly config: Config; private readonly abiRegistry?: Abi; diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 508c1e289..272fb5996 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -29,6 +29,9 @@ interface Config { type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; +/** + * Use this class to create token management transactions like issuing ESDTs, creating NFTs, setting roles, etc. + */ export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly trueAsHex: string; diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index ad606c652..29ea1573c 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -22,6 +22,9 @@ interface TokenComputer { isFungible(token: Token): boolean; } +/** + * Use this class to create transactions for native token transfers (EGLD) or custom tokens transfers (ESDT/NTF/MetaESDT). + */ export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; From 9b7f2f25105e5fabb6b2c117449cd9bb27038161 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 14 Feb 2024 10:45:05 +0200 Subject: [PATCH 093/275] fixes after review --- src/message.ts | 11 ++++------- .../relayedTransactionsFactory.ts | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/message.ts b/src/message.ts index bc0fe97fe..877251325 100644 --- a/src/message.ts +++ b/src/message.ts @@ -20,7 +20,7 @@ export class Message { /** * Number representing the message version. */ - public version?: number; + public version: number; constructor(options: { data: Uint8Array; signature?: Uint8Array; address?: IAddress; version?: number }) { this.data = options.data; @@ -60,14 +60,11 @@ export class MessageComputer { } unpackMessage(packedMessage: { message: string; signature?: string; address?: string; version?: number }): Message { - let dataHex = this.trimHexPrefix(packedMessage.message); + const dataHex = this.trimHexPrefix(packedMessage.message); const data = Buffer.from(dataHex, "hex"); - let signature: Uint8Array | undefined = undefined; - if (packedMessage.signature) { - let signatureHex = this.trimHexPrefix(packedMessage.signature); - signature = Buffer.from(signatureHex, "hex"); - } + const signatureHex = this.trimHexPrefix(packedMessage.signature || ""); + const signature = Buffer.from(signatureHex, "hex"); let address: Address | undefined = undefined; if (packedMessage.address) { diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 5949e0dd2..a7ff15f80 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -14,7 +14,7 @@ interface IConfig { } /** - * Use this class to create both RelyedV1 and RelayedV2 transactions. + * Use this class to create both RelayedV1 and RelayedV2 transactions. */ export class RelayedTransactionsFactory { private readonly config: IConfig; From 2917009404dd7d50f0e2ec569b28577f07caa57a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 15 Feb 2024 11:54:01 +0200 Subject: [PATCH 094/275] add token management transactions parser --- src/errors.ts | 275 ++++----- .../tokenOperationsOutcomeParser.ts | 22 +- src/transactionsOutcomeParsers/resources.ts | 55 ++ ...anagementTransactionsOutcomeParser.spec.ts | 560 ++++++++++++++++++ ...okenManagementTransactionsOutcomeParser.ts | 361 +++++++++++ 5 files changed, 1131 insertions(+), 142 deletions(-) create mode 100644 src/transactionsOutcomeParsers/resources.ts create mode 100644 src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts create mode 100644 src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts diff --git a/src/errors.ts b/src/errors.ts index 1f23fd1ca..30310edcd 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -2,362 +2,373 @@ * The base class for exceptions (errors). */ export class Err extends Error { - inner: Error | undefined = undefined; + inner: Error | undefined = undefined; - public constructor(message: string, inner?: Error) { - super(message); - this.inner = inner; - } + public constructor(message: string, inner?: Error) { + super(message); + this.inner = inner; + } - /** - * Returns a pretty, friendly summary for the error or for the chain of errros (if appropriate). - */ - summary(): any[] { - let result = []; + /** + * Returns a pretty, friendly summary for the error or for the chain of errros (if appropriate). + */ + summary(): any[] { + let result = []; - result.push({ name: this.name, message: this.message }); + result.push({ name: this.name, message: this.message }); - let inner: any = this.inner; - while (inner) { - result.push({ name: inner.name, message: inner.message }); - inner = inner.inner; - } + let inner: any = this.inner; + while (inner) { + result.push({ name: inner.name, message: inner.message }); + inner = inner.inner; + } - return result; - } + return result; + } } /** * Signals invalid arguments for a function, for an operation. */ export class ErrInvalidArgument extends Err { - public constructor(message: string, inner?: Error) { - super(`Invalid argument: ${message}`, inner); - } + public constructor(message: string, inner?: Error) { + super(`Invalid argument: ${message}`, inner); + } } /** * Signals an unsupported operation. */ export class ErrUnsupportedOperation extends Err { - public constructor(operation: string, reason: string = "not specified") { - super(`Operation "${operation}" not supported. Reason: ${reason}`); - } + public constructor(operation: string, reason: string = "not specified") { + super(`Operation "${operation}" not supported. Reason: ${reason}`); + } } /** * Signals the provisioning of objects of unexpected (bad) types. */ export class ErrBadType extends Err { - public constructor(name: string, type: any, value?: any) { - super(`Bad type of "${name}": ${value}. Expected type: ${type}`); - } + public constructor(name: string, type: any, value?: any) { + super(`Bad type of "${name}": ${value}. Expected type: ${type}`); + } } /** * Signals that an invariant failed. */ export class ErrInvariantFailed extends Err { - public constructor(message: string) { - super(`Invariant failed: [${message}]`); - } + public constructor(message: string) { + super(`Invariant failed: [${message}]`); + } } /** * Signals an unexpected condition. */ export class ErrUnexpectedCondition extends Err { - public constructor(message: string) { - super(`Unexpected condition: [${message}]`); - } + public constructor(message: string) { + super(`Unexpected condition: [${message}]`); + } } /** * Signals issues with {@link Address} instantiation. */ export class ErrAddressCannotCreate extends Err { - public constructor(input: any, inner?: Error) { - let message = `Cannot create address from: ${input}`; - super(message, inner); - } + public constructor(input: any, inner?: Error) { + let message = `Cannot create address from: ${input}`; + super(message, inner); + } } /** * Signals issues with the HRP of an {@link Address}. */ export class ErrAddressBadHrp extends Err { - public constructor(expected: string, got: string) { - super(`Wrong address HRP. Expected: ${expected}, got ${got}`); - } + public constructor(expected: string, got: string) { + super(`Wrong address HRP. Expected: ${expected}, got ${got}`); + } } /** * Signals the presence of an empty / invalid address. */ export class ErrAddressEmpty extends Err { - public constructor() { - super(`Address is empty`); - } + public constructor() { + super(`Address is empty`); + } } /** * Signals an invalid value for {@link GasLimit} objects. */ export class ErrNotEnoughGas extends Err { - public constructor(value: number) { - super(`Not enough gas provided: ${value}`); - } + public constructor(value: number) { + super(`Not enough gas provided: ${value}`); + } } /** * Signals an invalid value for {@link Nonce} objects. */ export class ErrNonceInvalid extends Err { - public constructor(value: number) { - super(`Invalid nonce: ${value}`); - } + public constructor(value: number) { + super(`Invalid nonce: ${value}`); + } } /** * Signals an invalid value for {@link TransactionVersion} objects. */ export class ErrTransactionVersionInvalid extends Err { - public constructor(value: number) { - super(`Invalid transaction version: ${value}`); - } + public constructor(value: number) { + super(`Invalid transaction version: ${value}`); + } } /** * Signals an invalid value for {@link TransactionOptions} objects. */ export class ErrTransactionOptionsInvalid extends Err { - public constructor(value: number) { - super(`Invalid transaction options: ${value}`); - } + public constructor(value: number) { + super(`Invalid transaction options: ${value}`); + } } /** * Signals an error related to signing a message (a transaction). */ export class ErrSignatureCannotCreate extends Err { - public constructor(input: any, inner?: Error) { - let message = `Cannot create signature from: ${input}`; - super(message, inner); - } + public constructor(input: any, inner?: Error) { + let message = `Cannot create signature from: ${input}`; + super(message, inner); + } } /** * Signals an invalid value for the name of a {@link ContractFunction}. */ export class ErrInvalidFunctionName extends Err { - public constructor() { - super(`Invalid function name`); - } + public constructor() { + super(`Invalid function name`); + } } /** * Signals a failed operation, since the Timer is already running. */ export class ErrAsyncTimerAlreadyRunning extends Err { - public constructor() { - super("Async timer already running"); - } + public constructor() { + super("Async timer already running"); + } } /** * Signals a failed operation, since the Timer has been aborted. */ export class ErrAsyncTimerAborted extends Err { - public constructor() { - super("Async timer aborted"); - } + public constructor() { + super("Async timer aborted"); + } } /** * Signals a timout for a {@link TransactionWatcher}. */ export class ErrTransactionWatcherTimeout extends Err { - public constructor() { - super(`TransactionWatcher has timed out`); - } + public constructor() { + super(`TransactionWatcher has timed out`); + } } /** * Signals an issue related to waiting for a specific transaction status. */ export class ErrExpectedTransactionStatusNotReached extends Err { - public constructor() { - super(`Expected transaction status not reached`); - } + public constructor() { + super(`Expected transaction status not reached`); + } } /** * Signals an issue related to waiting for specific transaction events. */ export class ErrExpectedTransactionEventsNotFound extends Err { - public constructor() { - super(`Expected transaction events not found`); - } + public constructor() { + super(`Expected transaction events not found`); + } } /** * Signals a generic error in the context of Smart Contracts. */ export class ErrContract extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } export class ErrContractHasNoAddress extends ErrContract { - public constructor() { - super(` + public constructor() { + super(` The smart contract has no address set. Make sure you provide the address in the constructor, or call setAddress() appropriately. If you need to recompute the address of the contract, make use of SmartContract.computeAddress() (static method). `); - } + } } /** * Signals an error thrown by the mock-like test objects. */ export class ErrMock extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals a generic type error. */ export class ErrTypingSystem extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals a missing field on a struct. */ export class ErrMissingFieldOnStruct extends Err { - public constructor(fieldName: string, structName: string) { - super(`field ${fieldName} does not exist on struct ${structName}`); - } + public constructor(fieldName: string, structName: string) { + super(`field ${fieldName} does not exist on struct ${structName}`); + } } /** * Signals a missing field on an enum. */ export class ErrMissingFieldOnEnum extends Err { - public constructor(fieldName: string, enumName: string) { - super(`field ${fieldName} does not exist on enum ${enumName}`); - } + public constructor(fieldName: string, enumName: string) { + super(`field ${fieldName} does not exist on enum ${enumName}`); + } } /** * Signals an error when parsing the contract results. */ export class ErrCannotParseContractResults extends Err { - public constructor(details: string) { - super(`cannot parse contract results: ${details}`); - } + public constructor(details: string) { + super(`cannot parse contract results: ${details}`); + } } /** * Signals an error when parsing the outcome of a transaction (results and logs). */ export class ErrCannotParseTransactionOutcome extends Err { - public constructor(transactionHash: string, message: string) { - super(`cannot parse outcome of transaction ${transactionHash}: ${message}`); - } + public constructor(transactionHash: string, message: string) { + super(`cannot parse outcome of transaction ${transactionHash}: ${message}`); + } } /** * Signals a generic codec (encode / decode) error. */ export class ErrCodec extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals a generic contract interaction error. */ export class ErrContractInteraction extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals that a method is not yet implemented */ export class ErrNotImplemented extends Err { - public constructor() { - super("Method not yet implemented"); - } + public constructor() { + super("Method not yet implemented"); + } } /** * Signals invalid arguments when using the relayed v1 builder */ export class ErrInvalidRelayedV1BuilderArguments extends Err { - public constructor() { - super("invalid arguments for relayed v1 builder"); - } + public constructor() { + super("invalid arguments for relayed v1 builder"); + } } /** * Signals invalid arguments when using the relayed v2 builder */ export class ErrInvalidRelayedV2BuilderArguments extends Err { - public constructor() { - super("invalid arguments for relayed v2 builder"); - } + public constructor() { + super("invalid arguments for relayed v2 builder"); + } } /** * Signals that Gas Limit isn't 0 for an inner tx when using relayed v2 builder */ export class ErrGasLimitShouldBe0ForInnerTransaction extends Err { - public constructor() { - super("gas limit must be 0 for the inner transaction for relayed v2"); - } + public constructor() { + super("gas limit must be 0 for the inner transaction for relayed v2"); + } } /** * Signals that the `isCompleted` property is missing on the transaction obect and is needed for the Transaction Watcher */ export class ErrIsCompletedFieldIsMissingOnTransaction extends Err { - public constructor() { - super("The transaction watcher requires the `isCompleted` property to be defined on the transaction object. Perhaps you've used the sdk-network-provider's `ProxyNetworkProvider.getTransaction()` and in that case you should also pass `withProcessStatus=true`.") - } + public constructor() { + super( + "The transaction watcher requires the `isCompleted` property to be defined on the transaction object. Perhaps you've used the sdk-network-provider's `ProxyNetworkProvider.getTransaction()` and in that case you should also pass `withProcessStatus=true`.", + ); + } } /** * Signals that the provided token identifier is not valid */ export class ErrInvalidTokenIdentifier extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals a generic bad usage error */ export class ErrBadUsage extends Err { - public constructor(message: string) { - super(message); - } + public constructor(message: string) { + super(message); + } } /** * Signals an invalid inner transaction for relayed transactions */ -export class ErrInvalidInnerTransaction extends Err{ - public constructor(message: string){ - super(message); - } +export class ErrInvalidInnerTransaction extends Err { + public constructor(message: string) { + super(message); + } +} + +/** + * Signals an error when parsing the logs of a transaction. + */ +export class ErrParseTransactionOutcome extends Err { + public constructor(message: string) { + super(message); + } } diff --git a/src/tokenOperations/tokenOperationsOutcomeParser.ts b/src/tokenOperations/tokenOperationsOutcomeParser.ts index 260ffb3d3..8fc489f3c 100644 --- a/src/tokenOperations/tokenOperationsOutcomeParser.ts +++ b/src/tokenOperations/tokenOperationsOutcomeParser.ts @@ -3,7 +3,6 @@ import { ErrCannotParseTransactionOutcome } from "../errors"; import { IAddress } from "../interface"; import { bufferToBigInt } from "./codec"; - interface ITransactionOnNetwork { hash: string; contractResults: IContractResults; @@ -42,8 +41,7 @@ export interface IRegisterAndSetAllRolesOutcome { roles: string[]; } -export interface IToggleBurnRoleGloballyOutcome { -} +export interface IToggleBurnRoleGloballyOutcome {} export interface ISetSpecialRoleOutcome { userAddress: string; @@ -71,8 +69,7 @@ export interface IBurnOutcome { burntSupply: string; } -export interface IPausingOutcome { -} +export interface IPausingOutcome {} export interface IFreezingOutcome { userAddress: string; @@ -106,6 +103,9 @@ export interface IBurnQuantityOutcome { burntQuantity: string; } +/** + * @deprecated Use {@link TokenManagementTransactionsOutcomeParser} + */ export class TokenOperationsOutcomeParser { parseIssueFungible(transaction: ITransactionOnNetwork): IESDTIssueOutcome { this.ensureNoError(transaction); @@ -146,7 +146,7 @@ export class TokenOperationsOutcomeParser { const tokenIdentifier = this.extractTokenIdentifier(eventRegister); const eventSetRole = this.findSingleEventByIdentifier(transaction, "ESDTSetRole"); - const roles = eventSetRole.topics.slice(3).map(topic => topic.valueOf().toString()); + const roles = eventSetRole.topics.slice(3).map((topic) => topic.valueOf().toString()); return { tokenIdentifier, roles }; } @@ -167,7 +167,7 @@ export class TokenOperationsOutcomeParser { const event = this.findSingleEventByIdentifier(transaction, "ESDTSetRole"); const userAddress = event.address.toString(); const tokenIdentifier = this.extractTokenIdentifier(event); - const roles = event.topics.slice(3).map(topic => topic.valueOf().toString()); + const roles = event.topics.slice(3).map((topic) => topic.valueOf().toString()); return { userAddress, tokenIdentifier, roles }; } @@ -284,13 +284,16 @@ export class TokenOperationsOutcomeParser { const data = Buffer.from(event.data.substring(1), "hex").toString(); const message = event.topics[1]?.valueOf().toString(); - throw new ErrCannotParseTransactionOutcome(transaction.hash, `encountered signalError: ${message} (${data})`); + throw new ErrCannotParseTransactionOutcome( + transaction.hash, + `encountered signalError: ${message} (${data})`, + ); } } } private findSingleEventByIdentifier(transaction: ITransactionOnNetwork, identifier: string): ITransactionEvent { - const events = this.gatherAllEvents(transaction).filter(event => event.identifier == identifier); + const events = this.gatherAllEvents(transaction).filter((event) => event.identifier == identifier); if (events.length == 0) { throw new ErrCannotParseTransactionOutcome(transaction.hash, `cannot find event of type ${identifier}`); @@ -330,4 +333,3 @@ export class TokenOperationsOutcomeParser { return Address.fromBuffer(event.topics[3]?.valueOf()).toString(); } } - diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts new file mode 100644 index 000000000..4fd7249ad --- /dev/null +++ b/src/transactionsOutcomeParsers/resources.ts @@ -0,0 +1,55 @@ +export class TransactionEvent { + address: string; + identifier: string; + topics: string[]; + data: Uint8Array; + + constructor(init: Partial) { + this.address = ""; + this.identifier = ""; + this.topics = []; + this.data = new Uint8Array(); + + Object.assign(this, init); + } +} + +export class TransactionLogs { + address: string; + events: TransactionEvent[]; + + constructor(init: Partial) { + this.address = ""; + this.events = []; + + Object.assign(this, init); + } +} + +export class SmartContractResult { + sender: string; + receiver: string; + data: Uint8Array; + logs: TransactionLogs; + + constructor(init: Partial) { + this.sender = ""; + this.receiver = ""; + this.data = new Uint8Array(); + this.logs = new TransactionLogs({}); + + Object.assign(this, init); + } +} + +export class TransactionOutcome { + smartContractResults: SmartContractResult[]; + transactionLogs: TransactionLogs; + + constructor(init: Partial) { + this.smartContractResults = []; + this.transactionLogs = new TransactionLogs({}); + + Object.assign(this, init); + } +} diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts new file mode 100644 index 000000000..976ea5a90 --- /dev/null +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -0,0 +1,560 @@ +import { assert } from "chai"; +import { ErrParseTransactionOutcome } from "../errors"; +import { TokenManagementTransactionsOutcomeParser } from "./tokenManagementTransactionsOutcomeParser"; +import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; + +describe("test token management transactions outcome parser", () => { + const parser = new TokenManagementTransactionsOutcomeParser(); + + it("should test ensure error", () => { + const event = new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + identifier: "signalError", + topics: ["Avk0jZ1kR+l9c76wQQoYcu4hvXPz+jxxTdqQeaCrbX8=", "dGlja2VyIG5hbWUgaXMgbm90IHZhbGlk"], + data: Buffer.from("QDc1NzM2NTcyMjA2NTcyNzI2Zjcy", "base64"), + }); + + const logs = new TransactionLogs({ events: [event] }); + const scResult = new SmartContractResult({}); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + assert.throws( + () => { + parser.parseIssueFungible(txOutcome); + }, + ErrParseTransactionOutcome, + "encountered signalError: ticker name is not valid (user error)", + ); + }); + + it("should test parse issue fungible", () => { + const identifer = "ZZZ-9ee87d"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "issue", + topics: [base64Identifier, "U0VDT05E", "Wlpa", "RnVuZ2libGVFU0RU", "Ag=="], + }); + + const logs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + const outcome = parser.parseIssueFungible(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse issue non fungible", () => { + const identifer = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const firstEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "upgradeProperties", + topics: ["TkZULWYwMWQxZQ==", "", "Y2FuVXBncmFkZQ==", "dHJ1ZQ==", "Y2FuQWRkU3BlY2lhbFJvbGVz", "dHJ1ZQ=="], + }); + + const secondEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTSetBurnRoleForAll", + topics: ["TkZULWYwMWQxZQ==", "", "", "RVNEVFJvbGVCdXJuRm9yQWxs"], + }); + + const thirdEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "issueNonFungible", + topics: [base64Identifier, "TkZURVNU", "TkZU", "Tm9uRnVuZ2libGVFU0RU"], + }); + + const logs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [firstEvent, secondEvent, thirdEvent], + }); + + const scResult = new SmartContractResult({}); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + const outcome = parser.parseIssueNonFungible(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse issue semi fungible", () => { + const identifer = "SEMIFNG-2c6d9f"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "issueSemiFungible", + topics: [base64Identifier, "U0VNSQ==", "U0VNSUZORw==", "U2VtaUZ1bmdpYmxlRVNEVA=="], + }); + + const logs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + const outcome = parser.parseIssueSemiFungible(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse register meta esdt", () => { + const identifer = "METATEST-e05d11"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "registerMetaESDT", + topics: [base64Identifier, "TUVURVNU", "TUVUQVRFU1Q=", "TWV0YUVTRFQ="], + }); + + const logs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + const outcome = parser.parseRegisterMetaEsdt(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse register and set all roles", () => { + const identifer = "LMAO-d9f892"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const roles = ["ESDTRoleLocalMint", "ESDTRoleLocalBurn"]; + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "registerAndSetAllRoles", + topics: [base64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const resultEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTSetRole", + topics: ["TE1BTy1kOWY4OTI=", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="], + }); + + const resultLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [resultEvent], + }); + + const scResult = new SmartContractResult({ + sender: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + receiver: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + data: Buffer.from( + "RVNEVFNldFJvbGVANGM0ZDQxNGYyZDY0Mzk2NjM4MzkzMkA0NTUzNDQ1NDUyNmY2YzY1NGM2ZjYzNjE2YzRkNjk2ZTc0QDQ1NTM0NDU0NTI2ZjZjNjU0YzZmNjM2MTZjNDI3NTcyNmU=", + "base64", + ), + logs: resultLogs, + }); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseRegisterAndSetAllRoles(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + assert.deepEqual(outcome.roles, roles); + }); + + it("should test parse register set special role", () => { + const identifer = "METATEST-e05d11"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const roles = ["ESDTRoleNFTCreate", "ESDTRoleNFTAddQuantity", "ESDTRoleNFTBurn"]; + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTSetRole", + topics: [ + base64Identifier, + "", + "", + "RVNEVFJvbGVORlRDcmVhdGU=", + "RVNEVFJvbGVORlRBZGRRdWFudGl0eQ==", + "RVNEVFJvbGVORlRCdXJu", + ], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseSetSpecialRole(txOutcome); + assert.equal(outcome.userAddress, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(outcome.tokenIdentifier, identifer); + assert.deepEqual(outcome.roles, roles); + }); + + it("should test parse nft create", () => { + const identifer = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(1); + const initialQuantity = BigInt(1); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTNFTCreate", + topics: [ + base64Identifier, + "AQ==", + "AQ==", + "CAESAgABIuUBCAESCE5GVEZJUlNUGiA8NdfqyxqZpKDMqlN+8MwK4Qn0H2wrQCID5jO/uwcfXCDEEyouUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4RzJDaHR0cHM6Ly9pcGZzLmlvL2lwZnMvUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4Rzo9dGFnczo7bWV0YWRhdGE6UW1SY1A5NGtYcjV6WmpSR3ZpN21KNnVuN0xweFVoWVZSNFI0UnBpY3h6Z1lrdA==", + ], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseNftCreate(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.initialQuantity, initialQuantity); + }); + + it("should test parse local mint", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(0); + const mintedSupply = BigInt(100000); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTLocalMint", + topics: [base64Identifier, "", "AYag"], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseLocalMint(txOutcome); + assert.equal(outcome.userAddress, event.address); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.mintedSupply, mintedSupply); + }); + + it("should test parse local burn", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(0); + const burntSupply = BigInt(100000); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTLocalBurn", + topics: [base64Identifier, "", "AYag"], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseLocalBurn(txOutcome); + assert.equal(outcome.userAddress, event.address); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.burntSupply, burntSupply); + }); + + it("should test parse pause", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTPause", + topics: [base64Identifier], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parsePause(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse unpause", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTUnPause", + topics: [base64Identifier], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseUnpause(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + }); + + it("should test parse freeze", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(0); + const balance = BigInt(10000000); + const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + + const event = new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + identifier: "ESDTFreeze", + topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({ + sender: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + receiver: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + data: Buffer.from("RVNEVEZyZWV6ZUA0MTQxNDEyZDMyMzk2MzM0NjMzOQ==", "base64"), + logs: transactionLogs, + }); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + }); + + const outcome = parser.parseFreeze(txOutcome); + assert.equal(outcome.userAddress, address); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.balance, balance); + }); + + it("should test parse unfreeze", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(0); + const balance = BigInt(10000000); + const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + + const event = new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + identifier: "ESDTUnFreeze", + topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({ + sender: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + receiver: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + data: Buffer.from("RVNEVEZyZWV6ZUA0MTQxNDEyZDMyMzk2MzM0NjMzOQ==", "base64"), + logs: transactionLogs, + }); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + }); + + const outcome = parser.parseUnfreeze(txOutcome); + assert.equal(outcome.userAddress, address); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.balance, balance); + }); + + it("should test parse wipe", () => { + const identifer = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(0); + const balance = BigInt(10000000); + const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + + const event = new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + identifier: "ESDTWipe", + topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({ + sender: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + receiver: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + data: Buffer.from("RVNEVEZyZWV6ZUA0MTQxNDEyZDMyMzk2MzM0NjMzOQ==", "base64"), + logs: transactionLogs, + }); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + }); + + const outcome = parser.parseWipe(txOutcome); + assert.equal(outcome.userAddress, address); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.balance, balance); + }); + + it("should test parse update attributes", () => { + const identifer = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(1); + const attributes = "metadata:ipfsCID/test.json;tags:tag1,tag2"; + const base64Attributes = Buffer.from(attributes).toString("base64"); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTNFTUpdateAttributes", + topics: [base64Identifier, "AQ==", "", base64Attributes], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseUpdateAttributes(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(Buffer.from(outcome.attributes).toString(), attributes); + }); + + it("should test parse add quantity", () => { + const identifer = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(1); + const addedQuantity = BigInt(10); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTNFTAddQuantity", + topics: [base64Identifier, "AQ==", "Cg=="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseAddQuantity(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.addedQuantity, addedQuantity); + }); + + it("should test parse burn quantity", () => { + const identifer = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifer).toString("base64"); + const nonce = BigInt(1); + const burntQuantity = BigInt(16); + + const event = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTNFTBurn", + topics: [base64Identifier, "AQ==", "EA=="], + }); + + const transactionLogs = new TransactionLogs({ + address: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + events: [event], + }); + + const scResult = new SmartContractResult({}); + + const txOutcome = new TransactionOutcome({ + smartContractResults: [scResult], + transactionLogs: transactionLogs, + }); + + const outcome = parser.parseBurnQuantity(txOutcome); + assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.nonce, nonce); + assert.equal(outcome.burntQuantity, burntQuantity); + }); +}); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts new file mode 100644 index 000000000..0c7ad9436 --- /dev/null +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -0,0 +1,361 @@ +import { TransactionEvent, TransactionOutcome } from "./resources"; +import { ErrParseTransactionOutcome } from "../errors"; +import { Address } from "../address"; +import { bufferToBigInt } from "../smartcontracts/codec/utils"; + +export class TokenManagementTransactionsOutcomeParser { + constructor() {} + + parseIssueFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "issue"); + const identifer = this.extractTokenIdentifier(event); + + return { tokenIdentifier: identifer }; + } + + parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "issueNonFungible"); + const identifer = this.extractTokenIdentifier(event); + + return { tokenIdentifier: identifer }; + } + + parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "issueSemiFungible"); + const identifer = this.extractTokenIdentifier(event); + + return { tokenIdentifier: identifer }; + } + + parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "registerMetaESDT"); + const identifer = this.extractTokenIdentifier(event); + + return { tokenIdentifier: identifer }; + } + + parseRegisterAndSetAllRoles(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; roles: string[] } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const registerEvent = this.findSingleEventByIdentifier(transactionOutcome, "registerAndSetAllRoles"); + const tokenIdentifier = this.extractTokenIdentifier(registerEvent); + + const setRoleEvent = this.findSingleEventByIdentifier(transactionOutcome, "ESDTSetRole"); + const encodedRoles = setRoleEvent.topics.slice(3); + + let roles: string[] = []; + for (const role of encodedRoles) { + const decodedRole = Buffer.from(role, "base64"); + roles = roles.concat(decodedRole.toString()); + } + + return { tokenIdentifier: tokenIdentifier, roles: roles }; + } + + parseSetBurnRoleGlobally(transactionOutcome: TransactionOutcome) { + this.ensureNoError(transactionOutcome.transactionLogs.events); + } + + parseUnsetBurnRoleGlobally(transactionOutcome: TransactionOutcome) { + this.ensureNoError(transactionOutcome.transactionLogs.events); + } + + parseSetSpecialRole(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + roles: string[]; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTSetRole"); + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + + const encodedRoles = event.topics.slice(3); + + let roles: string[] = []; + for (const role of encodedRoles) { + const decodedRole = Buffer.from(role, "base64"); + roles = roles.concat(decodedRole.toString()); + } + + return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; + } + + parseNftCreate(transactionOutcome: TransactionOutcome): { + tokenIdentifier: string; + nonce: bigint; + initialQuantity: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTCreate"); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const amount = this.extractAmount(event); + + return { tokenIdentifier: tokenIdentifier, nonce: nonce, initialQuantity: amount }; + } + + parseLocalMint(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + mintedSupply: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTLocalMint"); + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const mintedSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + mintedSupply: mintedSupply, + }; + } + + parseLocalBurn(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + burntSupply: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTLocalBurn"); + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntSupply: burntSupply, + }; + } + + parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTPause"); + const tokenIdentifier = this.extractTokenIdentifier(event); + + return { tokenIdentifier: tokenIdentifier }; + } + + parseUnpause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTUnPause"); + const tokenIdentifier = this.extractTokenIdentifier(event); + + return { tokenIdentifier: tokenIdentifier }; + } + + parseFreeze(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTFreeze"); + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + } + + parseUnfreeze(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTUnFreeze"); + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + } + + parseWipe(transactionOutcome: TransactionOutcome): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTWipe"); + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + } + + parseUpdateAttributes(transactionOutcome: TransactionOutcome): { + tokenIdentifier: string; + nonce: bigint; + attributes: Uint8Array; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + attributes: attributes, + }; + } + + parseAddQuantity(transactionOutcome: TransactionOutcome): { + tokenIdentifier: string; + nonce: bigint; + addedQuantity: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const addedQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + addedQuantity: addedQuantity, + }; + } + + parseBurnQuantity(transactionOutcome: TransactionOutcome): { + tokenIdentifier: string; + nonce: bigint; + burntQuantity: bigint; + } { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTBurn"); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntQuantity: burntQuantity, + }; + } + + private ensureNoError(transactionEvents: TransactionEvent[]) { + for (const event of transactionEvents) { + if (event.identifier == "signalError") { + const data = Buffer.from(event.data.toString().slice(1)).toString(); + const message = Buffer.from(event.topics[1], "base64").toString(); + + throw new ErrParseTransactionOutcome( + `encountered signalError: ${message} (${Buffer.from(data, "hex").toString()})`, + ); + } + } + } + + private findSingleEventByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent { + const events = this.gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); + + if (events.length == 0) { + throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); + } + if (events.length > 1) { + throw new ErrParseTransactionOutcome(`more than one event of type ${identifier}`); + } + + return events[0]; + } + + private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { + const allEvents = []; + + allEvents.push(...transactionOutcome.transactionLogs.events); + + for (const item of transactionOutcome.smartContractResults) { + allEvents.push(...item.logs.events); + } + + return allEvents; + } + + private extractTokenIdentifier(event: TransactionEvent): string { + if (!event.topics[0]) { + return ""; + } + return Buffer.from(event.topics[0], "base64").toString(); + } + + private extractNonce(event: TransactionEvent): bigint { + if (!event.topics[1]) { + return BigInt(0); + } + const nonce = Buffer.from(event.topics[1], "base64"); + return BigInt(bufferToBigInt(nonce).toFixed(0)); + } + + private extractAmount(event: TransactionEvent): bigint { + if (!event.topics[2]) { + return BigInt(0); + } + const amount = Buffer.from(event.topics[2], "base64"); + return BigInt(bufferToBigInt(amount).toFixed(0)); + } + + private extractAddress(event: TransactionEvent): string { + if (!event.topics[3]) { + return ""; + } + const address = Buffer.from(event.topics[3], "base64"); + return Address.fromBuffer(address).bech32(); + } +} From 35996e78e951a16fcab51e99629d2ed23a273e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 14:32:03 +0200 Subject: [PATCH 095/275] Compiler option: ES2020. --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 716261e67..089ef3062 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,10 @@ { "compilerOptions": { "module": "CommonJS", - "target": "es2015", + "target": "ES2020", "outDir": "out", "lib": [ - "ES2015", + "ES2020", "DOM" ], "sourceMap": true, From 0dbe620c99333b90b9bb974f11c1af3680ad5da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 14:32:30 +0200 Subject: [PATCH 096/275] For "Token" and "NextTokenTransfer", use "bigint" instead of "BigNumber.Value". --- src/tokens.spec.ts | 6 +-- src/tokens.ts | 11 +++--- .../smartContractTransactionsFactory.spec.ts | 38 +++++++++---------- .../tokenTransfersDataBuilder.ts | 2 +- .../transferTransactionsFactory.spec.ts | 20 +++++----- src/utils.codec.spec.ts | 10 ++++- src/utils.codec.ts | 14 +++++-- 7 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index 9fd54cd4a..e7949b56a 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -1,12 +1,12 @@ -import { Token, TokenComputer } from "./tokens"; import { assert } from "chai"; +import { Token, TokenComputer } from "./tokens"; describe("test token computer", async () => { const tokenComputer = new TokenComputer(); it("should test if token is fungible", async () => { - const fungibleToken = new Token("TEST-123456", 0); - const nonFungibleToken = new Token("NFT-987654", 7); + const fungibleToken = new Token("TEST-123456", 0n); + const nonFungibleToken = new Token("NFT-987654", 7n); assert.equal(tokenComputer.isFungible(fungibleToken), true); assert.equal(tokenComputer.isFungible(nonFungibleToken), false); diff --git a/src/tokens.ts b/src/tokens.ts index e6d18c28b..66d200e0a 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -1,11 +1,10 @@ -import BigNumber from "bignumber.js"; import { ErrInvalidTokenIdentifier } from "./errors"; export class Token { identifier: string; - nonce: BigNumber.Value; + nonce: bigint; - constructor(identifier: string, nonce: BigNumber.Value) { + constructor(identifier: string, nonce: bigint) { this.identifier = identifier; this.nonce = nonce; } @@ -13,9 +12,9 @@ export class Token { export class NextTokenTransfer { token: Token; - amount: BigNumber.Value; + amount: bigint; - constructor(token: Token, amount: BigNumber.Value) { + constructor(token: Token, amount: bigint) { this.token = token; this.amount = amount; } @@ -25,7 +24,7 @@ export class TokenComputer { constructor() {} isFungible(token: Token): boolean { - return token.nonce === 0; + return token.nonce == 0n; } extractNonceFromExtendedIdentifier(identifier: string): number { diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index d4ab3c621..fe447a9c5 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -1,15 +1,15 @@ +import BigNumber from "bignumber.js"; import { assert, expect } from "chai"; -import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; import { Address } from "../address"; -import { Code } from "../smartcontracts/code"; -import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; -import { U32Value } from "../smartcontracts"; import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; -import { loadContractCode, loadAbiRegistry } from "../testutils/utils"; import { Err } from "../errors"; +import { U32Value } from "../smartcontracts"; +import { Code } from "../smartcontracts/code"; +import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; +import { loadAbiRegistry, loadContractCode } from "../testutils/utils"; +import { NextTokenTransfer, Token, TokenComputer } from "../tokens"; +import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import BigNumber from "bignumber.js"; -import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; describe("test smart contract transactions factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -149,8 +149,8 @@ describe("test smart contract transactions factory", function () { const func = "add"; const gasLimit = 6000000; const args = [new U32Value(7)]; - const token = new Token("FOO-6ce17b", 0); - const transfer = new NextTokenTransfer(token, 10); + const token = new Token("FOO-6ce17b", 0n); + const transfer = new NextTokenTransfer(token, 10n); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -185,10 +185,10 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const fooToken = new Token("FOO-6ce17b", 0); - const fooTransfer = new NextTokenTransfer(fooToken, 10); - const barToken = new Token("BAR-5bc08f", 0); - const barTransfer = new NextTokenTransfer(barToken, 3140); + const fooToken = new Token("FOO-6ce17b", 0n); + const fooTransfer = new NextTokenTransfer(fooToken, 10n); + const barToken = new Token("BAR-5bc08f", 0n); + const barTransfer = new NextTokenTransfer(barToken, 3140n); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -230,8 +230,8 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const token = new Token("NFT-123456", 1); - const transfer = new NextTokenTransfer(token, 1); + const token = new Token("NFT-123456", 1n); + const transfer = new NextTokenTransfer(token, 1n); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -274,10 +274,10 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000; const args = [new U32Value(7)]; - const firstToken = new Token("NFT-123456", 1); - const firstTransfer = new NextTokenTransfer(firstToken, 1); - const secondToken = new Token("NFT-123456", 42); - const secondTransfer = new NextTokenTransfer(secondToken, 1); + const firstToken = new Token("NFT-123456", 1n); + const firstTransfer = new NextTokenTransfer(firstToken, 1n); + const secondToken = new Token("NFT-123456", 42n); + const secondTransfer = new NextTokenTransfer(secondToken, 1n); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 7804e7bd2..593f92759 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,6 +1,6 @@ import { IAddress } from "../interface"; import { NextTokenTransfer, TokenComputer } from "../tokens"; -import { numberToPaddedHex, utf8ToHex, addressToHex } from "../utils.codec"; +import { addressToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { private tokenComputer: TokenComputer; diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 2f6091593..39903b91f 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -1,9 +1,9 @@ import { assert } from "chai"; import { Address } from "../address"; -import { Token, NextTokenTransfer, TokenComputer } from "../tokens"; +import { ErrBadUsage } from "../errors"; +import { NextTokenTransfer, Token, TokenComputer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; -import { ErrBadUsage } from "../errors"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig("D"); @@ -58,8 +58,8 @@ describe("test transfer transcations factory", function () { }); it("should create 'TransactionNext' for esdt transfer", async () => { - const fooToken = new Token("FOO-123456", 0); - const transfer = new NextTokenTransfer(fooToken, 1000000); + const fooToken = new Token("FOO-123456", 0n); + const transfer = new NextTokenTransfer(fooToken, 1000000n); const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -75,8 +75,8 @@ describe("test transfer transcations factory", function () { }); it("should create 'TransactionNext' for nft transfer", async () => { - const nft = new Token("NFT-123456", 10); - const transfer = new NextTokenTransfer(nft, 1); + const nft = new Token("NFT-123456", 10n); + const transfer = new NextTokenTransfer(nft, 1n); const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -95,11 +95,11 @@ describe("test transfer transcations factory", function () { }); it("should create 'TransactionNext' for multiple nft transfers", async () => { - const firstNft = new Token("NFT-123456", 10); - const firstTransfer = new NextTokenTransfer(firstNft, 1); + const firstNft = new Token("NFT-123456", 10n); + const firstTransfer = new NextTokenTransfer(firstNft, 1n); - const secondNft = new Token("TEST-987654", 1); - const secondTransfer = new NextTokenTransfer(secondNft, 1); + const secondNft = new Token("TEST-987654", 1n); + const secondTransfer = new NextTokenTransfer(secondNft, 1n); const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ sender: alice, diff --git a/src/utils.codec.spec.ts b/src/utils.codec.spec.ts index ba38f632c..817496ccb 100644 --- a/src/utils.codec.spec.ts +++ b/src/utils.codec.spec.ts @@ -1,11 +1,19 @@ import { assert } from "chai"; -import { isPaddedHex, numberToPaddedHex, zeroPadStringIfOddLength, byteArrayToHex, utf8ToHex } from "./utils.codec"; +import { byteArrayToHex, isPaddedHex, numberToPaddedHex, utf8ToHex, zeroPadStringIfOddLength } from "./utils.codec"; describe("test codec utils", () => { it("should convert numberToPaddedHex", () => { assert.equal(numberToPaddedHex(1), "01"); assert.equal(numberToPaddedHex(10), "0a"); assert.equal(numberToPaddedHex(256), "0100"); + + assert.equal(numberToPaddedHex(1n), "01"); + assert.equal(numberToPaddedHex(10n), "0a"); + assert.equal(numberToPaddedHex(256n), "0100"); + + assert.equal(numberToPaddedHex("1"), "01"); + assert.equal(numberToPaddedHex("10"), "0a"); + assert.equal(numberToPaddedHex("256"), "0100"); }); it("should check if isPaddedHex", () => { diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 6d3264121..0e03b658b 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -1,10 +1,18 @@ import BigNumber from "bignumber.js"; -import * as contractsCodecUtils from "./smartcontracts/codec/utils"; import { Address } from "./address"; import { IAddress } from "./interface"; +import * as contractsCodecUtils from "./smartcontracts/codec/utils"; + +export function numberToPaddedHex(value: bigint | number | BigNumber.Value) { + let hexableNumber: { toString(radix?: number): string }; + + if (typeof value === "bigint" || typeof value === "number") { + hexableNumber = value; + } else { + hexableNumber = new BigNumber(value); + } -export function numberToPaddedHex(value: BigNumber.Value) { - let hex = new BigNumber(value).toString(16); + const hex = hexableNumber.toString(16); return zeroPadStringIfOddLength(hex); } From bfdb4533c06be465d313d0eece3a59b86d89f85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 14:34:31 +0200 Subject: [PATCH 097/275] ES2015 -> ES2020. --- tsconfig.tests.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.tests.json b/tsconfig.tests.json index 29ec228e4..52a987db1 100644 --- a/tsconfig.tests.json +++ b/tsconfig.tests.json @@ -1,10 +1,10 @@ { "compilerOptions": { "module": "CommonJS", - "target": "ES2015", + "target": "ES2020", "outDir": "out-tests", "lib": [ - "ES2015", + "ES2020", "DOM" ], "sourceMap": true, From 20a6f19e13449897e22260ca9cac7795e63061c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 15:04:41 +0200 Subject: [PATCH 098/275] Fix after review. --- src/tokens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens.ts b/src/tokens.ts index 66d200e0a..361800ac7 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -24,7 +24,7 @@ export class TokenComputer { constructor() {} isFungible(token: Token): boolean { - return token.nonce == 0n; + return token.nonce === 0n; } extractNonceFromExtendedIdentifier(identifier: string): number { From 847be22ae4c5d1ebb091dcd4018b7f41b07b7193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 17:37:56 +0200 Subject: [PATCH 099/275] Add extra methods on Address, wrt. specs. --- src/address.ts | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/address.ts b/src/address.ts index 546017459..123a54175 100644 --- a/src/address.ts +++ b/src/address.ts @@ -138,9 +138,16 @@ export class Address { } /** - * Returns the hex representation of the address (pubkey) + * Use {@link toHex} instead. */ hex(): string { + return this.toHex(); + } + + /** + * Returns the hex representation of the address (pubkey) + */ + toHex(): string { if (this.isEmpty()) { return ""; } @@ -149,9 +156,16 @@ export class Address { } /** - * Returns the bech32 representation of the address + * Use {@link toBech32} instead. */ bech32(): string { + return this.toBech32(); + } + + /** + * Returns the bech32 representation of the address + */ + toBech32(): string { if (this.isEmpty()) { return ""; } @@ -162,9 +176,16 @@ export class Address { } /** - * Returns the pubkey as raw bytes (buffer) + * Use {@link getPublicKey} instead. */ pubkey(): Buffer { + return this.getPublicKey(); + } + + /** + * Returns the pubkey as raw bytes (buffer) + */ + getPublicKey(): Buffer { if (this.isEmpty()) { return Buffer.from([]); } @@ -214,7 +235,17 @@ export class Address { return new Address("0".repeat(64)); } + /** + * Use {@link isSmartContract} instead. + */ isContractAddress(): boolean { return this.hex().startsWith(SMART_CONTRACT_HEX_PUBKEY_PREFIX); } + + /** + * Returns whether the address is a smart contract address. + */ + isSmartContract(): boolean { + return this.isContractAddress(); + } } From 0dd4a3a23307fcc70ca9731a223dfc962e1061c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 19:28:33 +0200 Subject: [PATCH 100/275] Adjust some deprecations. --- src/smartcontracts/transactionPayloadBuilders.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index c70fbdccb..4234381f6 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -6,11 +6,10 @@ import { TypedValue } from "./typesystem"; export const WasmVirtualMachine = "0500"; -/** - * A builder for {@link TransactionPayload} objects, to be used for Smart Contract deployment transactions. - */ /** * @deprecated Use {@link SmartContractTransactionsFactory} instead. + * + * A builder for {@link TransactionPayload} objects, to be used for Smart Contract deployment transactions. */ export class ContractDeployPayloadBuilder { private code: ICode | null = null; @@ -65,6 +64,8 @@ export class ContractDeployPayloadBuilder { } /** + * @deprecated Use {@link SmartContractTransactionsFactory} instead. + * * A builder for {@link TransactionPayload} objects, to be used for Smart Contract upgrade transactions. */ export class ContractUpgradePayloadBuilder { @@ -120,6 +121,8 @@ export class ContractUpgradePayloadBuilder { } /** + * @deprecated Use {@link SmartContractTransactionsFactory} instead. + * * A builder for {@link TransactionPayload} objects, to be used for Smart Contract execution transactions. */ export class ContractCallPayloadBuilder { From fc954bd5083dac2c7b1e160a207bd5c4f932e086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 19:33:38 +0200 Subject: [PATCH 101/275] Breaking change: Address constructor cannot be called with no parameters anymore. Replacement: Address.empty(). --- src/account.ts | 2 +- src/address.spec.ts | 2 +- src/address.ts | 8 ++++---- src/signableMessage.ts | 2 +- src/smartcontracts/interaction.ts | 4 ++-- src/smartcontracts/query.ts | 2 +- src/smartcontracts/resultsParser.spec.ts | 4 ++-- src/smartcontracts/smartContract.ts | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/account.ts b/src/account.ts index 68ccf6092..d371afdc6 100644 --- a/src/account.ts +++ b/src/account.ts @@ -8,7 +8,7 @@ export class Account { /** * The address of the account. */ - readonly address: IAddress = new Address(); + readonly address: IAddress = Address.empty(); /** * The nonce of the account (the account sequence number). diff --git a/src/address.spec.ts b/src/address.spec.ts index 248b858a1..63abaa513 100644 --- a/src/address.spec.ts +++ b/src/address.spec.ts @@ -17,7 +17,7 @@ describe("test address", () => { }); it("should create empty address", async () => { - let nobody = new Address(); + const nobody = Address.empty(); assert.isEmpty(nobody.hex()); assert.isEmpty(nobody.bech32()); diff --git a/src/address.ts b/src/address.ts index 123a54175..b8a4b7c3a 100644 --- a/src/address.ts +++ b/src/address.ts @@ -23,7 +23,7 @@ export class Address { /** * Creates an address object, given a raw string (whether a hex pubkey or a Bech32 address), a sequence of bytes, or another Address object. */ - public constructor(value?: Address | Buffer | string) { + public constructor(value: Address | Buffer | string) { if (!value) { return; } @@ -48,7 +48,7 @@ export class Address { } private static fromValidHex(value: string): Address { - let result = new Address(); + let result = Address.empty(); result.valueHex = value; return result; } @@ -91,10 +91,10 @@ export class Address { } /** - * Creates an empty address object + * Creates an empty address object. Generally speaking, this should not be used in client code (internal use only). */ static empty(): Address { - return new Address(); + return new Address(""); } /** diff --git a/src/signableMessage.ts b/src/signableMessage.ts index 4fe82b7e0..3277e1061 100644 --- a/src/signableMessage.ts +++ b/src/signableMessage.ts @@ -36,7 +36,7 @@ export class SignableMessage { this.signature = Buffer.from([]); this.version = 1; this.signer = "ErdJS"; - this.address = new Address(); + this.address = Address.empty(); Object.assign(this, init); } diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index 1b5b71f37..9cf2b7b76 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -35,9 +35,9 @@ export class Interaction { private gasLimit: IGasLimit = 0; private gasPrice: IGasPrice | undefined = undefined; private chainID: IChainID = ""; - private querent: IAddress = new Address(); + private querent: IAddress = Address.empty(); private explicitReceiver?: IAddress; - private sender: IAddress = new Address(); + private sender: IAddress = Address.empty(); private isWithSingleESDTTransfer: boolean = false; private isWithSingleESDTNFTTransfer: boolean = false; diff --git a/src/smartcontracts/query.ts b/src/smartcontracts/query.ts index a298ebf05..3db545197 100644 --- a/src/smartcontracts/query.ts +++ b/src/smartcontracts/query.ts @@ -18,7 +18,7 @@ export class Query { args?: TypedValue[], value?: ITransactionValue }) { - this.caller = obj.caller || new Address(); + this.caller = obj.caller || Address.empty(); this.address = obj.address; this.func = obj.func; this.args = obj.args || []; diff --git a/src/smartcontracts/resultsParser.spec.ts b/src/smartcontracts/resultsParser.spec.ts index e257cc079..2c033a652 100644 --- a/src/smartcontracts/resultsParser.spec.ts +++ b/src/smartcontracts/resultsParser.spec.ts @@ -202,7 +202,7 @@ describe("test smart contract results parser", () => { it("should parse contract outcome, on signal error", async () => { let transaction = new TransactionOnNetwork({ logs: new TransactionLogs({ - address: new Address(), + address: Address.empty(), events: [ new TransactionEvent({ identifier: "signalError", @@ -222,7 +222,7 @@ describe("test smart contract results parser", () => { it("should parse contract outcome, on too much gas warning", async () => { let transaction = new TransactionOnNetwork({ logs: new TransactionLogs({ - address: new Address(), + address: Address.empty(), events: [ new TransactionEvent({ identifier: "writeLog", diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 788c9d541..7e02329cd 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -31,7 +31,7 @@ interface IAbi { * An abstraction for deploying and interacting with Smart Contracts. */ export class SmartContract implements ISmartContract { - private address: IAddress = new Address(); + private address: IAddress = Address.empty(); private abi?: IAbi; /** @@ -53,7 +53,7 @@ export class SmartContract implements ISmartContract { * Create a SmartContract object by providing its address on the Network. */ constructor(options: { address?: IAddress, abi?: IAbi } = {}) { - this.address = options.address || new Address(); + this.address = options.address || Address.empty(); this.abi = options.abi; if (this.abi) { From 29bf7dbbb0f6c2646f5d4f78f7a466cd3d9f8c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 19:45:57 +0200 Subject: [PATCH 102/275] Breaking change (fixing change): when address is required, but detected to be empty (or zero), an error is thrown (instead of just displaying a WARN). --- src/compatibility.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/compatibility.ts b/src/compatibility.ts index 3aec47640..b214c4f29 100644 --- a/src/compatibility.ts +++ b/src/compatibility.ts @@ -1,26 +1,21 @@ import { Address } from "./address"; +import { Err } from "./errors"; import { IAddress } from "./interface"; /** * For internal use only. */ export class Compatibility { - static areWarningsEnabled: boolean = true; - /** * For internal use only. */ static guardAddressIsSetAndNonZero(address: IAddress | undefined, context: string, resolution: string) { - if (!this.areWarningsEnabled) { - return; - } - if (!address || address.bech32() == "") { - console.warn( + throw new Err( `${context}: address should be set; ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, ); } else if (address.bech32() == Address.Zero().bech32()) { - console.warn( + throw new Err( `${context}: address should not be the 'zero' address (also known as the 'contracts deployment address'); ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, ); } From db67192857cb447c3b03ab732c46b38075e4d6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 15 Feb 2024 19:48:32 +0200 Subject: [PATCH 103/275] Fix comments. --- src/address.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/address.ts b/src/address.ts index b8a4b7c3a..9745ac9c4 100644 --- a/src/address.ts +++ b/src/address.ts @@ -91,7 +91,8 @@ export class Address { } /** - * Creates an empty address object. Generally speaking, this should not be used in client code (internal use only). + * Creates an empty address object. + * Generally speaking, this should not be used by client code (internal use only). */ static empty(): Address { return new Address(""); @@ -229,7 +230,8 @@ export class Address { } /** - * Creates the Zero address (the one that should be used when deploying smart contracts) + * Creates the Zero address (the one that should be used when deploying smart contracts). + * Generally speaking, this should not be used by client code (internal use only). */ static Zero(): Address { return new Address("0".repeat(64)); From 26be4672e8fe2d908bc29c3d2a3a01f2e73648e5 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 15 Feb 2024 20:27:04 +0200 Subject: [PATCH 104/275] first part of replacing BigNumber with BigInt --- src/interface.ts | 8 +- src/smartcontracts/smartContract.ts | 6 +- src/transaction.ts | 52 +++++---- src/transactionNext.spec.ts | 70 ++++++------ .../delegationTransactionsFactory.spec.ts | 43 ++++--- .../delegationTransactionsFactory.ts | 102 ++++++++--------- .../relayedTransactionsFactory.spec.ts | 54 ++++----- .../relayedTransactionsFactory.ts | 34 +++--- .../smartContractTransactionsFactory.ts | 23 ++-- ...anagementTransactionIntentsFactory.spec.ts | 17 ++- .../tokenManagementTransactionsFactory.ts | 94 +++++++++------- .../transactionNextBuilder.ts | 24 ++-- .../transactionsFactoryConfig.ts | 105 +++++++++--------- .../transferTransactionsFactory.spec.ts | 24 ++-- .../transferTransactionsFactory.ts | 31 +++--- 15 files changed, 330 insertions(+), 357 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index 0fe960767..4ab8f6729 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -59,13 +59,13 @@ export type ITokenPayment = ITokenTransfer; export interface ITransactionNext { sender: string; receiver: string; - gasLimit: BigNumber.Value; + gasLimit: bigint; chainID: string; - nonce: BigNumber.Value; - value: BigNumber.Value; + nonce: bigint; + value: bigint; senderUsername: string; receiverUsername: string; - gasPrice: BigNumber.Value; + gasPrice: bigint; data: Uint8Array; version: number; options: number; diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 788c9d541..85f8782f8 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -130,7 +130,7 @@ export class SmartContract implements ISmartContract { const nextTx = scNextTransactionFactory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, - gasLimit: gasLimit.valueOf(), + gasLimit: BigInt(gasLimit.valueOf()), args: initArguments, isUpgradeable: metadataAsJson.upgradeable, isReadable: metadataAsJson.readable, @@ -191,7 +191,7 @@ export class SmartContract implements ISmartContract { sender: caller, contract: this.getAddress(), bytecode: bytecode, - gasLimit: gasLimit.valueOf(), + gasLimit: BigInt(gasLimit.valueOf()), args: initArguments, isUpgradeable: metadataAsJson.upgradeable, isReadable: metadataAsJson.readable, @@ -229,7 +229,7 @@ export class SmartContract implements ISmartContract { sender: caller, contract: receiver ? receiver : this.getAddress(), functionName: func.toString(), - gasLimit: gasLimit.valueOf(), + gasLimit: BigInt(gasLimit.valueOf()), args: args }) diff --git a/src/transaction.ts b/src/transaction.ts index 9518e31aa..68a1d7ce8 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -428,9 +428,9 @@ export class Transaction { const tx = new Transaction({ sender: Address.fromBech32(transaction.sender), receiver: Address.fromBech32(transaction.receiver), - gasLimit: new BigNumber(transaction.gasLimit).toNumber(), + gasLimit: new BigNumber(transaction.gasLimit.toString()).toNumber(), chainID: transaction.chainID, - value: new BigNumber(transaction.value).toFixed(0), + value: new BigNumber(transaction.value.toString()).toFixed(0), data: new TransactionPayload(Buffer.from(transaction.data)), nonce: Number(transaction.nonce), gasPrice: Number(transaction.gasPrice), @@ -485,12 +485,12 @@ export class TransactionNext { /** * The nonce of the transaction (the account sequence number of the sender). */ - public nonce: BigNumber.Value; + public nonce: bigint; /** * The value to transfer. */ - public value: BigNumber.Value; + public value: bigint; /** * The address of the sender. @@ -515,12 +515,12 @@ export class TransactionNext { /** * The gas price to be used. */ - public gasPrice: BigNumber.Value; + public gasPrice: bigint; /** * The maximum amount of gas to be consumed when processing the transaction. */ - public gasLimit: BigNumber.Value; + public gasLimit: bigint; /** * The payload of the transaction. @@ -575,27 +575,27 @@ export class TransactionNext { options, guardian, }: { - nonce?: BigNumber.Value; - value?: BigNumber.Value; + nonce?: bigint; + value?: bigint; sender: string; receiver: string; senderUsername?: string; receiverUsername?: string; - gasPrice?: BigNumber.Value; - gasLimit: BigNumber.Value; + gasPrice?: bigint; + gasLimit: bigint; data?: Uint8Array; chainID: string; version?: number; options?: number; guardian?: string; }) { - this.nonce = nonce || 0; - this.value = value || new BigNumber(0); + this.nonce = nonce || 0n; + this.value = value || 0n; this.sender = sender; this.receiver = receiver; this.senderUsername = senderUsername || ""; this.receiverUsername = receiverUsername || ""; - this.gasPrice = gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE); + this.gasPrice = gasPrice || BigInt(TRANSACTION_MIN_GAS_PRICE); this.gasLimit = gasLimit; this.data = data || new Uint8Array(); this.chainID = chainID; @@ -614,26 +614,24 @@ export class TransactionNext { export class TransactionComputer { constructor() { } - computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): BigNumber { - const moveBalanceGas = new BigNumber( + computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): bigint { + const moveBalanceGas = BigInt( networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte); if (moveBalanceGas > transaction.gasLimit) { throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); } - const gasPrice = new BigNumber(transaction.gasPrice); - const feeForMove = moveBalanceGas.multipliedBy(gasPrice); + const gasPrice = transaction.gasPrice; + const feeForMove = moveBalanceGas * gasPrice; if (moveBalanceGas === transaction.gasLimit) { return feeForMove; } - const diff = new BigNumber(transaction.gasLimit).minus(moveBalanceGas); - const modifiedGasPrice = gasPrice.multipliedBy( - new BigNumber(networkConfig.GasPriceModifier) - ); - const processingFee = diff.multipliedBy(modifiedGasPrice); + const diff = transaction.gasLimit- moveBalanceGas; + const modifiedGasPrice = gasPrice * BigInt(networkConfig.GasPriceModifier); + const processingFee = diff * modifiedGasPrice; - return feeForMove.plus(processingFee); + return feeForMove + processingFee; } computeBytesForSigning(transaction: ITransactionNext): Uint8Array { @@ -670,14 +668,14 @@ export class TransactionComputer { private toPlainObject(transaction: ITransactionNext) { return { - nonce: Number(transaction.nonce), - value: new BigNumber(transaction.value).toFixed(0), + nonce: transaction.nonce, + value: transaction.value.toString(), receiver: transaction.receiver, sender: transaction.sender, senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, - gasPrice: Number(transaction.gasPrice), - gasLimit: Number(transaction.gasLimit), + gasPrice: transaction.gasPrice, + gasLimit: transaction.gasLimit, data: transaction.data && transaction.data.length === 0 ? undefined : Buffer.from(transaction.data).toString("base64"), chainID: transaction.chainID, version: transaction.version, diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts index 3649ad01a..ccb203922 100644 --- a/src/transactionNext.spec.ts +++ b/src/transactionNext.spec.ts @@ -35,10 +35,10 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: sender, receiver: receiver, - gasLimit: 50000, - value: 0, + gasLimit: 50000n, + value: 0n, version: 2, - nonce: 89, + nonce: 89n, }); let serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); @@ -46,17 +46,17 @@ describe("test transaction next", async () => { assert.equal( serializedTransaction, - `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}` + `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}`, ); transaction = new TransactionNext({ chainID: networkConfig.ChainID, sender: sender, receiver: receiver, - gasLimit: 70000, - value: new BigNumber("1000000000000000000"), + gasLimit: 70000n, + value: 1000000000000000000n, version: 2, - nonce: 90, + nonce: 90n, data: new Uint8Array(Buffer.from("hello")), }); @@ -65,7 +65,7 @@ describe("test transaction next", async () => { assert.equal( serializedTransaction, - `{"nonce":90,"value":"1000000000000000000","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":70000,"data":"aGVsbG8=","chainID":"D","version":2}` + `{"nonce":90,"value":"1000000000000000000","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":70000,"data":"aGVsbG8=","chainID":"D","version":2}`, ); }); @@ -74,22 +74,22 @@ describe("test transaction next", async () => { chainID: "T", sender: wallets.carol.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 50000, - value: new BigNumber("1000000000000000000"), + gasLimit: 50000n, + value: 1000000000000000000n, version: 2, - nonce: 204, + nonce: 204n, senderUsername: "carol", receiverUsername: "alice", }); transaction.signature = await wallets.carol.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(transaction)) + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), ); console.log(Buffer.from(transaction.signature).toString("hex")); assert.equal( Buffer.from(transaction.signature).toString("hex"), - "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06" + "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06", ); }); @@ -98,21 +98,21 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 100000, - value: new BigNumber("1000000000000"), + gasLimit: 100000n, + value: 1000000000000n, version: 2, - nonce: 17243, + nonce: 17243n, data: Buffer.from("testtx"), }); transaction.signature = Buffer.from( "eaa9e4dfbd21695d9511e9754bde13e90c5cfb21748a339a79be11f744c71872e9fe8e73c6035c413f5f08eef09e5458e9ea6fc315ff4da0ab6d000b450b2a07", - "hex" + "hex", ); const hash = transactionComputer.computeTransactionHash(transaction); assert.equal( Buffer.from(hash).toString("hex"), - "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03" + "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03", ); }); @@ -121,23 +121,23 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 100000, - value: new BigNumber("1000000000000"), + gasLimit: 100000n, + value: 1000000000000n, version: 2, - nonce: 17244, + nonce: 17244n, data: Buffer.from("testtx"), senderUsername: "alice", receiverUsername: "alice", }); transaction.signature = Buffer.from( "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", - "hex" + "hex", ); const hash = transactionComputer.computeTransactionHash(transaction); assert.equal( Buffer.from(hash).toString("hex"), - "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29" + "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29", ); }); @@ -146,7 +146,7 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 50000, + gasLimit: 50000n, data: Buffer.from("toolittlegaslimit"), }); @@ -160,8 +160,8 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 20, - gasPrice: 500, + gasLimit: 20n, + gasPrice: 500n, }); const config = new NetworkConfig(10); @@ -174,8 +174,8 @@ describe("test transaction next", async () => { chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 12010, - gasPrice: 500, + gasLimit: 12010n, + gasPrice: 500n, data: Buffer.from("testdata"), }); @@ -191,18 +191,18 @@ describe("test transaction next", async () => { chainID: "local-testnet", sender: alice.address.bech32(), receiver: wallets.bob.address.bech32(), - gasLimit: 150000, - gasPrice: 1000000000, + gasLimit: 150000n, + gasPrice: 1000000000n, data: new Uint8Array(Buffer.from("test data field")), version: 2, options: 2, - nonce: 92, - value: new BigNumber("123456789000000000000000000000"), + nonce: 92n, + value: 123456789000000000000000000000n, guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", }); transaction.guardianSignature = new Uint8Array(64); transaction.signature = new Uint8Array( - await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))) + await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), ); const oldTransaction = Transaction.fromTransactionNext(transaction); @@ -211,13 +211,13 @@ describe("test transaction next", async () => { let buffer = serializer.serializeTransaction(oldTransaction); assert.equal( buffer.toString("hex"), - "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", ); const txHash = transactionComputer.computeTransactionHash(transaction); assert.equal( Buffer.from(txHash).toString("hex"), - "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c" + "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c", ); }); }); diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index a36a03343..465f48071 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { Address } from "../address"; import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { assert } from "chai"; @@ -12,9 +11,9 @@ describe("test delegation transactions factory", function () { it("should create 'TransactionNext' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - const delagationCap = "5000000000000000000000"; - const serviceFee = 10; - const value = new BigNumber("1250000000000000000000"); + const delagationCap = 5000000000000000000000n; + const serviceFee = 10n; + const value = 1250000000000000000000n; const transaction = delegationFactory.createTransactionForNewDelegationContract({ sender: sender, @@ -27,7 +26,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, DELEGATION_MANAGER_SC_ADDRESS); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); - assert.equal(transaction.gasLimit.valueOf(), 60126500); + assert.equal(transaction.gasLimit, 60126500n); assert.equal(transaction.value, value); }); @@ -65,7 +64,7 @@ describe("test delegation transactions factory", function () { "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@81109fa1c8d3dc7b6c2d6e65206cc0bc1a83c9b2d1eb91a601d66ad32def430827d5eb52917bd2b0d04ce195738db216", ), ); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for removing nodes", async function () { @@ -88,7 +87,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("removeNodes@61626261")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for staking nodes", async function () { @@ -111,7 +110,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("stakeNodes@61626261")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for unbonding nodes", async function () { @@ -134,8 +133,8 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("unBondNodes@61626261")); - assert.equal(transaction.value, 0); - assert.equal(transaction.gasLimit.valueOf(), 12080000); + assert.equal(transaction.value, 0n); + assert.equal(transaction.gasLimit, 12080000n); }); it("should create 'TransactionNext' for unstaking nodes", async function () { @@ -158,8 +157,8 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("unStakeNodes@61626261")); - assert.equal(transaction.value, 0); - assert.equal(transaction.gasLimit.valueOf(), 12081500); + assert.equal(transaction.value, 0n); + assert.equal(transaction.gasLimit, 12081500n); }); it("should create 'TransactionNext' for unjailing nodes", async function () { @@ -182,13 +181,13 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("unJailNodes@61626261")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const serviceFee = new BigNumber(10); + const serviceFee = 10n; const transaction = delegationFactory.createTransactionForChangingServiceFee({ sender: sender, @@ -200,13 +199,13 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("changeServiceFee@0a")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); - const delegationCap = new BigNumber("5000000000000000000000"); + const delegationCap = 5000000000000000000000n; const transaction = delegationFactory.createTransactionForModifyingDelegationCap({ sender: sender, @@ -218,7 +217,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("modifyTotalDelegationCap@010f0cf064dd59200000")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for setting automatic activation", async function () { @@ -234,7 +233,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("setAutomaticActivation@74727565")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for unsetting automatic activation", async function () { @@ -250,7 +249,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("setAutomaticActivation@66616c7365")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for setting cap check on redelegate rewards", async function () { @@ -266,7 +265,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("setCheckCapOnReDelegateRewards@74727565")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for unsetting cap check on redelegate rewards", async function () { @@ -282,7 +281,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("setCheckCapOnReDelegateRewards@66616c7365")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for setting metadata", async function () { @@ -301,6 +300,6 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); assert.isDefined(transaction.data); assert.deepEqual(transaction.data, Buffer.from("setMetaData@6e616d65@77656273697465@6964656e746966696572")); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); }); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 9e389ab69..89b5c17f1 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,5 +1,4 @@ import { IAddress } from "../interface"; -import { BigNumber } from "bignumber.js"; import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Address } from "../address"; @@ -9,15 +8,15 @@ import { TransactionNext } from "../transaction"; interface Config { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; - gasLimitStake: BigNumber.Value; - gasLimitUnstake: BigNumber.Value; - gasLimitUnbond: BigNumber.Value; - gasLimitCreateDelegationContract: BigNumber.Value; - gasLimitDelegationOperations: BigNumber.Value; - additionalGasLimitPerValidatorNode: BigNumber.Value; - additionalGasLimitForDelegationOperations: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; + gasLimitStake: bigint; + gasLimitUnstake: bigint; + gasLimitUnbond: bigint; + gasLimitCreateDelegationContract: bigint; + gasLimitDelegationOperations: bigint; + additionalGasLimitPerValidatorNode: bigint; + additionalGasLimitForDelegationOperations: bigint; } interface IValidatorPublicKey { @@ -33,9 +32,9 @@ export class DelegationTransactionsFactory { createTransactionForNewDelegationContract(options: { sender: IAddress; - totalDelegationCap: BigNumber.Value; - serviceFee: BigNumber.Value; - amount: BigNumber.Value; + totalDelegationCap: bigint; + serviceFee: bigint; + amount: bigint; }): TransactionNext { const dataParts = [ "createNewDelegationContract", @@ -43,9 +42,8 @@ export class DelegationTransactionsFactory { numberToPaddedHex(options.serviceFee.toString()), ]; - const executionGasLimit = new BigNumber(this.config.gasLimitCreateDelegationContract).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const executionGasLimit = + this.config.gasLimitCreateDelegationContract + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -119,13 +117,10 @@ export class DelegationTransactionsFactory { } const numNodes = options.publicKeys.length; - const additionalGasForAllNodes = new BigNumber(numNodes).multipliedBy( - this.config.additionalGasLimitPerValidatorNode, - ); + const additionalGasForAllNodes = BigInt(numNodes) * this.config.additionalGasLimitPerValidatorNode; - const executionGasLimit = additionalGasForAllNodes - .plus(this.config.gasLimitStake) - .plus(this.config.gasLimitDelegationOperations); + const executionGasLimit = + additionalGasForAllNodes + this.config.gasLimitStake + this.config.gasLimitDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -149,10 +144,10 @@ export class DelegationTransactionsFactory { } const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes) - .multipliedBy(this.config.additionalGasLimitPerValidatorNode) - .plus(this.config.gasLimitUnbond) - .plus(this.config.gasLimitDelegationOperations); + const executionGasLimit = + BigInt(numNodes) * this.config.additionalGasLimitPerValidatorNode + + this.config.gasLimitUnbond + + this.config.gasLimitDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -176,10 +171,10 @@ export class DelegationTransactionsFactory { } const numNodes = options.publicKeys.length; - const executionGasLimit = new BigNumber(numNodes) - .multipliedBy(this.config.additionalGasLimitPerValidatorNode) - .plus(this.config.gasLimitUnstake) - .plus(this.config.gasLimitDelegationOperations); + const executionGasLimit = + BigInt(numNodes) * this.config.additionalGasLimitPerValidatorNode + + this.config.gasLimitUnstake + + this.config.gasLimitDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -216,12 +211,11 @@ export class DelegationTransactionsFactory { createTransactionForChangingServiceFee(options: { sender: IAddress; delegationContract: IAddress; - serviceFee: BigNumber.Value; + serviceFee: bigint; }): TransactionNext { const dataParts = ["changeServiceFee", numberToPaddedHex(options.serviceFee)]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -236,12 +230,11 @@ export class DelegationTransactionsFactory { createTransactionForModifyingDelegationCap(options: { sender: IAddress; delegationContract: IAddress; - delegationCap: BigNumber.Value; + delegationCap: bigint; }): TransactionNext { const dataParts = ["modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap)]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -258,9 +251,8 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; }): TransactionNext { const dataParts = ["setAutomaticActivation", utf8ToHex("true")]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -277,9 +269,8 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; }): TransactionNext { const dataParts = ["setAutomaticActivation", utf8ToHex("false")]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -296,9 +287,8 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; }): TransactionNext { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("true")]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -315,9 +305,8 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; }): TransactionNext { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("false")]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -343,9 +332,8 @@ export class DelegationTransactionsFactory { utf8ToHex(options.identifier), ]; - const gasLimit = new BigNumber(this.config.gasLimitDelegationOperations).plus( - this.config.additionalGasLimitForDelegationOperations, - ); + const gasLimit = + this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; return new TransactionNextBuilder({ config: this.config, @@ -357,11 +345,9 @@ export class DelegationTransactionsFactory { }).build(); } - private computeExecutionGasLimitForNodesManagement(numNodes: number): BigNumber.Value { - const additionalGasForAllNodes = new BigNumber(this.config.additionalGasLimitPerValidatorNode).multipliedBy( - numNodes, - ); + private computeExecutionGasLimitForNodesManagement(numNodes: number): bigint { + const additionalGasForAllNodes = this.config.additionalGasLimitPerValidatorNode * BigInt(numNodes); - return new BigNumber(this.config.gasLimitDelegationOperations).plus(additionalGasForAllNodes); + return this.config.gasLimitDelegationOperations + additionalGasForAllNodes; } } diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index daa36d93a..32fd2e848 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -19,7 +19,7 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: alice.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", - gasLimit: 10000000, + gasLimit: 10000000n, data: Buffer.from("getContractConfig"), chainID: config.chainID, }); @@ -29,7 +29,7 @@ describe("test relayed v1 transaction builder", function () { "The inner transaction is not signed"; }); - innerTransaction.gasLimit = 0; + innerTransaction.gasLimit = 0n; innerTransaction.signature = Buffer.from("invalidsignature"); assert.throws(() => { @@ -42,10 +42,10 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", - gasLimit: 60000000, + gasLimit: 60000000n, data: Buffer.from("getContractConfig"), chainID: config.chainID, - nonce: 198, + nonce: 198n, }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); @@ -55,7 +55,7 @@ describe("test relayed v1 transaction builder", function () { innerTransaction: innerTransaction, relayerAddress: alice.address, }); - relayedTransaction.nonce = 2627; + relayedTransaction.nonce = 2627n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); @@ -74,12 +74,12 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: carol.address.bech32(), receiver: alice.address.bech32(), - gasLimit: 50000, + gasLimit: 50000n, chainID: config.chainID, - nonce: 208, + nonce: 208n, senderUsername: "carol", receiverUsername: "alice", - value: new BigNumber("1000000000000000000"), + value: 1000000000000000000n, }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); @@ -89,7 +89,7 @@ describe("test relayed v1 transaction builder", function () { innerTransaction: innerTransaction, relayerAddress: frank.address, }); - relayedTransaction.nonce = 715; + relayedTransaction.nonce = 715n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); @@ -108,12 +108,12 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: carol.address.bech32(), receiver: alice.address.bech32(), - gasLimit: 50000, + gasLimit: 50000n, chainID: config.chainID, - nonce: 208, + nonce: 208n, senderUsername: "carol", receiverUsername: "alice", - value: new BigNumber("1999999000000000000000000"), + value: 1999999000000000000000000n, }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); @@ -123,7 +123,7 @@ describe("test relayed v1 transaction builder", function () { innerTransaction: innerTransaction, relayerAddress: frank.address, }); - relayedTransaction.nonce = 715; + relayedTransaction.nonce = 715n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); @@ -142,10 +142,10 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", - gasLimit: 60000000, + gasLimit: 60000000n, chainID: config.chainID, data: Buffer.from("getContractConfig"), - nonce: 198, + nonce: 198n, version: 2, options: 2, guardian: grace.address.bech32(), @@ -159,7 +159,7 @@ describe("test relayed v1 transaction builder", function () { innerTransaction: innerTransaction, relayerAddress: alice.address, }); - relayedTransaction.nonce = 2627; + relayedTransaction.nonce = 2627n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); @@ -178,10 +178,10 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", - gasLimit: 60000000, + gasLimit: 60000000n, chainID: config.chainID, data: Buffer.from("addNumber"), - nonce: 198, + nonce: 198n, version: 2, options: 2, guardian: grace.address.bech32(), @@ -195,7 +195,7 @@ describe("test relayed v1 transaction builder", function () { innerTransaction: innerTransaction, relayerAddress: alice.address, }); - relayedTransaction.nonce = 2627; + relayedTransaction.nonce = 2627n; relayedTransaction.options = 2; relayedTransaction.guardian = frank.address.bech32(); @@ -217,25 +217,25 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), receiver: bob.address.bech32(), - gasLimit: 50000, + gasLimit: 50000n, chainID: config.chainID, }); assert.throws(() => { factory.createRelayedV2Transaction({ innerTransaction: innerTransaction, - innerTransactionGasLimit: 50000, + innerTransactionGasLimit: 50000n, relayerAddress: carol.address, }), "The gas limit should not be set for the inner transaction"; }); - innerTransaction.gasLimit = 0; + innerTransaction.gasLimit = 0n; assert.throws(() => { factory.createRelayedV2Transaction({ innerTransaction: innerTransaction, - innerTransactionGasLimit: 50000, + innerTransactionGasLimit: 50000n, relayerAddress: carol.address, }), "The inner transaction is not signed"; @@ -246,10 +246,10 @@ describe("test relayed v1 transaction builder", function () { let innerTransaction = new TransactionNext({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", - gasLimit: 0, + gasLimit: 0n, chainID: config.chainID, data: Buffer.from("getContractConfig"), - nonce: 15, + nonce: 15n, version: 2, options: 0, }); @@ -259,10 +259,10 @@ describe("test relayed v1 transaction builder", function () { const relayedTransaction = factory.createRelayedV2Transaction({ innerTransaction: innerTransaction, - innerTransactionGasLimit: new BigNumber("60000000"), + innerTransactionGasLimit: 60000000n, relayerAddress: alice.address, }); - relayedTransaction.nonce = 37; + relayedTransaction.nonce = 37n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 8893ccd38..4dcf001d2 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -9,8 +9,8 @@ const JSONbig = require("json-bigint"); interface IConfig { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; } export class RelayedTransactionsFactory { @@ -35,12 +35,8 @@ export class RelayedTransactionsFactory { const serializedTransaction = this.prepareInnerTransactionForRelayedV1(options.innerTransaction); const data = `relayedTx@${Buffer.from(serializedTransaction).toString("hex")}`; - const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( - new BigNumber(data.length), - ); - const gasLimit = new BigNumber(this.config.minGasLimit) - .plus(additionalGasForDataLength) - .plus(new BigNumber(options.innerTransaction.gasLimit)); + const additionalGasForDataLength = this.config.gasLimitPerByte * BigInt(data.length); + const gasLimit = this.config.minGasLimit + additionalGasForDataLength + options.innerTransaction.gasLimit; return new TransactionNext({ chainID: this.config.chainID, @@ -53,7 +49,7 @@ export class RelayedTransactionsFactory { createRelayedV2Transaction(options: { innerTransaction: ITransactionNext; - innerTransactionGasLimit: BigNumber.Value; + innerTransactionGasLimit: bigint; relayerAddress: IAddress; }): TransactionNext { if (options.innerTransaction.gasLimit) { @@ -66,24 +62,20 @@ export class RelayedTransactionsFactory { const { argumentsString } = new ArgSerializer().valuesToString([ new AddressValue(Address.fromBech32(options.innerTransaction.receiver)), - new U64Value(options.innerTransaction.nonce), + new U64Value(new BigNumber(options.innerTransaction.nonce.toString())), new BytesValue(Buffer.from(options.innerTransaction.data)), new BytesValue(Buffer.from(options.innerTransaction.signature)), ]); const data = `relayedTxV2@${argumentsString}`; - const additionalGasForDataLength = new BigNumber(this.config.gasLimitPerByte).multipliedBy( - new BigNumber(data.length), - ); - const gasLimit = new BigNumber(options.innerTransactionGasLimit) - .plus(new BigNumber(this.config.minGasLimit)) - .plus(additionalGasForDataLength); + const additionalGasForDataLength = this.config.gasLimitPerByte * BigInt(data.length); + const gasLimit = options.innerTransactionGasLimit + this.config.minGasLimit + additionalGasForDataLength; return new TransactionNext({ sender: options.relayerAddress.bech32(), receiver: options.innerTransaction.sender, - value: 0, + value: 0n, gasLimit: gasLimit, chainID: this.config.chainID, data: Buffer.from(data), @@ -94,12 +86,12 @@ export class RelayedTransactionsFactory { private prepareInnerTransactionForRelayedV1(innerTransaction: TransactionNext): string { const txObject = { - nonce: new BigNumber(innerTransaction.nonce).toNumber(), + nonce: innerTransaction.nonce, sender: Address.fromBech32(innerTransaction.sender).pubkey().toString("base64"), receiver: Address.fromBech32(innerTransaction.receiver).pubkey().toString("base64"), - value: BigInt(new BigNumber(innerTransaction.value).toFixed(0)), - gasPrice: new BigNumber(innerTransaction.gasPrice).toNumber(), - gasLimit: new BigNumber(innerTransaction.gasLimit).toNumber(), + value: innerTransaction.value, + gasPrice: innerTransaction.gasPrice, + gasLimit: innerTransaction.gasLimit, data: Buffer.from(innerTransaction.data).toString("base64"), signature: Buffer.from(innerTransaction.signature).toString("base64"), chainID: Buffer.from(innerTransaction.chainID).toString("base64"), diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index e64e2e774..e6e72685e 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -1,4 +1,3 @@ -import { BigNumber } from "bignumber.js"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; @@ -13,8 +12,8 @@ import { TransactionNext } from "../transaction"; interface Config { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; } interface Abi { @@ -43,15 +42,15 @@ export class SmartContractTransactionsFactory { createTransactionForDeploy(options: { sender: IAddress; bytecode: Uint8Array; - gasLimit: BigNumber.Value; + gasLimit: bigint; args?: any[]; - nativeTransferAmount?: BigNumber.Value; + nativeTransferAmount?: bigint; isUpgradeable?: boolean; isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; }): TransactionNext { - const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; @@ -77,14 +76,14 @@ export class SmartContractTransactionsFactory { sender: IAddress; contract: IAddress; functionName: string; - gasLimit: BigNumber.Value; + gasLimit: bigint; args?: any[]; - nativeTransferAmount?: BigNumber.Value; + nativeTransferAmount?: bigint; tokenTransfers?: NextTokenTransfer[]; }): TransactionNext { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; - const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const numberOfTokens = tokenTransfer.length; if (nativeTransferAmount && numberOfTokens) { @@ -126,15 +125,15 @@ export class SmartContractTransactionsFactory { sender: IAddress; contract: IAddress; bytecode: Uint8Array; - gasLimit: BigNumber.Value; + gasLimit: bigint; args?: any[]; - nativeTransferAmount?: BigNumber.Value; + nativeTransferAmount?: bigint; isUpgradeable?: boolean; isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; }): TransactionNext { - const nativeTransferAmount = options.nativeTransferAmount ?? 0; + const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index b675e0ce1..fc29ceea5 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { assert } from "chai"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { loadTestWallets, TestWallet } from "../testutils"; @@ -22,14 +21,14 @@ describe("test token management transactions factory", () => { tokenName: "TEST", tokenTicker: "TEST", tokenType: "FNG", - numDecimals: 2, + numDecimals: 2n, }); assert.deepEqual(transaction.data, Buffer.from("registerAndSetAllRoles@54455354@54455354@464e47@02")); assert.equal(transaction.sender, frank.address.toString()); assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"); assert.deepEqual(transaction.value, config.issueCost); - assert.deepEqual(transaction.gasLimit, new BigNumber("60125000")); + assert.deepEqual(transaction.gasLimit, 60125000n); }); it("should create 'TransactionNext' for issuing fungible token", () => { @@ -37,8 +36,8 @@ describe("test token management transactions factory", () => { sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", - initialSupply: 100, - numDecimals: 0, + initialSupply: 100n, + numDecimals: 0n, canFreeze: true, canWipe: true, canPause: true, @@ -113,7 +112,7 @@ describe("test token management transactions factory", () => { sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", - numDecimals: 10, + numDecimals: 10n, canFreeze: true, canWipe: true, canPause: true, @@ -154,14 +153,14 @@ describe("test token management transactions factory", () => { ); assert.equal(transaction.sender, frank.address.toString()); assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); it("should create 'TransactionNext' for creating nft", () => { const transaction = tokenManagementFactory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", - initialQuantity: 1, + initialQuantity: 1n, name: "test", royalties: 1000, hash: "abba", @@ -175,6 +174,6 @@ describe("test token management transactions factory", () => { ); assert.equal(transaction.sender, grace.address.toString()); assert.equal(transaction.receiver, grace.address.toString()); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); }); }); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 508c1e289..e26a97d81 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { Address } from "../address"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { IAddress } from "../interface"; @@ -6,25 +5,26 @@ import { Logger } from "../logger"; import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; +import BigNumber from "bignumber.js"; interface Config { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; - gasLimitIssue: BigNumber.Value; - gasLimitToggleBurnRoleGlobally: BigNumber.Value; - gasLimitEsdtLocalMint: BigNumber.Value; - gasLimitEsdtLocalBurn: BigNumber.Value; - gasLimitSetSpecialRole: BigNumber.Value; - gasLimitPausing: BigNumber.Value; - gasLimitFreezing: BigNumber.Value; - gasLimitWiping: BigNumber.Value; - gasLimitEsdtNftCreate: BigNumber.Value; - gasLimitEsdtNftUpdateAttributes: BigNumber.Value; - gasLimitEsdtNftAddQuantity: BigNumber.Value; - gasLimitEsdtNftBurn: BigNumber.Value; - gasLimitStorePerByte: BigNumber.Value; - issueCost: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; + gasLimitIssue: bigint; + gasLimitToggleBurnRoleGlobally: bigint; + gasLimitEsdtLocalMint: bigint; + gasLimitEsdtLocalBurn: bigint; + gasLimitSetSpecialRole: bigint; + gasLimitPausing: bigint; + gasLimitFreezing: bigint; + gasLimitWiping: bigint; + gasLimitEsdtNftCreate: bigint; + gasLimitEsdtNftUpdateAttributes: bigint; + gasLimitEsdtNftAddQuantity: bigint; + gasLimitEsdtNftBurn: bigint; + gasLimitStorePerByte: bigint; + issueCost: bigint; } type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; @@ -44,8 +44,8 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenName: string; tokenTicker: string; - initialSupply: BigNumber.Value; - numDecimals: BigNumber.Value; + initialSupply: bigint; + numDecimals: bigint; canFreeze: boolean; canWipe: boolean; canPause: boolean; @@ -59,8 +59,8 @@ export class TokenManagementTransactionsFactory { "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - bigIntToHex(options.initialSupply), - bigIntToHex(options.numDecimals), + bigIntToHex(new BigNumber(options.initialSupply.toString())), + bigIntToHex(new BigNumber(options.numDecimals.toString())), utf8ToHex("canFreeze"), options.canFreeze ? this.trueAsHex : this.falseAsHex, utf8ToHex("canWipe"), @@ -180,7 +180,7 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenName: string; tokenTicker: string; - numDecimals: BigNumber.Value; + numDecimals: bigint; canFreeze: boolean; canWipe: boolean; canPause: boolean; @@ -195,7 +195,7 @@ export class TokenManagementTransactionsFactory { "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - bigIntToHex(options.numDecimals), + bigIntToHex(new BigNumber(options.numDecimals.toString())), utf8ToHex("canFreeze"), options.canFreeze ? this.trueAsHex : this.falseAsHex, utf8ToHex("canWipe"), @@ -228,7 +228,7 @@ export class TokenManagementTransactionsFactory { tokenName: string; tokenTicker: string; tokenType: RegisterAndSetAllRolesTokenType; - numDecimals: BigNumber.Value; + numDecimals: bigint; }): TransactionNext { this.notifyAboutUnsettingBurnRoleGlobally(); @@ -237,7 +237,7 @@ export class TokenManagementTransactionsFactory { utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), - bigIntToHex(options.numDecimals), + bigIntToHex(new BigNumber(options.numDecimals.toString())), ]; return new TransactionNextBuilder({ @@ -383,7 +383,7 @@ export class TokenManagementTransactionsFactory { createTransactionForCreatingNFT(options: { sender: IAddress; tokenIdentifier: string; - initialQuantity: BigNumber.Value; + initialQuantity: bigint; name: string; royalties: number; hash: string; @@ -393,7 +393,7 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.initialQuantity), + bigIntToHex(new BigNumber(options.initialQuantity.toString())), utf8ToHex(options.name), bigIntToHex(options.royalties), utf8ToHex(options.hash), @@ -403,14 +403,14 @@ export class TokenManagementTransactionsFactory { // Note that the following is an approximation (a reasonable one): const nftData = options.name + options.hash + options.attributes + options.uris.join(""); - const storageGasLimit = new BigNumber(this.config.gasLimitPerByte).multipliedBy(nftData.length); + const storageGasLimit = this.config.gasLimitPerByte + BigInt(nftData.length); return new TransactionNextBuilder({ config: this.config, sender: options.sender, receiver: options.sender, dataParts: dataParts, - gasLimit: new BigNumber(this.config.gasLimitEsdtNftCreate).plus(storageGasLimit), + gasLimit: this.config.gasLimitEsdtNftCreate + storageGasLimit, addDataMovementGas: true, }).build(); } @@ -495,9 +495,13 @@ export class TokenManagementTransactionsFactory { createTransactionForLocalMint(options: { sender: IAddress; tokenIdentifier: string; - supplyToMint: BigNumber.Value; + supplyToMint: bigint; }): TransactionNext { - const dataParts = ["ESDTLocalMint", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToMint)]; + const dataParts = [ + "ESDTLocalMint", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(new BigNumber(options.supplyToMint.toString())), + ]; return new TransactionNextBuilder({ config: this.config, @@ -512,9 +516,13 @@ export class TokenManagementTransactionsFactory { createTransactionForLocalBurning(options: { sender: IAddress; tokenIdentifier: string; - supplyToBurn: BigNumber.Value; + supplyToBurn: bigint; }): TransactionNext { - const dataParts = ["ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), bigIntToHex(options.supplyToBurn)]; + const dataParts = [ + "ESDTLocalBurn", + utf8ToHex(options.tokenIdentifier), + bigIntToHex(new BigNumber(options.supplyToBurn.toString())), + ]; return new TransactionNextBuilder({ config: this.config, @@ -529,13 +537,13 @@ export class TokenManagementTransactionsFactory { createTransactionForUpdatingAttributes(options: { sender: IAddress; tokenIdentifier: string; - tokenNonce: BigNumber.Value; + tokenNonce: bigint; attributes: Uint8Array; }): TransactionNext { const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.tokenNonce), + bigIntToHex(new BigNumber(options.tokenNonce.toString())), byteArrayToHex(options.attributes), ]; @@ -552,14 +560,14 @@ export class TokenManagementTransactionsFactory { createTransactionForAddingQuantity(options: { sender: IAddress; tokenIdentifier: string; - tokenNonce: BigNumber.Value; - quantityToAdd: BigNumber.Value; + tokenNonce: bigint; + quantityToAdd: bigint; }): TransactionNext { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.tokenNonce), - bigIntToHex(options.quantityToAdd), + bigIntToHex(new BigNumber(options.tokenNonce.toString())), + bigIntToHex(new BigNumber(options.quantityToAdd.toString())), ]; return new TransactionNextBuilder({ @@ -575,14 +583,14 @@ export class TokenManagementTransactionsFactory { createTransactionForBurningQuantity(options: { sender: IAddress; tokenIdentifier: string; - tokenNonce: BigNumber.Value; - quantityToBurn: BigNumber.Value; + tokenNonce: bigint; + quantityToBurn: bigint; }): TransactionNext { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), - bigIntToHex(options.tokenNonce), - bigIntToHex(options.quantityToBurn), + bigIntToHex(new BigNumber(options.tokenNonce.toString())), + bigIntToHex(new BigNumber(options.quantityToBurn.toString())), ]; return new TransactionNextBuilder({ diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index c4b440f6d..99967ffcf 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -6,8 +6,8 @@ import { TransactionNext } from "../transaction"; interface Config { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; } export class TransactionNextBuilder { @@ -15,37 +15,35 @@ export class TransactionNextBuilder { private sender: IAddress; private receiver: IAddress; private dataParts: string[]; - private providedGasLimit: BigNumber; + private providedGasLimit: bigint; private addDataMovementGas: boolean; - private amount?: BigNumber.Value; + private amount?: bigint; constructor(options: { config: Config; sender: IAddress; receiver: IAddress; dataParts: string[]; - gasLimit: BigNumber.Value; + gasLimit: bigint; addDataMovementGas: boolean; - amount?: BigNumber.Value; + amount?: bigint; }) { this.config = options.config; this.sender = options.sender; this.receiver = options.receiver; this.dataParts = options.dataParts; - this.providedGasLimit = new BigNumber(options.gasLimit); + this.providedGasLimit = options.gasLimit; this.addDataMovementGas = options.addDataMovementGas; this.amount = options.amount; } - private computeGasLimit(payload: ITransactionPayload): BigNumber.Value { + private computeGasLimit(payload: ITransactionPayload): bigint { if (!this.addDataMovementGas) { return this.providedGasLimit; } - const dataMovementGas = new BigNumber(this.config.minGasLimit).plus( - new BigNumber(this.config.gasLimitPerByte).multipliedBy(payload.length()), - ); - const gasLimit = dataMovementGas.plus(this.providedGasLimit); + const dataMovementGas = this.config.minGasLimit + this.config.gasLimitPerByte * BigInt(payload.length()); + const gasLimit = dataMovementGas + this.providedGasLimit; return gasLimit; } @@ -62,7 +60,7 @@ export class TransactionNextBuilder { sender: this.sender.bech32(), receiver: this.receiver.bech32(), gasLimit: gasLimit, - value: this.amount || 0, + value: this.amount || 0n, data: data.valueOf(), chainID: this.config.toString(), }); diff --git a/src/transactionsFactories/transactionsFactoryConfig.ts b/src/transactionsFactories/transactionsFactoryConfig.ts index c07276701..1115fff9f 100644 --- a/src/transactionsFactories/transactionsFactoryConfig.ts +++ b/src/transactionsFactories/transactionsFactoryConfig.ts @@ -1,71 +1,70 @@ -import { BigNumber } from "bignumber.js"; import { DEFAULT_HRP } from "../constants"; export class TransactionsFactoryConfig { chainID: string; addressHrp: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; - gasLimitIssue: BigNumber.Value; - gasLimitToggleBurnRoleGlobally: BigNumber.Value; - gasLimitEsdtLocalMint: BigNumber.Value; - gasLimitEsdtLocalBurn: BigNumber.Value; - gasLimitSetSpecialRole: BigNumber.Value; - gasLimitPausing: BigNumber.Value; - gasLimitFreezing: BigNumber.Value; - gasLimitWiping: BigNumber.Value; - gasLimitEsdtNftCreate: BigNumber.Value; - gasLimitEsdtNftUpdateAttributes: BigNumber.Value; - gasLimitEsdtNftAddQuantity: BigNumber.Value; - gasLimitEsdtNftBurn: BigNumber.Value; - gasLimitStorePerByte: BigNumber.Value; - issueCost: BigNumber.Value; - gasLimitStake: BigNumber.Value; - gasLimitUnstake: BigNumber.Value; - gasLimitUnbond: BigNumber.Value; - gasLimitCreateDelegationContract: BigNumber.Value; - gasLimitDelegationOperations: BigNumber.Value; - additionalGasLimitPerValidatorNode: BigNumber.Value; - additionalGasLimitForDelegationOperations: BigNumber.Value; - gasLimitESDTTransfer: BigNumber.Value; - gasLimitESDTNFTTransfer: BigNumber.Value; - gasLimitMultiESDTNFTTransfer: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; + gasLimitIssue: bigint; + gasLimitToggleBurnRoleGlobally: bigint; + gasLimitEsdtLocalMint: bigint; + gasLimitEsdtLocalBurn: bigint; + gasLimitSetSpecialRole: bigint; + gasLimitPausing: bigint; + gasLimitFreezing: bigint; + gasLimitWiping: bigint; + gasLimitEsdtNftCreate: bigint; + gasLimitEsdtNftUpdateAttributes: bigint; + gasLimitEsdtNftAddQuantity: bigint; + gasLimitEsdtNftBurn: bigint; + gasLimitStorePerByte: bigint; + issueCost: bigint; + gasLimitStake: bigint; + gasLimitUnstake: bigint; + gasLimitUnbond: bigint; + gasLimitCreateDelegationContract: bigint; + gasLimitDelegationOperations: bigint; + additionalGasLimitPerValidatorNode: bigint; + additionalGasLimitForDelegationOperations: bigint; + gasLimitESDTTransfer: bigint; + gasLimitESDTNFTTransfer: bigint; + gasLimitMultiESDTNFTTransfer: bigint; constructor(chainId: string) { // General-purpose configuration this.chainID = chainId; this.addressHrp = DEFAULT_HRP; - this.minGasLimit = new BigNumber(50000); - this.gasLimitPerByte = new BigNumber(1500); + this.minGasLimit = 50000n; + this.gasLimitPerByte = 1500n; // Configuration for token operations - this.gasLimitIssue = new BigNumber(60000000); - this.gasLimitToggleBurnRoleGlobally = new BigNumber(60000000); - this.gasLimitEsdtLocalMint = new BigNumber(300000); - this.gasLimitEsdtLocalBurn = new BigNumber(300000); - this.gasLimitSetSpecialRole = new BigNumber(60000000); - this.gasLimitPausing = new BigNumber(60000000); - this.gasLimitFreezing = new BigNumber(60000000); - this.gasLimitWiping = new BigNumber(60000000); - this.gasLimitEsdtNftCreate = new BigNumber(3000000); - this.gasLimitEsdtNftUpdateAttributes = new BigNumber(1000000); - this.gasLimitEsdtNftAddQuantity = new BigNumber(1000000); - this.gasLimitEsdtNftBurn = new BigNumber(1000000); - this.gasLimitStorePerByte = new BigNumber(50000); - this.issueCost = new BigNumber("50000000000000000"); + this.gasLimitIssue = 60000000n; + this.gasLimitToggleBurnRoleGlobally = 60000000n; + this.gasLimitEsdtLocalMint = 300000n; + this.gasLimitEsdtLocalBurn = 300000n; + this.gasLimitSetSpecialRole = 60000000n; + this.gasLimitPausing = 60000000n; + this.gasLimitFreezing = 60000000n; + this.gasLimitWiping = 60000000n; + this.gasLimitEsdtNftCreate = 3000000n; + this.gasLimitEsdtNftUpdateAttributes = 1000000n; + this.gasLimitEsdtNftAddQuantity = 1000000n; + this.gasLimitEsdtNftBurn = 1000000n; + this.gasLimitStorePerByte = 50000n; + this.issueCost = 50000000000000000n; // Configuration for delegation operations - this.gasLimitStake = new BigNumber(5000000); - this.gasLimitUnstake = new BigNumber(5000000); - this.gasLimitUnbond = new BigNumber(5000000); - this.gasLimitCreateDelegationContract = new BigNumber(50000000); - this.gasLimitDelegationOperations = new BigNumber(1000000); - this.additionalGasLimitPerValidatorNode = new BigNumber(6000000); - this.additionalGasLimitForDelegationOperations = new BigNumber(10000000); + this.gasLimitStake = 5000000n; + this.gasLimitUnstake = 5000000n; + this.gasLimitUnbond = 5000000n; + this.gasLimitCreateDelegationContract = 50000000n; + this.gasLimitDelegationOperations = 1000000n; + this.additionalGasLimitPerValidatorNode = 6000000n; + this.additionalGasLimitForDelegationOperations = 10000000n; // Configuration for token transfers - this.gasLimitESDTTransfer = new BigNumber(200000); - this.gasLimitESDTNFTTransfer = new BigNumber(200000); - this.gasLimitMultiESDTNFTTransfer = new BigNumber(200000); + this.gasLimitESDTTransfer = 200000n; + this.gasLimitESDTNFTTransfer = 200000n; + this.gasLimitMultiESDTNFTTransfer = 200000n; } } diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 39903b91f..fcf09b097 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -32,13 +32,13 @@ describe("test transfer transcations factory", function () { const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, - nativeAmount: "1000000000000000000", + nativeAmount: 1000000000000000000n, }); assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "1000000000000000000"); - assert.equal(transaction.gasLimit.valueOf(), "50000"); + assert.equal(transaction.value.valueOf(), 1000000000000000000n); + assert.equal(transaction.gasLimit.valueOf(), 50000n); assert.deepEqual(transaction.data, new Uint8Array()); }); @@ -46,14 +46,14 @@ describe("test transfer transcations factory", function () { const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, - nativeAmount: "1000000000000000000", + nativeAmount: 1000000000000000000n, data: "test data", }); assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "1000000000000000000"); - assert.equal(transaction.gasLimit.valueOf(), "63500"); + assert.equal(transaction.value.valueOf(), 1000000000000000000n); + assert.equal(transaction.gasLimit.valueOf(), 63500n); assert.deepEqual(transaction.data, Buffer.from("test data")); }); @@ -69,8 +69,8 @@ describe("test transfer transcations factory", function () { assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, bob.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "410000"); + assert.equal(transaction.value.valueOf(), 0n); + assert.equal(transaction.gasLimit.valueOf(), 410000n); assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); @@ -86,8 +86,8 @@ describe("test transfer transcations factory", function () { assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, alice.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "1210500"); + assert.equal(transaction.value.valueOf(), 0n); + assert.equal(transaction.gasLimit.valueOf(), 1210500n); assert.deepEqual( transaction.data.toString(), "ESDTNFTTransfer@4e46542d313233343536@0a@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8", @@ -109,8 +109,8 @@ describe("test transfer transcations factory", function () { assert.equal(transaction.sender, alice.bech32()); assert.equal(transaction.receiver, alice.bech32()); - assert.equal(transaction.value.valueOf(), "0"); - assert.equal(transaction.gasLimit.valueOf(), "1466000"); + assert.equal(transaction.value.valueOf(), 0n); + assert.equal(transaction.gasLimit.valueOf(), 1466000n); assert.deepEqual( transaction.data.toString(), "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@4e46542d313233343536@0a@01@544553542d393837363534@01@01", diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index ad606c652..1160a32a6 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { IAddress } from "../interface"; import { NextTokenTransfer, Token } from "../tokens"; @@ -11,11 +10,11 @@ const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; interface IConfig { chainID: string; - minGasLimit: BigNumber.Value; - gasLimitPerByte: BigNumber.Value; - gasLimitESDTTransfer: BigNumber.Value; - gasLimitESDTNFTTransfer: BigNumber.Value; - gasLimitMultiESDTNFTTransfer: BigNumber.Value; + minGasLimit: bigint; + gasLimitPerByte: bigint; + gasLimitESDTTransfer: bigint; + gasLimitESDTNFTTransfer: bigint; + gasLimitMultiESDTNFTTransfer: bigint; } interface TokenComputer { @@ -36,7 +35,7 @@ export class NextTransferTransactionsFactory { createTransactionForNativeTokenTransfer(options: { sender: IAddress; receiver: IAddress; - nativeAmount: BigNumber.Value; + nativeAmount: bigint; data?: string; }): TransactionNext { const data = options.data || ""; @@ -46,7 +45,7 @@ export class NextTransferTransactionsFactory { sender: options.sender, receiver: options.receiver, dataParts: [data], - gasLimit: 0, + gasLimit: 0n, addDataMovementGas: true, amount: options.nativeAmount, }).build(); @@ -72,9 +71,9 @@ export class NextTransferTransactionsFactory { options.tokenTransfers, ); - const extraGasForTransfer = new BigNumber(this.config.gasLimitMultiESDTNFTTransfer) - .multipliedBy(new BigNumber(numberOfTransfers)) - .plus(new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER)); + const extraGasForTransfer = + this.config.gasLimitMultiESDTNFTTransfer * BigInt(numberOfTransfers) + + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); return new TransactionNextBuilder({ config: this.config, @@ -93,19 +92,15 @@ export class NextTransferTransactionsFactory { }): TransactionNext { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; - let extraGasForTransfer = new BigNumber(0); + let extraGasForTransfer = 0n; let receiver = options.receiver; if (this.tokenComputer.isFungible(transfer.token)) { transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_TRANSFER), - ); + extraGasForTransfer = this.config.gasLimitESDTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_TRANSFER); } else { transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasForTransfer = new BigNumber(this.config.gasLimitESDTNFTTransfer).plus( - new BigNumber(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER), - ); + extraGasForTransfer = this.config.gasLimitESDTNFTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); receiver = options.sender; } From 42498c3b384b8abf1f21a8326b3eb3462b48f38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 16 Feb 2024 09:48:40 +0200 Subject: [PATCH 105/275] Minor refactoring. Additional tests. --- src/address.spec.ts | 12 ++++++++++++ src/address.ts | 22 +++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/address.spec.ts b/src/address.spec.ts index 63abaa513..48313ab04 100644 --- a/src/address.spec.ts +++ b/src/address.spec.ts @@ -55,4 +55,16 @@ describe("test address", () => { assert.isFalse(Address.isValid("xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz")); assert.isFalse(Address.isValid("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2")); }); + + it("should check whether isSmartContract", () => { + assert.isFalse( + Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th").isSmartContract(), + ); + assert.isTrue( + Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l").isSmartContract(), + ); + assert.isTrue( + Address.fromBech32("erd1qqqqqqqqqqqqqpgqxwakt2g7u9atsnr03gqcgmhcv38pt7mkd94q6shuwt").isSmartContract(), + ); + }); }); diff --git a/src/address.ts b/src/address.ts index 9745ac9c4..a5b3fda5d 100644 --- a/src/address.ts +++ b/src/address.ts @@ -110,12 +110,12 @@ export class Address { throw new errors.ErrAddressCannotCreate(value, err); } - let prefix = decoded.prefix; + const prefix = decoded.prefix; if (prefix != HRP) { throw new errors.ErrAddressBadHrp(HRP, prefix); } - let pubkey = Buffer.from(bech32.fromWords(decoded.words)); + const pubkey = Buffer.from(bech32.fromWords(decoded.words)); if (pubkey.length != PUBKEY_LENGTH) { throw new errors.ErrAddressCannotCreate(value); } @@ -194,6 +194,14 @@ export class Address { return Buffer.from(this.valueHex, "hex"); } + /** + * Returns the human-readable-part of the bech32 addresses. + * The HRP is currently hardcoded to "erd". + */ + getHrp(): string { + return HRP; + } + /** * Returns whether the address is empty. */ @@ -216,7 +224,7 @@ export class Address { * Returns the bech32 representation of the address */ toString(): string { - return this.bech32(); + return this.toBech32(); } /** @@ -224,8 +232,8 @@ export class Address { */ toJSON(): object { return { - bech32: this.bech32(), - pubkey: this.hex(), + bech32: this.toBech32(), + pubkey: this.toHex(), }; } @@ -241,13 +249,13 @@ export class Address { * Use {@link isSmartContract} instead. */ isContractAddress(): boolean { - return this.hex().startsWith(SMART_CONTRACT_HEX_PUBKEY_PREFIX); + return this.isSmartContract(); } /** * Returns whether the address is a smart contract address. */ isSmartContract(): boolean { - return this.isContractAddress(); + return this.toHex().startsWith(SMART_CONTRACT_HEX_PUBKEY_PREFIX); } } From 57a6e19aeb21030442fffdad58aafc79ea4e4aba Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 11:13:53 +0200 Subject: [PATCH 106/275] fixes after replacing BigNumber with BigInt --- src/transaction.spec.ts | 8 +-- src/transaction.ts | 8 +-- src/transactionNext.spec.ts | 1 - .../relayedTransactionsFactory.spec.ts | 1 - .../smartContractTransactionsFactory.spec.ts | 51 +++++++++---------- .../transactionNextBuilder.ts | 1 - 6 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 988c8f418..755529b64 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -22,8 +22,8 @@ describe("test transaction construction", async () => { const plainTransactionNextObject = { sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - gasLimit: 56000, - value: "1000000000000000000", + gasLimit: 56000n, + value: 1000000000000000000n, data: Buffer.from("test"), chainID: "T" }; @@ -32,8 +32,8 @@ describe("test transaction construction", async () => { const transaction = Transaction.fromTransactionNext(nextTransaction); assert.deepEqual(transaction.getSender(), Address.fromBech32(plainTransactionNextObject.sender)); assert.deepEqual(transaction.getReceiver(), Address.fromBech32(plainTransactionNextObject.receiver)); - assert.equal(transaction.getGasLimit().valueOf(), plainTransactionNextObject.gasLimit); - assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value); + assert.equal(transaction.getGasLimit().valueOf().toFixed(0), plainTransactionNextObject.gasLimit.toString()); + assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value.toString()); assert.equal(transaction.getData().toString(), plainTransactionNextObject.data.toString()); assert.equal(transaction.getChainID().valueOf(), plainTransactionNextObject.chainID); assert.equal(transaction.getNonce().valueOf(), 0); diff --git a/src/transaction.ts b/src/transaction.ts index 68a1d7ce8..07301c6a5 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -628,7 +628,7 @@ export class TransactionComputer { } const diff = transaction.gasLimit- moveBalanceGas; - const modifiedGasPrice = gasPrice * BigInt(networkConfig.GasPriceModifier); + const modifiedGasPrice = BigInt(new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0)); const processingFee = diff * modifiedGasPrice; return feeForMove + processingFee; @@ -668,14 +668,14 @@ export class TransactionComputer { private toPlainObject(transaction: ITransactionNext) { return { - nonce: transaction.nonce, + nonce: Number(transaction.nonce), value: transaction.value.toString(), receiver: transaction.receiver, sender: transaction.sender, senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, - gasPrice: transaction.gasPrice, - gasLimit: transaction.gasLimit, + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), data: transaction.data && transaction.data.length === 0 ? undefined : Buffer.from(transaction.data).toString("base64"), chainID: transaction.chainID, version: transaction.version, diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts index ccb203922..78a46832f 100644 --- a/src/transactionNext.spec.ts +++ b/src/transactionNext.spec.ts @@ -1,7 +1,6 @@ import { assert } from "chai"; import { TestWallet, loadTestWallets } from "./testutils"; import { TransactionNext, TransactionComputer, Transaction } from "./transaction"; -import BigNumber from "bignumber.js"; import { ProtoSerializer } from "./proto"; class NetworkConfig { diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 32fd2e848..24aa83e48 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -3,7 +3,6 @@ import { TestWallet, loadTestWallets } from "../testutils"; import { TransactionComputer, TransactionNext } from "../transaction"; import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import BigNumber from "bignumber.js"; describe("test relayed v1 transaction builder", function () { const config = new TransactionsFactoryConfig("T"); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index fe447a9c5..eabe4664f 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -1,4 +1,3 @@ -import BigNumber from "bignumber.js"; import { assert, expect } from "chai"; import { Address } from "../address"; import { CONTRACT_DEPLOY_ADDRESS } from "../constants"; @@ -36,7 +35,7 @@ describe("test smart contract transactions factory", function () { it("should throw error when args are not of type 'TypedValue'", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [0]; assert.throws( @@ -54,7 +53,7 @@ describe("test smart contract transactions factory", function () { it("should create 'TransactionNext' for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(0)]; const transaction = smartContractFactory.createTransactionForDeploy({ @@ -74,7 +73,7 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.receiver, CONTRACT_DEPLOY_ADDRESS); expect(transaction.data.length).to.be.greaterThan(0); assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value, 0); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiDeployNext); }); @@ -83,7 +82,7 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(7)]; const transaction = smartContractFactory.createTransactionForExecute({ @@ -104,8 +103,8 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.deepEqual(transaction.data, Buffer.from("add@07")); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value, 0); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -114,8 +113,8 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; - const gasLimit = 6000000; - const egldAmount = new BigNumber("1000000000000000000"); + const gasLimit = 6000000n; + const egldAmount = 1000000000000000000n; const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -137,8 +136,8 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.deepEqual(transaction.data, Buffer.from("add@07")); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value.valueOf(), "1000000000000000000"); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 1000000000000000000n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -147,7 +146,7 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(7)]; const token = new Token("FOO-6ce17b", 0n); const transfer = new NextTokenTransfer(token, 10n); @@ -172,8 +171,8 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.deepEqual(transaction.data, Buffer.from("ESDTTransfer@464f4f2d366365313762@0a@616464@07")); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -182,7 +181,7 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); const func = "add"; - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(7)]; const fooToken = new Token("FOO-6ce17b", 0n); @@ -217,8 +216,8 @@ describe("test smart contract transactions factory", function () { ), ); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -227,7 +226,7 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(7)]; const token = new Token("NFT-123456", 1n); @@ -261,8 +260,8 @@ describe("test smart contract transactions factory", function () { ), ); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -271,7 +270,7 @@ describe("test smart contract transactions factory", function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(7)]; const firstToken = new Token("NFT-123456", 1n); @@ -307,8 +306,8 @@ describe("test smart contract transactions factory", function () { ), ); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value.valueOf(), "0"); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiExecuteNext); }); @@ -316,7 +315,7 @@ describe("test smart contract transactions factory", function () { it("should create 'TransactionNext' for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); - const gasLimit = 6000000; + const gasLimit = 6000000n; const args = [new U32Value(0)]; const transaction = smartContractFactory.createTransactionForUpgrade({ @@ -338,8 +337,8 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); assert.equal(transaction.receiver, "erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); assert.isTrue(Buffer.from(transaction.data!).toString().startsWith("upgradeContract@")); - assert.equal(transaction.gasLimit.valueOf(), gasLimit); - assert.equal(transaction.value, 0); + assert.equal(transaction.gasLimit, gasLimit); + assert.equal(transaction.value, 0n); assert.deepEqual(transaction, abiUpgradeNext); }); diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index 99967ffcf..e1c8b0496 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -1,4 +1,3 @@ -import { BigNumber } from "bignumber.js"; import { IAddress, ITransactionPayload } from "../interface"; import { ARGUMENTS_SEPARATOR } from "../constants"; import { TransactionPayload } from "../transactionPayload"; From e76a3c28de92b29d628c4efa3e88f06da0980d68 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 12:29:16 +0200 Subject: [PATCH 107/275] fixes after review --- src/transaction.ts | 58 ++----- ...anagementTransactionsOutcomeParser.spec.ts | 144 +++++++----------- ...okenManagementTransactionsOutcomeParser.ts | 30 ++-- 3 files changed, 88 insertions(+), 144 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 9518e31aa..746482b6f 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -560,51 +560,25 @@ export class TransactionNext { /** * Creates a new Transaction object. */ - public constructor({ - sender, - receiver, - gasLimit, - chainID, - nonce, - value, - senderUsername, - receiverUsername, - gasPrice, - data, - version, - options, - guardian, - }: { - nonce?: BigNumber.Value; - value?: BigNumber.Value; - sender: string; - receiver: string; - senderUsername?: string; - receiverUsername?: string; - gasPrice?: BigNumber.Value; - gasLimit: BigNumber.Value; - data?: Uint8Array; - chainID: string; - version?: number; - options?: number; - guardian?: string; - }) { - this.nonce = nonce || 0; - this.value = value || new BigNumber(0); - this.sender = sender; - this.receiver = receiver; - this.senderUsername = senderUsername || ""; - this.receiverUsername = receiverUsername || ""; - this.gasPrice = gasPrice || new BigNumber(TRANSACTION_MIN_GAS_PRICE); - this.gasLimit = gasLimit; - this.data = data || new Uint8Array(); - this.chainID = chainID; - this.version = version || TRANSACTION_VERSION_DEFAULT; - this.options = options || TRANSACTION_OPTIONS_DEFAULT; - this.guardian = guardian || ""; + public constructor(init: Partial) { + this.nonce = 0; + this.value = new BigNumber(0); + this.sender = ""; + this.receiver = ""; + this.senderUsername = ""; + this.receiverUsername = ""; + this.gasPrice = new BigNumber(TRANSACTION_MIN_GAS_PRICE); + this.gasLimit = 0; + this.data = new Uint8Array(); + this.chainID = ""; + this.version = TRANSACTION_VERSION_DEFAULT; + this.options = TRANSACTION_OPTIONS_DEFAULT; + this.guardian = ""; this.signature = new Uint8Array(); this.guardianSignature = new Uint8Array(); + + Object.assign(this, init); } } diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index 976ea5a90..a95813f81 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -15,8 +15,7 @@ describe("test token management transactions outcome parser", () => { }); const logs = new TransactionLogs({ events: [event] }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ transactionLogs: logs }); assert.throws( () => { @@ -28,8 +27,8 @@ describe("test token management transactions outcome parser", () => { }); it("should test parse issue fungible", () => { - const identifer = "ZZZ-9ee87d"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "ZZZ-9ee87d"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -42,16 +41,15 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse issue non fungible", () => { - const identifer = "NFT-f01d1e"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const firstEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -76,16 +74,15 @@ describe("test token management transactions outcome parser", () => { events: [firstEvent, secondEvent, thirdEvent], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueNonFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse issue semi fungible", () => { - const identifer = "SEMIFNG-2c6d9f"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "SEMIFNG-2c6d9f"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -98,16 +95,15 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueSemiFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse register meta esdt", () => { - const identifer = "METATEST-e05d11"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "METATEST-e05d11"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -120,16 +116,15 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseRegisterMetaEsdt(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse register and set all roles", () => { - const identifer = "LMAO-d9f892"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "LMAO-d9f892"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const roles = ["ESDTRoleLocalMint", "ESDTRoleLocalBurn"]; const event = new TransactionEvent({ @@ -170,13 +165,13 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseRegisterAndSetAllRoles(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.deepEqual(outcome.roles, roles); }); it("should test parse register set special role", () => { - const identifer = "METATEST-e05d11"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "METATEST-e05d11"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const roles = ["ESDTRoleNFTCreate", "ESDTRoleNFTAddQuantity", "ESDTRoleNFTBurn"]; const event = new TransactionEvent({ @@ -197,22 +192,19 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseSetSpecialRole(txOutcome); assert.equal(outcome.userAddress, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.deepEqual(outcome.roles, roles); }); it("should test parse nft create", () => { - const identifer = "NFT-f01d1e"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(1); const initialQuantity = BigInt(1); @@ -232,22 +224,19 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseNftCreate(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.initialQuantity, initialQuantity); }); it("should test parse local mint", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(0); const mintedSupply = BigInt(100000); @@ -262,23 +251,20 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseLocalMint(txOutcome); assert.equal(outcome.userAddress, event.address); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.mintedSupply, mintedSupply); }); it("should test parse local burn", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(0); const burntSupply = BigInt(100000); @@ -293,23 +279,20 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseLocalBurn(txOutcome); assert.equal(outcome.userAddress, event.address); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.burntSupply, burntSupply); }); it("should test parse pause", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -322,20 +305,17 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parsePause(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse unpause", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -348,20 +328,17 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseUnpause(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); }); it("should test parse freeze", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(0); const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; @@ -390,14 +367,14 @@ describe("test token management transactions outcome parser", () => { const outcome = parser.parseFreeze(txOutcome); assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.balance, balance); }); it("should test parse unfreeze", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(0); const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; @@ -426,14 +403,14 @@ describe("test token management transactions outcome parser", () => { const outcome = parser.parseUnfreeze(txOutcome); assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.balance, balance); }); it("should test parse wipe", () => { - const identifer = "AAA-29c4c9"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "AAA-29c4c9"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(0); const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; @@ -462,14 +439,14 @@ describe("test token management transactions outcome parser", () => { const outcome = parser.parseWipe(txOutcome); assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.balance, balance); }); it("should test parse update attributes", () => { - const identifer = "NFT-f01d1e"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(1); const attributes = "metadata:ipfsCID/test.json;tags:tag1,tag2"; const base64Attributes = Buffer.from(attributes).toString("base64"); @@ -485,22 +462,19 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseUpdateAttributes(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(Buffer.from(outcome.attributes).toString(), attributes); }); it("should test parse add quantity", () => { - const identifer = "NFT-f01d1e"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(1); const addedQuantity = BigInt(10); @@ -515,22 +489,19 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseAddQuantity(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.addedQuantity, addedQuantity); }); it("should test parse burn quantity", () => { - const identifer = "NFT-f01d1e"; - const base64Identifier = Buffer.from(identifer).toString("base64"); + const identifier = "NFT-f01d1e"; + const base64Identifier = Buffer.from(identifier).toString("base64"); const nonce = BigInt(1); const burntQuantity = BigInt(16); @@ -545,15 +516,12 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const scResult = new SmartContractResult({}); - const txOutcome = new TransactionOutcome({ - smartContractResults: [scResult], transactionLogs: transactionLogs, }); const outcome = parser.parseBurnQuantity(txOutcome); - assert.equal(outcome.tokenIdentifier, identifer); + assert.equal(outcome.tokenIdentifier, identifier); assert.equal(outcome.nonce, nonce); assert.equal(outcome.burntQuantity, burntQuantity); }); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index 0c7ad9436..f9b389ebc 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -10,36 +10,36 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const event = this.findSingleEventByIdentifier(transactionOutcome, "issue"); - const identifer = this.extractTokenIdentifier(event); + const identifier = this.extractTokenIdentifier(event); - return { tokenIdentifier: identifer }; + return { tokenIdentifier: identifier }; } parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { this.ensureNoError(transactionOutcome.transactionLogs.events); const event = this.findSingleEventByIdentifier(transactionOutcome, "issueNonFungible"); - const identifer = this.extractTokenIdentifier(event); + const identifier = this.extractTokenIdentifier(event); - return { tokenIdentifier: identifer }; + return { tokenIdentifier: identifier }; } parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { this.ensureNoError(transactionOutcome.transactionLogs.events); const event = this.findSingleEventByIdentifier(transactionOutcome, "issueSemiFungible"); - const identifer = this.extractTokenIdentifier(event); + const identifier = this.extractTokenIdentifier(event); - return { tokenIdentifier: identifer }; + return { tokenIdentifier: identifier }; } parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { this.ensureNoError(transactionOutcome.transactionLogs.events); const event = this.findSingleEventByIdentifier(transactionOutcome, "registerMetaESDT"); - const identifer = this.extractTokenIdentifier(event); + const identifier = this.extractTokenIdentifier(event); - return { tokenIdentifier: identifer }; + return { tokenIdentifier: identifier }; } parseRegisterAndSetAllRoles(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; roles: string[] } { @@ -53,8 +53,7 @@ export class TokenManagementTransactionsOutcomeParser { let roles: string[] = []; for (const role of encodedRoles) { - const decodedRole = Buffer.from(role, "base64"); - roles = roles.concat(decodedRole.toString()); + roles = roles.concat(this.decodeTopicAsString(role)); } return { tokenIdentifier: tokenIdentifier, roles: roles }; @@ -83,8 +82,7 @@ export class TokenManagementTransactionsOutcomeParser { let roles: string[] = []; for (const role of encodedRoles) { - const decodedRole = Buffer.from(role, "base64"); - roles = roles.concat(decodedRole.toString()); + roles = roles.concat(this.decodeTopicAsString(role)); } return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; @@ -294,7 +292,7 @@ export class TokenManagementTransactionsOutcomeParser { for (const event of transactionEvents) { if (event.identifier == "signalError") { const data = Buffer.from(event.data.toString().slice(1)).toString(); - const message = Buffer.from(event.topics[1], "base64").toString(); + const message = this.decodeTopicAsString(event.topics[1]); throw new ErrParseTransactionOutcome( `encountered signalError: ${message} (${Buffer.from(data, "hex").toString()})`, @@ -332,7 +330,7 @@ export class TokenManagementTransactionsOutcomeParser { if (!event.topics[0]) { return ""; } - return Buffer.from(event.topics[0], "base64").toString(); + return this.decodeTopicAsString(event.topics[0]); } private extractNonce(event: TransactionEvent): bigint { @@ -358,4 +356,8 @@ export class TokenManagementTransactionsOutcomeParser { const address = Buffer.from(event.topics[3], "base64"); return Address.fromBuffer(address).bech32(); } + + private decodeTopicAsString(topic: string): string { + return Buffer.from(topic, "base64").toString(); + } } From 4680e993422ffde075de09e053ab34857748f9b7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 13:55:55 +0200 Subject: [PATCH 108/275] fixes after review --- src/transaction.spec.ts | 2 +- src/transaction.ts | 2 +- ...anagementTransactionIntentsFactory.spec.ts | 2 +- .../tokenManagementTransactionsFactory.ts | 29 +++++++++---------- src/utils.codec.spec.ts | 3 ++ 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 755529b64..1ca9e6903 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -32,7 +32,7 @@ describe("test transaction construction", async () => { const transaction = Transaction.fromTransactionNext(nextTransaction); assert.deepEqual(transaction.getSender(), Address.fromBech32(plainTransactionNextObject.sender)); assert.deepEqual(transaction.getReceiver(), Address.fromBech32(plainTransactionNextObject.receiver)); - assert.equal(transaction.getGasLimit().valueOf().toFixed(0), plainTransactionNextObject.gasLimit.toString()); + assert.equal(transaction.getGasLimit().valueOf().toString(), plainTransactionNextObject.gasLimit.toString()); assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value.toString()); assert.equal(transaction.getData().toString(), plainTransactionNextObject.data.toString()); assert.equal(transaction.getChainID().valueOf(), plainTransactionNextObject.chainID); diff --git a/src/transaction.ts b/src/transaction.ts index 07301c6a5..e61d0ea4f 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -428,7 +428,7 @@ export class Transaction { const tx = new Transaction({ sender: Address.fromBech32(transaction.sender), receiver: Address.fromBech32(transaction.receiver), - gasLimit: new BigNumber(transaction.gasLimit.toString()).toNumber(), + gasLimit: Number(transaction.gasLimit), chainID: transaction.chainID, value: new BigNumber(transaction.value.toString()).toFixed(0), data: new TransactionPayload(Buffer.from(transaction.data)), diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index fc29ceea5..c6ad61695 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -49,7 +49,7 @@ describe("test token management transactions factory", () => { assert.deepEqual( next.data, Buffer.from( - "issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + "issue@4652414e4b@4652414e4b@64@00@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", ), ); assert.equal(next.sender, frank.address.toString()); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index e26a97d81..03791e6f8 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -2,10 +2,9 @@ import { Address } from "../address"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { IAddress } from "../interface"; import { Logger } from "../logger"; -import { addressToHex, bigIntToHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; +import { addressToHex, byteArrayToHex, utf8ToHex, numberToPaddedHex } from "../utils.codec"; import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; -import BigNumber from "bignumber.js"; interface Config { chainID: string; @@ -59,8 +58,8 @@ export class TokenManagementTransactionsFactory { "issue", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - bigIntToHex(new BigNumber(options.initialSupply.toString())), - bigIntToHex(new BigNumber(options.numDecimals.toString())), + numberToPaddedHex(options.initialSupply), + numberToPaddedHex(options.numDecimals), utf8ToHex("canFreeze"), options.canFreeze ? this.trueAsHex : this.falseAsHex, utf8ToHex("canWipe"), @@ -195,7 +194,7 @@ export class TokenManagementTransactionsFactory { "registerMetaESDT", utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), - bigIntToHex(new BigNumber(options.numDecimals.toString())), + numberToPaddedHex(options.numDecimals), utf8ToHex("canFreeze"), options.canFreeze ? this.trueAsHex : this.falseAsHex, utf8ToHex("canWipe"), @@ -237,7 +236,7 @@ export class TokenManagementTransactionsFactory { utf8ToHex(options.tokenName), utf8ToHex(options.tokenTicker), utf8ToHex(options.tokenType), - bigIntToHex(new BigNumber(options.numDecimals.toString())), + numberToPaddedHex(options.numDecimals), ]; return new TransactionNextBuilder({ @@ -393,9 +392,9 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.initialQuantity.toString())), + numberToPaddedHex(options.initialQuantity), utf8ToHex(options.name), - bigIntToHex(options.royalties), + numberToPaddedHex(options.royalties), utf8ToHex(options.hash), byteArrayToHex(options.attributes), ...options.uris.map(utf8ToHex), @@ -500,7 +499,7 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTLocalMint", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.supplyToMint.toString())), + numberToPaddedHex(options.supplyToMint), ]; return new TransactionNextBuilder({ @@ -521,7 +520,7 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.supplyToBurn.toString())), + numberToPaddedHex(options.supplyToBurn), ]; return new TransactionNextBuilder({ @@ -543,7 +542,7 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.tokenNonce.toString())), + numberToPaddedHex(options.tokenNonce), byteArrayToHex(options.attributes), ]; @@ -566,8 +565,8 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.tokenNonce.toString())), - bigIntToHex(new BigNumber(options.quantityToAdd.toString())), + numberToPaddedHex(options.tokenNonce), + numberToPaddedHex(options.quantityToAdd), ]; return new TransactionNextBuilder({ @@ -589,8 +588,8 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), - bigIntToHex(new BigNumber(options.tokenNonce.toString())), - bigIntToHex(new BigNumber(options.quantityToBurn.toString())), + numberToPaddedHex(options.tokenNonce), + numberToPaddedHex(options.quantityToBurn), ]; return new TransactionNextBuilder({ diff --git a/src/utils.codec.spec.ts b/src/utils.codec.spec.ts index 817496ccb..0da21c14d 100644 --- a/src/utils.codec.spec.ts +++ b/src/utils.codec.spec.ts @@ -3,14 +3,17 @@ import { byteArrayToHex, isPaddedHex, numberToPaddedHex, utf8ToHex, zeroPadStrin describe("test codec utils", () => { it("should convert numberToPaddedHex", () => { + assert.equal(numberToPaddedHex(0), "00"); assert.equal(numberToPaddedHex(1), "01"); assert.equal(numberToPaddedHex(10), "0a"); assert.equal(numberToPaddedHex(256), "0100"); + assert.equal(numberToPaddedHex(0n), "00"); assert.equal(numberToPaddedHex(1n), "01"); assert.equal(numberToPaddedHex(10n), "0a"); assert.equal(numberToPaddedHex(256n), "0100"); + assert.equal(numberToPaddedHex("0"), "00"); assert.equal(numberToPaddedHex("1"), "01"); assert.equal(numberToPaddedHex("10"), "0a"); assert.equal(numberToPaddedHex("256"), "0100"); From 80a4fcefd890b05788a7302b790267f93540de02 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 14:13:03 +0200 Subject: [PATCH 109/275] fixes after review --- src/interface.ts | 7 ------- src/message.ts | 10 +++++----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index 65a0099e9..663cfcecd 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -102,10 +102,3 @@ export interface ITransactionNext { signature: Uint8Array; guardianSignature: Uint8Array; } - -export interface IMessage { - data: Uint8Array; - signature?: Uint8Array; - address?: IAddress; - version?: number; -} diff --git a/src/message.ts b/src/message.ts index 877251325..d018f26dd 100644 --- a/src/message.ts +++ b/src/message.ts @@ -1,4 +1,4 @@ -import { IAddress, IMessage } from "./interface"; +import { IAddress } from "./interface"; import { DEFAULT_MESSAGE_VERSION, MESSAGE_PREFIX } from "./constants"; import { Address } from "./address"; @@ -26,14 +26,14 @@ export class Message { this.data = options.data; this.signature = options.signature; this.address = options.address; - this.version = options.version ? options.version : DEFAULT_MESSAGE_VERSION; + this.version = options.version || DEFAULT_MESSAGE_VERSION; } } export class MessageComputer { constructor() {} - computeBytesForSigning(message: IMessage): Uint8Array { + computeBytesForSigning(message: Message): Uint8Array { const messageSize = Buffer.from(message.data.length.toString()); const signableMessage = Buffer.concat([messageSize, message.data]); let bytesToHash = Buffer.concat([Buffer.from(MESSAGE_PREFIX), signableMessage]); @@ -41,11 +41,11 @@ export class MessageComputer { return createKeccakHash("keccak256").update(bytesToHash).digest(); } - computeBytesForVerifying(message: IMessage): Uint8Array { + computeBytesForVerifying(message: Message): Uint8Array { return this.computeBytesForSigning(message); } - packMessage(message: IMessage): { + packMessage(message: Message): { message: string; signature: string; address: string; From fcc10211f0738e5d6a204e8ab9a4fe7a63547f71 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 14:24:59 +0200 Subject: [PATCH 110/275] use toFixed instead of toString --- src/transaction.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 1ca9e6903..755529b64 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -32,7 +32,7 @@ describe("test transaction construction", async () => { const transaction = Transaction.fromTransactionNext(nextTransaction); assert.deepEqual(transaction.getSender(), Address.fromBech32(plainTransactionNextObject.sender)); assert.deepEqual(transaction.getReceiver(), Address.fromBech32(plainTransactionNextObject.receiver)); - assert.equal(transaction.getGasLimit().valueOf().toString(), plainTransactionNextObject.gasLimit.toString()); + assert.equal(transaction.getGasLimit().valueOf().toFixed(0), plainTransactionNextObject.gasLimit.toString()); assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value.toString()); assert.equal(transaction.getData().toString(), plainTransactionNextObject.data.toString()); assert.equal(transaction.getChainID().valueOf(), plainTransactionNextObject.chainID); From ab0488b3c2472c81bb7cdd439a3e2da2e569b3f4 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 10:35:45 +0200 Subject: [PATCH 111/275] started to modify tests --- src/transaction.local.net.spec.ts | 65 ++++++++++++++++--- src/transactionsFactories/index.ts | 1 + .../transferTransactionsFactory.ts | 1 + 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 56fa581ec..24c5605f4 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -4,9 +4,12 @@ import { Logger } from "./logger"; import { loadTestWallets, TestWallet } from "./testutils"; import { createLocalnetProvider } from "./testutils/networkProviders"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction } from "./transaction"; +import { Transaction, TransactionComputer } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { TransactionWatcher } from "./transactionWatcher"; +import { TransactionsFactoryConfig } from "./transactionsFactories/transactionsFactoryConfig"; +import { NextTransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; +import { TokenComputer } from "./tokens"; describe("test transaction", function () { let alice: TestWallet, bob: TestWallet; @@ -20,7 +23,9 @@ describe("test transaction", function () { let provider = createLocalnetProvider(); let watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true) } + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }); let network = await provider.getNetworkConfig(); @@ -34,7 +39,7 @@ describe("test transaction", function () { receiver: bob.address, value: TokenTransfer.egldFromAmount(42), gasLimit: network.MinGasLimit, - chainID: network.ChainID + chainID: network.ChainID, }); let transactionTwo = new Transaction({ @@ -42,7 +47,7 @@ describe("test transaction", function () { receiver: bob.address, value: TokenTransfer.egldFromAmount(43), gasLimit: network.MinGasLimit, - chainID: network.ChainID + chainID: network.ChainID, }); transactionOne.setNonce(alice.account.nonce); @@ -69,7 +74,9 @@ describe("test transaction", function () { let provider = createLocalnetProvider(); let watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true) } + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }); let network = await provider.getNetworkConfig(); @@ -83,7 +90,7 @@ describe("test transaction", function () { receiver: bob.address, value: TokenTransfer.egldFromAmount(42), gasLimit: network.MinGasLimit, - chainID: network.ChainID + chainID: network.ChainID, }); transactionOne.setNonce(alice.account.nonce); @@ -110,7 +117,7 @@ describe("test transaction", function () { gasLimit: 70000, receiver: alice.address, value: TokenTransfer.egldFromAmount(1000), - chainID: network.ChainID + chainID: network.ChainID, }); let transactionTwo = new Transaction({ @@ -119,7 +126,7 @@ describe("test transaction", function () { gasLimit: 70000, receiver: alice.address, value: TokenTransfer.egldFromAmount(1000000), - chainID: network.ChainID + chainID: network.ChainID, }); transactionOne.setNonce(alice.account.nonce); @@ -132,7 +139,47 @@ describe("test transaction", function () { Logger.trace(JSON.stringify(await provider.simulateTransaction(transactionTwo), null, 4)); }); - async function signTransaction(options: { transaction: Transaction, wallet: TestWallet }) { + it("should create transaction using the NextTokenTransferFactory", async function () { + this.timeout(70000); + + let provider = createLocalnetProvider(); + let watcher = new TransactionWatcher({ + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, + }); + + let network = await provider.getNetworkConfig(); + + const config = new TransactionsFactoryConfig(network.ChainID); + const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); + + await alice.sync(provider); + await bob.sync(provider); + let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); + + let transaction = factory.createTransactionForNativeTokenTransfer({ + sender: alice.address, + receiver: bob.address, + nativeAmount: new BigNumber("42000000000000000000"), + }); + transaction.nonce = alice.account.nonce.valueOf(); + + const transactionComputer = new TransactionComputer(); + transaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + ); + + await provider.sendTransaction(transaction); + await watcher.awaitCompleted(transaction); + + await bob.sync(provider); + let newBalanceOfBob = new BigNumber(bob.account.balance.toString()); + + assert.deepEqual(TokenTransfer.egldFromAmount(42).valueOf(), newBalanceOfBob.minus(initialBalanceOfBob)); + }); + + async function signTransaction(options: { transaction: Transaction; wallet: TestWallet }) { const transaction = options.transaction; const wallet = options.wallet; diff --git a/src/transactionsFactories/index.ts b/src/transactionsFactories/index.ts index 79cd9a638..6aa272608 100644 --- a/src/transactionsFactories/index.ts +++ b/src/transactionsFactories/index.ts @@ -1,4 +1,5 @@ export * from "./delegationTransactionsFactory"; +export * from "./relayedTransactionsFactory"; export * from "./smartContractTransactionsFactory"; export * from "./tokenManagementTransactionsFactory"; export * from "./transactionsFactoryConfig"; diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index ad606c652..d48f4f861 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -22,6 +22,7 @@ interface TokenComputer { isFungible(token: Token): boolean; } +// this name is only temporary; the class will be renamed to `TransferTransactionsFactory` export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; From b3ce9ae92e69ae6ba12f0ec284398e4139feada2 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 10:39:57 +0200 Subject: [PATCH 112/275] add space around operator --- src/transaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction.ts b/src/transaction.ts index e61d0ea4f..fd6e54fd9 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -627,7 +627,7 @@ export class TransactionComputer { return feeForMove; } - const diff = transaction.gasLimit- moveBalanceGas; + const diff = transaction.gasLimit - moveBalanceGas; const modifiedGasPrice = BigInt(new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0)); const processingFee = diff * modifiedGasPrice; From 23a75ed007fc5d98f9506a6b96433a3c6ad2f4ec Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 13:51:28 +0200 Subject: [PATCH 113/275] atempt to undo formatting --- src/transaction.ts | 1250 +++++++++++++++++++++----------------------- 1 file changed, 610 insertions(+), 640 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index a9a026cf3..7b552cace 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -4,20 +4,7 @@ import { Compatibility } from "./compatibility"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; import * as errors from "./errors"; import { Hash } from "./hash"; -import { - IAddress, - IChainID, - IGasLimit, - IGasPrice, - INonce, - IPlainTransactionObject, - ISignature, - ITransactionNext, - ITransactionOptions, - ITransactionPayload, - ITransactionValue, - ITransactionVersion, -} from "./interface"; +import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; import { INetworkConfig } from "./interfaceOfNetwork"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; @@ -32,470 +19,462 @@ const TRANSACTION_HASH_LENGTH = 32; * An abstraction for creating, signing and broadcasting transactions. */ export class Transaction { - /** - * The nonce of the transaction (the account sequence number of the sender). - */ - private nonce: INonce; - - /** - * The value to transfer. - */ - private value: ITransactionValue; - - /** - * The address of the sender. - */ - private sender: IAddress; - - /** - * The address of the receiver. - */ - private readonly receiver: IAddress; - - /** - * The username of the sender. - */ - private senderUsername: string; - - /** - * The username of the receiver. - */ - private receiverUsername: string; - - /** - * The gas price to be used. - */ - private gasPrice: IGasPrice; - - /** - * The maximum amount of gas to be consumed when processing the transaction. - */ - private gasLimit: IGasLimit; - - /** - * The payload of the transaction. - */ - private readonly data: ITransactionPayload; - - /** - * The chain ID of the Network (e.g. "1" for Mainnet). - */ - private chainID: IChainID; - - /** - * The version, required by the Network in order to correctly interpret the contents of the transaction. - * @deprecated Use getVersion() and setVersion() instead. - */ - version: TransactionVersion; - - /** - * The options field, useful for describing different settings available for transactions - * @deprecated Use getOptions() and setOptions() instead. - */ - options: TransactionOptions; - - /** - * The address of the guardian. - */ - private guardian: IAddress; - - /** - * The signature. - */ - private signature: Buffer; - - /** - * The signature of the guardian. - */ - private guardianSignature: Buffer; - - /** - * The transaction hash, also used as a transaction identifier. - */ - private hash: TransactionHash; - - /** - * Creates a new Transaction object. - */ - public constructor({ - nonce, - value, - sender, - receiver, - senderUsername, - receiverUsername, - gasPrice, - gasLimit, - data, - chainID, - version, - options, - guardian, - }: { - nonce?: INonce; - value?: ITransactionValue; - sender: IAddress; - receiver: IAddress; - senderUsername?: string; - receiverUsername?: string; - gasPrice?: IGasPrice; - gasLimit: IGasLimit; - data?: ITransactionPayload; - chainID: IChainID; - version?: ITransactionVersion; - options?: ITransactionOptions; - guardian?: IAddress; - }) { - this.nonce = nonce || 0; - this.value = value ? new BigNumber(value.toString()).toFixed(0) : 0; - this.sender = sender; - this.receiver = receiver; - this.senderUsername = senderUsername || ""; - this.receiverUsername = receiverUsername || ""; - this.gasPrice = gasPrice || TRANSACTION_MIN_GAS_PRICE; - this.gasLimit = gasLimit; - this.data = data || new TransactionPayload(); - this.chainID = chainID; - this.version = version ? new TransactionVersion(version.valueOf()) : TransactionVersion.withDefaultVersion(); - this.options = options ? new TransactionOptions(options.valueOf()) : TransactionOptions.withDefaultOptions(); - this.guardian = guardian || Address.empty(); - - this.signature = Buffer.from([]); - this.guardianSignature = Buffer.from([]); - this.hash = TransactionHash.empty(); - } - - getNonce(): INonce { - return this.nonce; - } - - /** - * Sets the account sequence number of the sender. Must be done prior signing. - */ - setNonce(nonce: INonce) { - this.nonce = nonce; - } - - getValue(): ITransactionValue { - return this.value; - } - - setValue(value: ITransactionValue) { - this.value = value; - } - - getSender(): IAddress { - return this.sender; - } - - setSender(sender: IAddress) { - this.sender = sender; - } - - getReceiver(): IAddress { - return this.receiver; - } - - getSenderUsername(): string { - return this.senderUsername; - } - - setSenderUsername(senderUsername: string) { - this.senderUsername = senderUsername; - } - - getReceiverUsername(): string { - return this.receiverUsername; - } - - setReceiverUsername(receiverUsername: string) { - this.receiverUsername = receiverUsername; - } - - getGuardian(): IAddress { - return this.guardian; - } - - getGasPrice(): IGasPrice { - return this.gasPrice; - } - - setGasPrice(gasPrice: IGasPrice) { - this.gasPrice = gasPrice; - } - - getGasLimit(): IGasLimit { - return this.gasLimit; - } - - setGasLimit(gasLimit: IGasLimit) { - this.gasLimit = gasLimit; - } - - getData(): ITransactionPayload { - return this.data; - } - - getChainID(): IChainID { - return this.chainID; - } - - setChainID(chainID: IChainID) { - this.chainID = chainID; - } - - getVersion(): TransactionVersion { - return this.version; - } - - setVersion(version: ITransactionVersion) { - this.version = new TransactionVersion(version.valueOf()); - } - - getOptions(): TransactionOptions { - // Make sure that "sdk-core v12" is compatible (for a while) with (older) libraries that were previously setting the (soon to be private) "options" field directly, - // instead of using the "setOptions()" method. - const options = new TransactionOptions(this.options.valueOf()); - return options; - } - - setOptions(options: ITransactionOptions) { - this.options = new TransactionOptions(options.valueOf()); - } - - getSignature(): Buffer { - return this.signature; - } - - getGuardianSignature(): Buffer { - return this.guardianSignature; - } - - setGuardian(guardian: IAddress) { - this.guardian = guardian; - } - - getHash(): TransactionHash { - guardNotEmpty(this.hash, "hash"); - return this.hash; - } - - /** - * Serializes a transaction to a sequence of bytes, ready to be signed. - * This function is called internally by signers. - */ - serializeForSigning(): Buffer { - // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash - let plain = this.toPlainObject(); - // Make sure we never sign the transaction with another signature set up (useful when using the same method for verification) - if (plain.signature) { - delete plain.signature; - } - - if (plain.guardianSignature) { - delete plain.guardianSignature; - } - - if (!plain.guardian) { - delete plain.guardian; - } - - let serialized = JSON.stringify(plain); - - return Buffer.from(serialized); - } - - /** - * Checks the integrity of the guarded transaction - */ - isGuardedTransaction(): boolean { - const hasGuardian = this.guardian.bech32().length > 0; - const hasGuardianSignature = this.guardianSignature.length > 0; - return this.getOptions().isWithGuardian() && hasGuardian && hasGuardianSignature; - } - - /** - * Converts the transaction object into a ready-to-serialize, plain JavaScript object. - * This function is called internally within the signing procedure. - */ - toPlainObject(): IPlainTransactionObject { - const plainObject = { - nonce: this.nonce.valueOf(), - value: this.value.toString(), - receiver: this.receiver.bech32(), - sender: this.sender.bech32(), - senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined, - receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined, - gasPrice: this.gasPrice.valueOf(), - gasLimit: this.gasLimit.valueOf(), - data: this.data.length() == 0 ? undefined : this.data.encoded(), - chainID: this.chainID.valueOf(), - version: this.getVersion().valueOf(), - options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(), - guardian: this.guardian?.bech32() - ? this.guardian.bech32() == "" - ? undefined - : this.guardian.bech32() - : undefined, - signature: this.signature.toString("hex") ? this.signature.toString("hex") : undefined, - guardianSignature: this.guardianSignature.toString("hex") - ? this.guardianSignature.toString("hex") - : undefined, - }; - - Compatibility.guardAddressIsSetAndNonZero( - new Address(plainObject.sender), - "'sender' of transaction", - "pass the actual sender to the Transaction constructor", - ); - - return plainObject; - } - - /** - * Converts a plain object transaction into a Transaction Object. - * - * @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject() - */ - static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction { - const tx = new Transaction({ - nonce: Number(plainObjectTransaction.nonce), - value: new BigNumber(plainObjectTransaction.value).toFixed(0), - receiver: Address.fromString(plainObjectTransaction.receiver), - receiverUsername: plainObjectTransaction.receiverUsername - ? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString() - : undefined, - sender: Address.fromString(plainObjectTransaction.sender), - senderUsername: plainObjectTransaction.senderUsername - ? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString() - : undefined, - guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined, - gasPrice: Number(plainObjectTransaction.gasPrice), - gasLimit: Number(plainObjectTransaction.gasLimit), - data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")), - chainID: String(plainObjectTransaction.chainID), - version: new TransactionVersion(plainObjectTransaction.version), - options: - plainObjectTransaction.options != null - ? new TransactionOptions(plainObjectTransaction.options) - : undefined, - }); - - if (plainObjectTransaction.signature) { - tx.applySignature(new Signature(plainObjectTransaction.signature)); - } - - if (plainObjectTransaction.guardianSignature) { - tx.applyGuardianSignature(new Signature(plainObjectTransaction.guardianSignature)); - } - - return tx; - } - - /** - * Applies the signature on the transaction. - * - * @param signature The signature, as computed by a signer. - */ - applySignature(signature: ISignature | Uint8Array) { - this.signature = interpretSignatureAsBuffer(signature); - this.hash = TransactionHash.compute(this); - } - - /** - * Applies the guardian signature on the transaction. - * - * @param guardianSignature The signature, as computed by a signer. - */ - applyGuardianSignature(guardianSignature: ISignature | Uint8Array) { - this.guardianSignature = interpretSignatureAsBuffer(guardianSignature); - this.hash = TransactionHash.compute(this); - } - - /** - * Converts a transaction to a ready-to-broadcast object. - * Called internally by the network provider. - */ - toSendable(): any { - return this.toPlainObject(); - } - - /** - * Computes the current transaction fee based on the {@link NetworkConfig} and transaction properties - * @param networkConfig {@link NetworkConfig} - */ - computeFee(networkConfig: INetworkConfig): BigNumber { - let moveBalanceGas = - networkConfig.MinGasLimit.valueOf() + this.data.length() * networkConfig.GasPerDataByte.valueOf(); - if (moveBalanceGas > this.gasLimit.valueOf()) { - throw new errors.ErrNotEnoughGas(this.gasLimit.valueOf()); - } - - let gasPrice = new BigNumber(this.gasPrice.valueOf()); - let feeForMove = new BigNumber(moveBalanceGas).multipliedBy(gasPrice); - if (moveBalanceGas === this.gasLimit.valueOf()) { - return feeForMove; - } - - let diff = new BigNumber(this.gasLimit.valueOf() - moveBalanceGas); - let modifiedGasPrice = gasPrice.multipliedBy(new BigNumber(networkConfig.GasPriceModifier.valueOf())); - let processingFee = diff.multipliedBy(modifiedGasPrice); - - return feeForMove.plus(processingFee); - } - - /** - * Creates a new Transaction object from a TransactionNext object. - */ - static fromTransactionNext(transaction: ITransactionNext): Transaction { - const tx = new Transaction({ - sender: Address.fromBech32(transaction.sender), - receiver: Address.fromBech32(transaction.receiver), - gasLimit: Number(transaction.gasLimit), - chainID: transaction.chainID, - value: new BigNumber(transaction.value.toString()).toFixed(0), - data: new TransactionPayload(Buffer.from(transaction.data)), - nonce: Number(transaction.nonce), - gasPrice: Number(transaction.gasPrice), - receiverUsername: transaction.receiverUsername, - senderUsername: transaction.senderUsername, - options: transaction.options, - version: transaction.version, - }); - - if (transaction.guardian) { - tx.guardian = Address.fromBech32(transaction.guardian); - } - - if (transaction.signature.length) { - tx.applySignature(transaction.signature); - } - - if (transaction.guardianSignature.length) { - tx.applyGuardianSignature(transaction.guardianSignature); - } - - return tx; - } + /** + * The nonce of the transaction (the account sequence number of the sender). + */ + private nonce: INonce; + + /** + * The value to transfer. + */ + private value: ITransactionValue; + + /** + * The address of the sender. + */ + private sender: IAddress; + + /** + * The address of the receiver. + */ + private readonly receiver: IAddress; + + /** + * The username of the sender. + */ + private senderUsername: string; + + /** + * The username of the receiver. + */ + private receiverUsername: string; + + /** + * The gas price to be used. + */ + private gasPrice: IGasPrice; + + /** + * The maximum amount of gas to be consumed when processing the transaction. + */ + private gasLimit: IGasLimit; + + /** + * The payload of the transaction. + */ + private readonly data: ITransactionPayload; + + /** + * The chain ID of the Network (e.g. "1" for Mainnet). + */ + private chainID: IChainID; + + /** + * The version, required by the Network in order to correctly interpret the contents of the transaction. + * @deprecated Use getVersion() and setVersion() instead. + */ + version: TransactionVersion; + + /** + * The options field, useful for describing different settings available for transactions + * @deprecated Use getOptions() and setOptions() instead. + */ + options: TransactionOptions; + + /** + * The address of the guardian. + */ + private guardian: IAddress; + + /** + * The signature. + */ + private signature: Buffer; + + /** + * The signature of the guardian. + */ + private guardianSignature: Buffer; + + /** + * The transaction hash, also used as a transaction identifier. + */ + private hash: TransactionHash; + + /** + * Creates a new Transaction object. + */ + public constructor({ + nonce, + value, + sender, + receiver, + senderUsername, + receiverUsername, + gasPrice, + gasLimit, + data, + chainID, + version, + options, + guardian, + }: { + nonce?: INonce; + value?: ITransactionValue; + sender: IAddress; + receiver: IAddress; + senderUsername?: string; + receiverUsername?: string; + gasPrice?: IGasPrice; + gasLimit: IGasLimit; + data?: ITransactionPayload; + chainID: IChainID; + version?: ITransactionVersion; + options?: ITransactionOptions; + guardian?: IAddress; + }) { + this.nonce = nonce || 0; + this.value = value ? new BigNumber(value.toString()).toFixed(0) : 0; + this.sender = sender; + this.receiver = receiver; + this.senderUsername = senderUsername || ""; + this.receiverUsername = receiverUsername || ""; + this.gasPrice = gasPrice || TRANSACTION_MIN_GAS_PRICE; + this.gasLimit = gasLimit; + this.data = data || new TransactionPayload(); + this.chainID = chainID; + this.version = version ? new TransactionVersion(version.valueOf()) : TransactionVersion.withDefaultVersion(); + this.options = options ? new TransactionOptions(options.valueOf()) : TransactionOptions.withDefaultOptions(); + this.guardian = guardian || Address.empty(); + + this.signature = Buffer.from([]); + this.guardianSignature = Buffer.from([]); + this.hash = TransactionHash.empty(); + } + + getNonce(): INonce { + return this.nonce; + } + + /** + * Sets the account sequence number of the sender. Must be done prior signing. + */ + setNonce(nonce: INonce) { + this.nonce = nonce; + } + + getValue(): ITransactionValue { + return this.value; + } + + setValue(value: ITransactionValue) { + this.value = value; + } + + getSender(): IAddress { + return this.sender; + } + + setSender(sender: IAddress) { + this.sender = sender; + } + + getReceiver(): IAddress { + return this.receiver; + } + + getSenderUsername(): string { + return this.senderUsername; + } + + setSenderUsername(senderUsername: string) { + this.senderUsername = senderUsername; + } + + getReceiverUsername(): string { + return this.receiverUsername; + } + + setReceiverUsername(receiverUsername: string) { + this.receiverUsername = receiverUsername; + } + + getGuardian(): IAddress { + return this.guardian; + } + + getGasPrice(): IGasPrice { + return this.gasPrice; + } + + setGasPrice(gasPrice: IGasPrice) { + this.gasPrice = gasPrice; + } + + getGasLimit(): IGasLimit { + return this.gasLimit; + } + + setGasLimit(gasLimit: IGasLimit) { + this.gasLimit = gasLimit; + } + + getData(): ITransactionPayload { + return this.data; + } + + getChainID(): IChainID { + return this.chainID; + } + + setChainID(chainID: IChainID) { + this.chainID = chainID; + } + + getVersion(): TransactionVersion { + return this.version; + } + + setVersion(version: ITransactionVersion) { + this.version = new TransactionVersion(version.valueOf()); + } + + getOptions(): TransactionOptions { + // Make sure that "sdk-core v12" is compatible (for a while) with (older) libraries that were previously setting the (soon to be private) "options" field directly, + // instead of using the "setOptions()" method. + const options = new TransactionOptions(this.options.valueOf()); + return options; + } + + setOptions(options: ITransactionOptions) { + this.options = new TransactionOptions(options.valueOf()); + } + + getSignature(): Buffer { + return this.signature; + } + + getGuardianSignature(): Buffer { + return this.guardianSignature; + } + + setGuardian(guardian: IAddress) { + this.guardian = guardian; + } + + getHash(): TransactionHash { + guardNotEmpty(this.hash, "hash"); + return this.hash; + } + + /** + * Serializes a transaction to a sequence of bytes, ready to be signed. + * This function is called internally by signers. + */ + serializeForSigning(): Buffer { + // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash + let plain = this.toPlainObject(); + // Make sure we never sign the transaction with another signature set up (useful when using the same method for verification) + if (plain.signature) { + delete plain.signature; + } + + if (plain.guardianSignature) { + delete plain.guardianSignature; + } + + if (!plain.guardian) { + delete plain.guardian + } + + let serialized = JSON.stringify(plain); + + return Buffer.from(serialized); + } + + /** + * Checks the integrity of the guarded transaction + */ + isGuardedTransaction(): boolean { + const hasGuardian = this.guardian.bech32().length > 0; + const hasGuardianSignature = this.guardianSignature.length > 0; + return this.getOptions().isWithGuardian() && hasGuardian && hasGuardianSignature; + } + + /** + * Converts the transaction object into a ready-to-serialize, plain JavaScript object. + * This function is called internally within the signing procedure. + */ + toPlainObject(): IPlainTransactionObject { + const plainObject = { + nonce: this.nonce.valueOf(), + value: this.value.toString(), + receiver: this.receiver.bech32(), + sender: this.sender.bech32(), + senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined, + receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined, + gasPrice: this.gasPrice.valueOf(), + gasLimit: this.gasLimit.valueOf(), + data: this.data.length() == 0 ? undefined : this.data.encoded(), + chainID: this.chainID.valueOf(), + version: this.getVersion().valueOf(), + options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(), + guardian: this.guardian?.bech32() ? (this.guardian.bech32() == "" ? undefined : this.guardian.bech32()) : undefined, + signature: this.signature.toString("hex") ? this.signature.toString("hex") : undefined, + guardianSignature: this.guardianSignature.toString("hex") ? this.guardianSignature.toString("hex") : undefined, + }; + + Compatibility.guardAddressIsSetAndNonZero(new Address(plainObject.sender), "'sender' of transaction", "pass the actual sender to the Transaction constructor") + + return plainObject; + } + + /** + * Converts a plain object transaction into a Transaction Object. + * + * @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject() + */ + static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction { + const tx = new Transaction({ + nonce: Number(plainObjectTransaction.nonce), + value: new BigNumber(plainObjectTransaction.value).toFixed(0), + receiver: Address.fromString(plainObjectTransaction.receiver), + receiverUsername: plainObjectTransaction.receiverUsername ? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString() : undefined, + sender: Address.fromString(plainObjectTransaction.sender), + senderUsername: plainObjectTransaction.senderUsername ? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString() : undefined, + guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined, + gasPrice: Number(plainObjectTransaction.gasPrice), + gasLimit: Number(plainObjectTransaction.gasLimit), + data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")), + chainID: String(plainObjectTransaction.chainID), + version: new TransactionVersion(plainObjectTransaction.version), + options: plainObjectTransaction.options != null ? new TransactionOptions(plainObjectTransaction.options) : undefined + }); + + if (plainObjectTransaction.signature) { + tx.applySignature( + new Signature(plainObjectTransaction.signature), + ); + } + + if (plainObjectTransaction.guardianSignature) { + tx.applyGuardianSignature( + new Signature(plainObjectTransaction.guardianSignature) + ); + } + + return tx; + } + + /** + * Applies the signature on the transaction. + * + * @param signature The signature, as computed by a signer. + */ + applySignature(signature: ISignature | Uint8Array) { + this.signature = interpretSignatureAsBuffer(signature); + this.hash = TransactionHash.compute(this); + } + + /** + * Applies the guardian signature on the transaction. + * + * @param guardianSignature The signature, as computed by a signer. + */ + applyGuardianSignature(guardianSignature: ISignature | Uint8Array) { + this.guardianSignature = interpretSignatureAsBuffer(guardianSignature); + this.hash = TransactionHash.compute(this); + } + + /** + * Converts a transaction to a ready-to-broadcast object. + * Called internally by the network provider. + */ + toSendable(): any { + return this.toPlainObject(); + } + + /** + * Computes the current transaction fee based on the {@link NetworkConfig} and transaction properties + * @param networkConfig {@link NetworkConfig} + */ + computeFee(networkConfig: INetworkConfig): BigNumber { + let moveBalanceGas = + networkConfig.MinGasLimit.valueOf() + + this.data.length() * networkConfig.GasPerDataByte.valueOf(); + if (moveBalanceGas > this.gasLimit.valueOf()) { + throw new errors.ErrNotEnoughGas(this.gasLimit.valueOf()); + } + + let gasPrice = new BigNumber(this.gasPrice.valueOf()); + let feeForMove = new BigNumber(moveBalanceGas).multipliedBy(gasPrice); + if (moveBalanceGas === this.gasLimit.valueOf()) { + return feeForMove; + } + + let diff = new BigNumber(this.gasLimit.valueOf() - moveBalanceGas); + let modifiedGasPrice = gasPrice.multipliedBy( + new BigNumber(networkConfig.GasPriceModifier.valueOf()) + ); + let processingFee = diff.multipliedBy(modifiedGasPrice); + + return feeForMove.plus(processingFee); + } + + /** + * Creates a new Transaction object from a TransactionNext object. + */ + static fromTransactionNext(transaction: ITransactionNext): Transaction { + const tx = new Transaction({ + sender: Address.fromBech32(transaction.sender), + receiver: Address.fromBech32(transaction.receiver), + gasLimit: Number(transaction.gasLimit), + chainID: transaction.chainID, + value: new BigNumber(transaction.value.toString()).toFixed(0), + data: new TransactionPayload(Buffer.from(transaction.data)), + nonce: Number(transaction.nonce), + gasPrice: Number(transaction.gasPrice), + receiverUsername: transaction.receiverUsername, + senderUsername: transaction.senderUsername, + options: transaction.options, + version: transaction.version + }); + + if (transaction.guardian) { + tx.guardian = Address.fromBech32(transaction.guardian) + } + + if (transaction.signature.length) { + tx.applySignature(transaction.signature); + } + + if (transaction.guardianSignature.length) { + tx.applyGuardianSignature(transaction.guardianSignature); + } + + return tx; + } } /** * An abstraction for handling and computing transaction hashes. */ export class TransactionHash extends Hash { - constructor(hash: string) { - super(hash); - } - - /** - * Computes the hash of a transaction. - */ - static compute(transaction: Transaction): TransactionHash { - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(transaction); - let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); - return new TransactionHash(hash); - } + constructor(hash: string) { + super(hash); + } + + /** + * Computes the hash of a transaction. + */ + static compute(transaction: Transaction): TransactionHash { + let serializer = new ProtoSerializer(); + let buffer = serializer.serializeTransaction(transaction); + let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) + .update(buffer) + .digest("hex"); + return new TransactionHash(hash); + } } /** @@ -503,103 +482,103 @@ export class TransactionHash extends Hash { * Will replace the {@link Transaction} class in the future. */ export class TransactionNext { - /** - * The nonce of the transaction (the account sequence number of the sender). - */ - public nonce: bigint; - - /** - * The value to transfer. - */ - public value: bigint; - - /** - * The address of the sender. - */ - public sender: string; - - /** - * The address of the receiver. - */ - public receiver: string; - - /** - * The username of the sender. - */ - public senderUsername: string; - - /** - * The username of the receiver. - */ - public receiverUsername: string; - - /** - * The gas price to be used. - */ - public gasPrice: bigint; - - /** - * The maximum amount of gas to be consumed when processing the transaction. - */ - public gasLimit: bigint; - - /** - * The payload of the transaction. - */ - public data: Uint8Array; - - /** - * The chain ID of the Network (e.g. "1" for Mainnet). - */ - public chainID: string; - - /** - * The version, required by the Network in order to correctly interpret the contents of the transaction. - */ - public version: number; - - /** - * The options field of the transactions. - */ - public options: number; - - /** - * The address of the guardian. - */ - public guardian: string; - - /** - * The signature. - */ - public signature: Uint8Array; - - /** - * The signature of the guardian. - */ - public guardianSignature: Uint8Array; - - /** - * Creates a new Transaction object. - */ + /** + * The nonce of the transaction (the account sequence number of the sender). + */ + public nonce: bigint; + + /** + * The value to transfer. + */ + public value: bigint; + + /** + * The address of the sender. + */ + public sender: string; + + /** + * The address of the receiver. + */ + public receiver: string; + + /** + * The username of the sender. + */ + public senderUsername: string; + + /** + * The username of the receiver. + */ + public receiverUsername: string; + + /** + * The gas price to be used. + */ + public gasPrice: bigint; + + /** + * The maximum amount of gas to be consumed when processing the transaction. + */ + public gasLimit: bigint; + + /** + * The payload of the transaction. + */ + public data: Uint8Array; + + /** + * The chain ID of the Network (e.g. "1" for Mainnet). + */ + public chainID: string; + + /** + * The version, required by the Network in order to correctly interpret the contents of the transaction. + */ + public version: number; + + /** + * The options field of the transactions. + */ + public options: number; + + /** + * The address of the guardian. + */ + public guardian: string; + + /** + * The signature. + */ + public signature: Uint8Array; + + /** + * The signature of the guardian. + */ + public guardianSignature: Uint8Array; + + /** + * Creates a new Transaction object. + */ public constructor(init: Partial) { - this.nonce = 0n; - this.value = 0n; - this.sender = ""; - this.receiver = ""; - this.senderUsername = ""; - this.receiverUsername = ""; - this.gasPrice = BigInt(TRANSACTION_MIN_GAS_PRICE); - this.gasLimit = 0n; - this.data = new Uint8Array(); - this.chainID = ""; - this.version = TRANSACTION_VERSION_DEFAULT; - this.options = TRANSACTION_OPTIONS_DEFAULT; - this.guardian = ""; - - this.signature = new Uint8Array(); - this.guardianSignature = new Uint8Array(); - - Object.assign(this, init); + this.nonce = 0n; + this.value = 0n; + this.sender = ""; + this.receiver = ""; + this.senderUsername = ""; + this.receiverUsername = ""; + this.gasPrice = BigInt(TRANSACTION_MIN_GAS_PRICE); + this.gasLimit = 0n; + this.data = new Uint8Array(); + this.chainID = ""; + this.version = TRANSACTION_VERSION_DEFAULT; + this.options = TRANSACTION_OPTIONS_DEFAULT; + this.guardian = ""; + + this.signature = new Uint8Array(); + this.guardianSignature = new Uint8Array(); + + Object.assign(this, init); } } @@ -607,89 +586,80 @@ export class TransactionNext { * An utilitary class meant to work together with the {@link TransactionNext} class. */ export class TransactionComputer { - constructor() {} - - computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): bigint { - const moveBalanceGas = BigInt( - networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, - ); - if (moveBalanceGas > transaction.gasLimit) { - throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); - } - - const gasPrice = transaction.gasPrice; - const feeForMove = moveBalanceGas * gasPrice; - if (moveBalanceGas === transaction.gasLimit) { - return feeForMove; - } - - const diff = transaction.gasLimit - moveBalanceGas; - const modifiedGasPrice = BigInt( - new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), - ); - const processingFee = diff * modifiedGasPrice; - - return feeForMove + processingFee; + constructor() { } + + computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): bigint { + const moveBalanceGas = BigInt( + networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, + ); + if (moveBalanceGas > transaction.gasLimit) { + throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); } - computeBytesForSigning(transaction: ITransactionNext): Uint8Array { - const plainTransaction = this.toPlainObject(transaction); + const gasPrice = transaction.gasPrice; + const feeForMove = moveBalanceGas * gasPrice; + if (moveBalanceGas === transaction.gasLimit) { + return feeForMove; + } - if (plainTransaction.signature) { - delete plainTransaction.signature; - } + const diff = transaction.gasLimit - moveBalanceGas; + const modifiedGasPrice = BigInt( + new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), + ); + const processingFee = diff * modifiedGasPrice; + + return feeForMove + processingFee; +} - if (plainTransaction.guardianSignature) { - delete plainTransaction.guardianSignature; - } + computeBytesForSigning(transaction: ITransactionNext): Uint8Array { + const plainTransaction = this.toPlainObject(transaction); - if (!plainTransaction.guardian) { - delete plainTransaction.guardian; - } + if (plainTransaction.signature) { + delete plainTransaction.signature; + } - const serialized = JSON.stringify(plainTransaction); + if (plainTransaction.guardianSignature) { + delete plainTransaction.guardianSignature; + } - return Buffer.from(serialized); + if (!plainTransaction.guardian) { + delete plainTransaction.guardian } - computeTransactionHash(transaction: ITransactionNext): Uint8Array { - let serializer = new ProtoSerializer(); + const serialized = JSON.stringify(plainTransaction); - const tx = Transaction.fromTransactionNext(transaction); - const buffer = serializer.serializeTransaction(tx); - const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); + return new Uint8Array(Buffer.from(serialized)); + } - return Buffer.from(hash, "hex"); - } + computeTransactionHash(transaction: ITransactionNext): Uint8Array { + let serializer = new ProtoSerializer(); + + const tx = Transaction.fromTransactionNext(transaction); + const buffer = serializer.serializeTransaction(tx); + const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) + .update(buffer) + .digest("hex"); + + return Buffer.from(hash, "hex"); + } - private toPlainObject(transaction: ITransactionNext) { - return { - nonce: Number(transaction.nonce), - value: transaction.value.toString(), - receiver: transaction.receiver, - sender: transaction.sender, - senderUsername: transaction.senderUsername - ? Buffer.from(transaction.senderUsername).toString("base64") - : undefined, - receiverUsername: transaction.receiverUsername - ? Buffer.from(transaction.receiverUsername).toString("base64") - : undefined, - gasPrice: Number(transaction.gasPrice), - gasLimit: Number(transaction.gasLimit), - data: - transaction.data && transaction.data.length === 0 - ? undefined - : Buffer.from(transaction.data).toString("base64"), - chainID: transaction.chainID, - version: transaction.version, - options: transaction.options ? transaction.options : undefined, - guardian: transaction.guardian ? transaction.guardian : undefined, - signature: - transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), - guardianSignature: - transaction.guardianSignature.length == 0 - ? undefined - : Buffer.from(transaction.guardianSignature).toString("hex"), - }; + private toPlainObject(transaction: ITransactionNext) { + return { + nonce: Number(transaction.nonce), + value: transaction.value.toString(), + receiver: transaction.receiver, + sender: transaction.sender, + senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, + receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), + data: transaction.data && transaction.data.length === 0 ? undefined : Buffer.from(transaction.data).toString("base64"), + chainID: transaction.chainID, + version: transaction.version, + options: transaction.options ? transaction.options : undefined, + guardian: transaction.guardian ? transaction.guardian : undefined, + signature: transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), + guardianSignature: transaction.guardianSignature.length == 0 ? undefined : Buffer.from(transaction.guardianSignature).toString("hex") } + } } From 15bf006373e996c684fac3a04136d05b3c3d3ee7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 13:55:23 +0200 Subject: [PATCH 114/275] fix indentation --- src/transaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction.ts b/src/transaction.ts index 7b552cace..393037300 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -609,7 +609,7 @@ export class TransactionComputer { const processingFee = diff * modifiedGasPrice; return feeForMove + processingFee; -} + } computeBytesForSigning(transaction: ITransactionNext): Uint8Array { const plainTransaction = this.toPlainObject(transaction); From 1becc4e7c47019a27e0dcb7284f36d8eee7ea7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 20 Feb 2024 14:32:14 +0200 Subject: [PATCH 115/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5430da97c..9b5181479 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.1", + "version": "13.0.0-beta.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.1", + "version": "13.0.0-beta.2", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 83fcc1c63..2d8b6e729 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.1", + "version": "13.0.0-beta.2", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 99109463c75a5f3c179fdfacf639fa3ea107a119 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 16:33:50 +0200 Subject: [PATCH 116/275] refactor transaction watcher & unit tests fixes --- package-lock.json | 42 +++-------- package.json | 2 +- .../smartContract.local.net.spec.ts | 72 ++++++++++++++++--- src/smartcontracts/smartContract.spec.ts | 8 +-- .../smartContractResults.local.net.spec.ts | 4 +- src/testutils/contractController.ts | 4 +- src/testutils/networkProviders.ts | 4 +- .../tokenOperationsFactory.test.net.spec.ts | 2 +- src/transaction.local.net.spec.ts | 14 ++-- src/transactionWatcher.spec.ts | 2 +- src/transactionWatcher.ts | 29 ++++---- .../delegationTransactionsFactory.spec.ts | 1 + .../transactionNextBuilder.ts | 2 +- 13 files changed, 105 insertions(+), 81 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5430da97c..187949585 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "protobufjs": "7.2.4" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.2.0", + "@multiversx/sdk-network-providers": "2.3.0", "@multiversx/sdk-wallet": "4.2.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", @@ -570,29 +570,18 @@ } }, "node_modules/@multiversx/sdk-network-providers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.2.0.tgz", - "integrity": "sha512-2n/+7Ap6S9rJGTiX38GCZ2TmY9zQ1U7o1DwnWpHNRJRxArSN/xzLrbcSKy8InMyc+4A+VHf5pV0Pk8NdPV6++w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.3.0.tgz", + "integrity": "sha512-dY7HI3rMgHHulxY9XR/O6/tCWji6ZvkuetW0NmLUjFnfOtkIdnhUzQ0u5wZaMN0SeuJIWf1QPZEsiGN82ilfTQ==", "dev": true, "dependencies": { - "axios": "1.6.1", + "axios": "1.6.5", "bech32": "1.1.4", "bignumber.js": "9.0.1", "buffer": "6.0.3", "json-bigint": "1.0.0" } }, - "node_modules/@multiversx/sdk-network-providers/node_modules/axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/@multiversx/sdk-transaction-decoder": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@multiversx/sdk-transaction-decoder/-/sdk-transaction-decoder-1.0.2.tgz", @@ -6059,29 +6048,16 @@ "dev": true }, "@multiversx/sdk-network-providers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.2.0.tgz", - "integrity": "sha512-2n/+7Ap6S9rJGTiX38GCZ2TmY9zQ1U7o1DwnWpHNRJRxArSN/xzLrbcSKy8InMyc+4A+VHf5pV0Pk8NdPV6++w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.3.0.tgz", + "integrity": "sha512-dY7HI3rMgHHulxY9XR/O6/tCWji6ZvkuetW0NmLUjFnfOtkIdnhUzQ0u5wZaMN0SeuJIWf1QPZEsiGN82ilfTQ==", "dev": true, "requires": { - "axios": "1.6.1", + "axios": "1.6.5", "bech32": "1.1.4", "bignumber.js": "9.0.1", "buffer": "6.0.3", "json-bigint": "1.0.0" - }, - "dependencies": { - "axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - } } }, "@multiversx/sdk-transaction-decoder": { diff --git a/package.json b/package.json index 83fcc1c63..436bef898 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "protobufjs": "7.2.4" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.2.0", + "@multiversx/sdk-network-providers": "2.3.0", "@multiversx/sdk-wallet": "4.2.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index 0635c076f..e6f9d9852 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -10,6 +10,11 @@ import { ResultsParser } from "./resultsParser"; import { SmartContract } from "./smartContract"; import { AddressValue, BigUIntValue, OptionalValue, OptionValue, TokenIdentifierValue, U32Value } from "./typesystem"; import { BytesValue } from "./typesystem/bytes"; +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; +import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TokenComputer } from "../tokens"; +import { promises } from "fs"; +import { TransactionComputer } from "../transaction"; describe("test on local testnet", function () { let alice: TestWallet, bob: TestWallet, carol: TestWallet; @@ -85,12 +90,12 @@ describe("test on local testnet", function () { await provider.sendTransaction(transactionDeploy); await provider.sendTransaction(transactionIncrement); - await watcher.awaitCompleted(transactionDeploy); + await watcher.awaitCompleted(transactionDeploy.getHash().hex()); let transactionOnNetwork = await provider.getTransaction(transactionDeploy.getHash().hex()); let bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); assert.isTrue(bundle.returnCode.isSuccess()); - await watcher.awaitCompleted(transactionIncrement); + await watcher.awaitCompleted(transactionIncrement.getHash().hex()); transactionOnNetwork = await provider.getTransaction(transactionIncrement.getHash().hex()); bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); assert.isTrue(bundle.returnCode.isSuccess()); @@ -150,9 +155,9 @@ describe("test on local testnet", function () { await provider.sendTransaction(transactionIncrementFirst); await provider.sendTransaction(transactionIncrementSecond); - await watcher.awaitCompleted(transactionDeploy); - await watcher.awaitCompleted(transactionIncrementFirst); - await watcher.awaitCompleted(transactionIncrementSecond); + await watcher.awaitCompleted(transactionDeploy.getHash().hex()); + await watcher.awaitCompleted(transactionIncrementFirst.getHash().hex()); + await watcher.awaitCompleted(transactionIncrementSecond.getHash().hex()); // Check counter let query = contract.createQuery({ func: new ContractFunction("get") }); @@ -212,9 +217,9 @@ describe("test on local testnet", function () { await provider.sendTransaction(transactionMintBob); await provider.sendTransaction(transactionMintCarol); - await watcher.awaitCompleted(transactionDeploy); - await watcher.awaitCompleted(transactionMintBob); - await watcher.awaitCompleted(transactionMintCarol); + await watcher.awaitCompleted(transactionDeploy.getHash().hex()); + await watcher.awaitCompleted(transactionMintBob.getHash().hex()); + await watcher.awaitCompleted(transactionMintCarol.getHash().hex()); // Query state, do some assertions let query = contract.createQuery({ func: new ContractFunction("totalSupply") }); @@ -294,8 +299,8 @@ describe("test on local testnet", function () { await provider.sendTransaction(transactionDeploy); await provider.sendTransaction(transactionStart); - await watcher.awaitAllEvents(transactionDeploy, ["SCDeploy"]); - await watcher.awaitAnyEvent(transactionStart, ["completedTxEvent"]); + await watcher.awaitAllEvents(transactionDeploy.getHash().hex(), ["SCDeploy"]); + await watcher.awaitAnyEvent(transactionStart.getHash().hex(), ["completedTxEvent"]); // Let's check the SCRs let transactionOnNetwork = await provider.getTransaction(transactionDeploy.getHash().hex()); @@ -325,4 +330,51 @@ describe("test on local testnet", function () { queryResponse = await provider.queryContract(query); assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0); }); + + it("counter: should deploy and call using the SmartContractFactory", async function () { + this.timeout(80000); + + TransactionWatcher.DefaultPollingInterval = 5000; + TransactionWatcher.DefaultTimeout = 50000; + + const network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const transactionComputer = new TransactionComputer(); + const config = new TransactionsFactoryConfig(network.ChainID); + const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + + let bytecode = await promises.readFile("src/testdata/counter.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const deployTxHash = await provider.sendTransaction(deployTransaction); + await watcher.awaitCompleted(deployTxHash); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + + alice.account.incrementNonce(); + + const smartContractCallTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 2000000n, + }); + smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + smartContractCallTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(smartContractCallTransaction)), + ); + + const scCallTxHash = await provider.sendTransaction(smartContractCallTransaction); + await watcher.awaitCompleted(scCallTxHash); + }); }); diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 0cb481044..23ad37018 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -64,7 +64,7 @@ describe("test contract", () => { await Promise.all([ provider.mockTransactionTimeline(deployTransaction, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), - watcher.awaitCompleted(deployTransaction) + watcher.awaitCompleted(deployTransaction.getHash().hex()) ]); assert.isTrue((await provider.getTransactionStatus(hash)).isExecuted()); @@ -118,8 +118,8 @@ describe("test contract", () => { await Promise.all([ provider.mockTransactionTimeline(callTransactionOne, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), provider.mockTransactionTimeline(callTransactionTwo, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), - watcher.awaitCompleted(callTransactionOne), - watcher.awaitCompleted(callTransactionTwo) + watcher.awaitCompleted(callTransactionOne.getHash().hex()), + watcher.awaitCompleted(callTransactionTwo.getHash().hex()) ]); assert.isTrue((await provider.getTransactionStatus(hashOne)).isExecuted()); @@ -159,7 +159,7 @@ describe("test contract", () => { await Promise.all([ provider.mockTransactionTimeline(deployTransaction, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), - watcher.awaitCompleted(deployTransaction) + watcher.awaitCompleted(deployTransaction.getHash().hex()) ]); assert.isTrue((await provider.getTransactionStatus(hash)).isExecuted()); diff --git a/src/smartcontracts/smartContractResults.local.net.spec.ts b/src/smartcontracts/smartContractResults.local.net.spec.ts index 6f0ef8802..885cb12f5 100644 --- a/src/smartcontracts/smartContractResults.local.net.spec.ts +++ b/src/smartcontracts/smartContractResults.local.net.spec.ts @@ -58,8 +58,8 @@ describe("fetch transactions from local testnet", function () { await provider.sendTransaction(transactionDeploy); await provider.sendTransaction(transactionIncrement); - await watcher.awaitCompleted(transactionDeploy); - await watcher.awaitCompleted(transactionIncrement); + await watcher.awaitCompleted(transactionDeploy.getHash().hex()); + await watcher.awaitCompleted(transactionIncrement.getHash().hex()); let transactionOnNetworkDeploy = await provider.getTransaction(transactionDeploy.getHash().hex()); let transactionOnNetworkIncrement = await provider.getTransaction(transactionIncrement.getHash().hex()); diff --git a/src/testutils/contractController.ts b/src/testutils/contractController.ts index 3fed66f79..1d1b7ca19 100644 --- a/src/testutils/contractController.ts +++ b/src/testutils/contractController.ts @@ -24,7 +24,7 @@ export class ContractController { Logger.info(`ContractController.deploy [begin]: transaction = ${transaction.getHash()}`); await this.provider.sendTransaction(transaction); - let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction); + let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex()); let bundle = this.parser.parseUntypedOutcome(transactionOnNetwork); Logger.info(`ContractController.deploy [end]: transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`); @@ -37,7 +37,7 @@ export class ContractController { interaction.check(); await this.provider.sendTransaction(transaction); - let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction); + let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex()); let bundle = this.parser.parseOutcome(transactionOnNetwork, interaction.getEndpoint()); Logger.info(`ContractController.execute [end]: function = ${interaction.getFunction()}, transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`); diff --git a/src/testutils/networkProviders.ts b/src/testutils/networkProviders.ts index 736a9bedb..48071d3f3 100644 --- a/src/testutils/networkProviders.ts +++ b/src/testutils/networkProviders.ts @@ -8,7 +8,7 @@ import { ITransactionStatus, } from "../interfaceOfNetwork"; import { Query } from "../smartcontracts/query"; -import { Transaction } from "../transaction"; +import { Transaction, TransactionNext } from "../transaction"; export function createLocalnetProvider(): INetworkProvider { return new ProxyNetworkProvider("http://localhost:7950", { timeout: 5000 }); @@ -23,7 +23,7 @@ export interface INetworkProvider { getAccount(address: IAddress): Promise; getTransaction(txHash: string, withProcessStatus?: boolean): Promise; getTransactionStatus(txHash: string): Promise; - sendTransaction(tx: Transaction): Promise; + sendTransaction(tx: Transaction | TransactionNext): Promise; simulateTransaction(tx: Transaction): Promise; queryContract(query: Query): Promise; } diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts index b93095b8a..05a4dfc03 100644 --- a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts +++ b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts @@ -682,7 +682,7 @@ describe("test factory on testnet", function () { await provider.sendTransaction(transaction); console.log(`Sent transaction [${tag}]: ${transaction.getHash().hex()}`); - const transactionOnNetwork = await watcher.awaitCompleted(transaction); + const transactionOnNetwork = await watcher.awaitCompleted(transaction.getHash().hex()); return transactionOnNetwork; } }); diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 24c5605f4..6b65009cf 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -60,8 +60,8 @@ describe("test transaction", function () { await provider.sendTransaction(transactionOne); await provider.sendTransaction(transactionTwo); - await watcher.awaitCompleted(transactionOne); - await watcher.awaitCompleted(transactionTwo); + await watcher.awaitCompleted(transactionOne.getHash().hex()); + await watcher.awaitCompleted(transactionTwo.getHash().hex()); await bob.sync(provider); let newBalanceOfBob = new BigNumber(bob.account.balance.toString()); @@ -96,7 +96,7 @@ describe("test transaction", function () { transactionOne.setNonce(alice.account.nonce); await signTransaction({ transaction: transactionOne, wallet: alice }); await provider.sendTransaction(transactionOne); - await watcher.awaitCompleted(transactionOne); + await watcher.awaitCompleted(transactionOne.getHash().hex()); await bob.sync(provider); let newBalanceOfBob = new BigNumber(bob.account.balance.toString()); @@ -161,17 +161,17 @@ describe("test transaction", function () { let transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice.address, receiver: bob.address, - nativeAmount: new BigNumber("42000000000000000000"), + nativeAmount: 42000000000000000000n, }); - transaction.nonce = alice.account.nonce.valueOf(); + transaction.nonce = BigInt(alice.account.nonce.valueOf()); const transactionComputer = new TransactionComputer(); transaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(transaction)), ); - await provider.sendTransaction(transaction); - await watcher.awaitCompleted(transaction); + const txHash = await provider.sendTransaction(transaction); + await watcher.awaitCompleted(txHash); await bob.sync(provider); let newBalanceOfBob = new BigNumber(bob.account.balance.toString()); diff --git a/src/transactionWatcher.spec.ts b/src/transactionWatcher.spec.ts index 92646cc47..058df41e9 100644 --- a/src/transactionWatcher.spec.ts +++ b/src/transactionWatcher.spec.ts @@ -23,7 +23,7 @@ describe("test transactionWatcher", () => { await Promise.all([ provider.mockTransactionTimelineByHash(hash, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), - watcher.awaitCompleted(dummyTransaction) + watcher.awaitCompleted(dummyTransaction.getHash().hex()) ]); assert.isTrue((await provider.getTransactionStatus(hash.hex())).isExecuted()); diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index b2fa2ec21..bd518d4e1 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -6,13 +6,6 @@ import { Logger } from "./logger"; export type PredicateIsAwaitedStatus = (status: ITransactionStatus) => boolean; -/** - * Internal interface: a transaction, as seen from the perspective of a {@link TransactionWatcher}. - */ -interface ITransaction { - getHash(): { hex(): string; } -} - /** * TransactionWatcher allows one to continuously watch (monitor), by means of polling, the status of a given transaction. */ @@ -52,10 +45,11 @@ export class TransactionWatcher { /** * Waits until the transaction reaches the "pending" status. + * @param txHash The hex-encoded transaction hash */ - public async awaitPending(transaction: ITransaction): Promise { + public async awaitPending(txHash: string): Promise { const isPending = (transaction: ITransactionOnNetwork) => transaction.status.isPending(); - const doFetch = async () => await this.fetcher.getTransaction(transaction.getHash().hex()); + const doFetch = async () => await this.fetcher.getTransaction(txHash); const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); return this.awaitConditionally( @@ -67,8 +61,9 @@ export class TransactionWatcher { /** * Waits until the transaction is completely processed. + * @param txHash The hex-encoded transaction hash */ - public async awaitCompleted(transaction: ITransaction): Promise { + public async awaitCompleted(txHash: string): Promise { const isCompleted = (transactionOnNetwork: ITransactionOnNetwork) => { if (transactionOnNetwork.isCompleted === undefined) { throw new ErrIsCompletedFieldIsMissingOnTransaction(); @@ -76,7 +71,7 @@ export class TransactionWatcher { return transactionOnNetwork.isCompleted }; - const doFetch = async () => await this.fetcher.getTransaction(transaction.getHash().hex()); + const doFetch = async () => await this.fetcher.getTransaction(txHash); const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); return this.awaitConditionally( @@ -86,14 +81,14 @@ export class TransactionWatcher { ); } - public async awaitAllEvents(transaction: ITransaction, events: string[]): Promise { + public async awaitAllEvents(txHash: string, events: string[]): Promise { const foundAllEvents = (transactionOnNetwork: ITransactionOnNetwork) => { const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map(event => event.identifier); const allAreFound = events.every(event => allEventIdentifiers.includes(event)); return allAreFound; }; - const doFetch = async () => await this.fetcher.getTransaction(transaction.getHash().hex()); + const doFetch = async () => await this.fetcher.getTransaction(txHash); const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); return this.awaitConditionally( @@ -103,14 +98,14 @@ export class TransactionWatcher { ); } - public async awaitAnyEvent(transaction: ITransaction, events: string[]): Promise { + public async awaitAnyEvent(txHash: string, events: string[]): Promise { const foundAnyEvent = (transactionOnNetwork: ITransactionOnNetwork) => { const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map(event => event.identifier); const anyIsFound = events.find(event => allEventIdentifiers.includes(event)) != undefined; return anyIsFound; }; - const doFetch = async () => await this.fetcher.getTransaction(transaction.getHash().hex()); + const doFetch = async () => await this.fetcher.getTransaction(txHash); const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); return this.awaitConditionally( @@ -120,8 +115,8 @@ export class TransactionWatcher { ); } - public async awaitOnCondition(transaction: ITransaction, condition: (data: ITransactionOnNetwork) => boolean): Promise { - const doFetch = async () => await this.fetcher.getTransaction(transaction.getHash().hex()); + public async awaitOnCondition(txHash: string, condition: (data: ITransactionOnNetwork) => boolean): Promise { + const doFetch = async () => await this.fetcher.getTransaction(txHash); const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); return this.awaitConditionally( diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 465f48071..f84d88d52 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -28,6 +28,7 @@ describe("test delegation transactions factory", function () { assert.deepEqual(transaction.data, Buffer.from("createNewDelegationContract@010f0cf064dd59200000@0a")); assert.equal(transaction.gasLimit, 60126500n); assert.equal(transaction.value, value); + assert.equal(transaction.chainID, config.chainID); }); it("should create 'TransactionNext' for adding nodes", async function () { diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionNextBuilder.ts index e1c8b0496..ec37ec884 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionNextBuilder.ts @@ -61,7 +61,7 @@ export class TransactionNextBuilder { gasLimit: gasLimit, value: this.amount || 0n, data: data.valueOf(), - chainID: this.config.toString(), + chainID: this.config.chainID, }); } } From 1206019a5d85acb7c7d0071aa7b4f1812da90e26 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 17:03:31 +0200 Subject: [PATCH 117/275] export token management transactions parser --- src/transactionsOutcomeParsers/index.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/transactionsOutcomeParsers/index.ts diff --git a/src/transactionsOutcomeParsers/index.ts b/src/transactionsOutcomeParsers/index.ts new file mode 100644 index 000000000..55d945b5b --- /dev/null +++ b/src/transactionsOutcomeParsers/index.ts @@ -0,0 +1,2 @@ +export * from "./resources"; +export * from "./tokenManagementTransactionsOutcomeParser"; From a5240ac0aeb0aaaa6158861fdc5b78fa6ee57f53 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 21 Feb 2024 10:23:39 +0200 Subject: [PATCH 118/275] fixes after review --- src/transaction.local.net.spec.ts | 12 ++++++------ .../transferTransactionsFactory.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 6b65009cf..fcab10cae 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -142,23 +142,23 @@ describe("test transaction", function () { it("should create transaction using the NextTokenTransferFactory", async function () { this.timeout(70000); - let provider = createLocalnetProvider(); - let watcher = new TransactionWatcher({ + const provider = createLocalnetProvider(); + const watcher = new TransactionWatcher({ getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true); }, }); - let network = await provider.getNetworkConfig(); + const network = await provider.getNetworkConfig(); const config = new TransactionsFactoryConfig(network.ChainID); const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); await alice.sync(provider); await bob.sync(provider); - let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); + const initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); - let transaction = factory.createTransactionForNativeTokenTransfer({ + const transaction = factory.createTransactionForNativeTokenTransfer({ sender: alice.address, receiver: bob.address, nativeAmount: 42000000000000000000n, @@ -174,7 +174,7 @@ describe("test transaction", function () { await watcher.awaitCompleted(txHash); await bob.sync(provider); - let newBalanceOfBob = new BigNumber(bob.account.balance.toString()); + const newBalanceOfBob = new BigNumber(bob.account.balance.toString()); assert.deepEqual(TokenTransfer.egldFromAmount(42).valueOf(), newBalanceOfBob.minus(initialBalanceOfBob)); }); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 5ea9b1fcc..226e238ed 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -23,8 +23,8 @@ interface TokenComputer { /** * Use this class to create transactions for native token transfers (EGLD) or custom tokens transfers (ESDT/NTF/MetaESDT). + * This name is only temporary, the class will be renamed to `TransferTransactionsFactory`. */ -// this name is only temporary; the class will be renamed to `TransferTransactionsFactory` export class NextTransferTransactionsFactory { private readonly config: IConfig; private readonly dataArgsBuilder: TokenTransfersDataBuilder; From f3862edf0c94d2eec760563df129506bea3d606a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 21 Feb 2024 11:00:30 +0200 Subject: [PATCH 119/275] change constructor parameter for the transactions factory config --- package-lock.json | 4 ++-- package.json | 2 +- src/smartcontracts/smartContract.local.net.spec.ts | 2 +- src/smartcontracts/smartContract.ts | 6 +++--- src/transaction.local.net.spec.ts | 2 +- .../delegationTransactionsFactory.spec.ts | 2 +- .../relayedTransactionsFactory.spec.ts | 2 +- .../smartContractTransactionsFactory.spec.ts | 2 +- .../tokenManagementTransactionIntentsFactory.spec.ts | 2 +- src/transactionsFactories/transactionsFactoryConfig.ts | 4 ++-- .../transferTransactionsFactory.spec.ts | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index c8762c2e5..56354a1d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.2", + "version": "13.0.0-beta.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.2", + "version": "13.0.0-beta.3", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 7feaad129..039fbbfd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.2", + "version": "13.0.0-beta.3", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index e6f9d9852..e0a637474 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -341,7 +341,7 @@ describe("test on local testnet", function () { await alice.sync(provider); const transactionComputer = new TransactionComputer(); - const config = new TransactionsFactoryConfig(network.ChainID); + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); let bytecode = await promises.readFile("src/testdata/counter.wasm"); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index b2330b366..1fb72987e 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -117,7 +117,7 @@ export class SmartContract implements ISmartContract { deploy({ deployer, code, codeMetadata, initArguments, value, gasLimit, gasPrice, chainID }: DeployArguments): Transaction { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); - const config = new TransactionsFactoryConfig(chainID.valueOf()); + const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, @@ -177,7 +177,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); - const config = new TransactionsFactoryConfig(chainID.valueOf()); + const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, @@ -215,7 +215,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); - const config = new TransactionsFactoryConfig(chainID.valueOf()); + const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); const scNextTransactionFactory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index fcab10cae..c00bbaa13 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -151,7 +151,7 @@ describe("test transaction", function () { const network = await provider.getNetworkConfig(); - const config = new TransactionsFactoryConfig(network.ChainID); + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); await alice.sync(provider); diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index f84d88d52..d65c36777 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -6,7 +6,7 @@ import { ValidatorPublicKey } from "@multiversx/sdk-wallet"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { - const config = new TransactionsFactoryConfig("D"); + const config = new TransactionsFactoryConfig({ chainID: "D" }); const delegationFactory = new DelegationTransactionsFactory(config); it("should create 'TransactionNext' for new delegation contract", async function () { diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 24aa83e48..c32d8a20b 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -5,7 +5,7 @@ import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test relayed v1 transaction builder", function () { - const config = new TransactionsFactoryConfig("T"); + const config = new TransactionsFactoryConfig({ chainID: "T" }); const factory = new RelayedTransactionsFactory(config); const transactionComputer = new TransactionComputer(); let alice: TestWallet, bob: TestWallet, carol: TestWallet, grace: TestWallet, frank: TestWallet; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index eabe4664f..8e5870b91 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -11,7 +11,7 @@ import { SmartContractTransactionsFactory } from "./smartContractTransactionsFac import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test smart contract transactions factory", function () { - const config = new TransactionsFactoryConfig("D"); + const config = new TransactionsFactoryConfig({ chainID: "D" }); let smartContractFactory: SmartContractTransactionsFactory; let abiAwareFactory: SmartContractTransactionsFactory; let adderByteCode: Code; diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index c6ad61695..0cb816422 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -11,7 +11,7 @@ describe("test token management transactions factory", () => { before(async function () { ({ frank, grace } = await loadTestWallets()); - config = new TransactionsFactoryConfig("T"); + config = new TransactionsFactoryConfig({ chainID: "T" }); tokenManagementFactory = new TokenManagementTransactionsFactory(config); }); diff --git a/src/transactionsFactories/transactionsFactoryConfig.ts b/src/transactionsFactories/transactionsFactoryConfig.ts index 1115fff9f..4de6201c3 100644 --- a/src/transactionsFactories/transactionsFactoryConfig.ts +++ b/src/transactionsFactories/transactionsFactoryConfig.ts @@ -30,9 +30,9 @@ export class TransactionsFactoryConfig { gasLimitESDTNFTTransfer: bigint; gasLimitMultiESDTNFTTransfer: bigint; - constructor(chainId: string) { + constructor(options: { chainID: string }) { // General-purpose configuration - this.chainID = chainId; + this.chainID = options.chainID; this.addressHrp = DEFAULT_HRP; this.minGasLimit = 50000n; this.gasLimitPerByte = 1500n; diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index fcf09b097..3cc865dbc 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -6,7 +6,7 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; describe("test transfer transcations factory", function () { - const config = new TransactionsFactoryConfig("D"); + const config = new TransactionsFactoryConfig({ chainID: "D" }); const nextTransferFactory = new NextTransferTransactionsFactory(config, new TokenComputer()); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); From 67ffcaf413823ae225ad21ac2652aa3bf90c996c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 23 Feb 2024 17:08:31 +0200 Subject: [PATCH 120/275] duplicate localnet tests to use the transaction factories --- .../interaction.local.net.spec.ts | 435 ++++++++++++++++-- .../smartContract.local.net.spec.ts | 385 ++++++++++++++-- .../smartContractResults.local.net.spec.ts | 72 ++- src/testutils/contractController.ts | 30 +- src/testutils/networkProviders.ts | 2 +- 5 files changed, 826 insertions(+), 98 deletions(-) diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 57db4e3c5..69133d356 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -3,11 +3,14 @@ import { assert } from "chai"; import { loadAbiRegistry, loadTestWallets, prepareDeployment, TestWallet } from "../testutils"; import { ContractController } from "../testutils/contractController"; import { createLocalnetProvider } from "../testutils/networkProviders"; -import { Transaction } from "../transaction"; +import { Transaction, TransactionComputer } from "../transaction"; import { Interaction } from "./interaction"; import { ReturnCode } from "./returnCode"; import { SmartContract } from "./smartContract"; - +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; +import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TokenComputer } from "../tokens"; +import { promises } from "fs"; describe("test smart contract interactor", function () { let provider = createLocalnetProvider(); @@ -34,16 +37,21 @@ describe("test smart contract interactor", function () { codePath: "src/testdata/answer.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); - let { bundle: { returnCode } } = await controller.deploy(deployTransaction); + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); assert.isTrue(returnCode.isSuccess()); - const interaction = contract.methods.getUltimateAnswer() - .withGasLimit(3000000) - .withChainID(network.ChainID) - .withSender(alice.address); + const interaction = ( + contract.methods + .getUltimateAnswer() + .withGasLimit(3000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); // Query let queryResponseBundle = await controller.query(interaction); @@ -61,10 +69,7 @@ describe("test smart contract interactor", function () { await provider.sendTransaction(transaction); // Execute, and wait for execution - transaction = interaction - .withSender(alice.address) - .useThenIncrementNonceOf(alice.account) - .buildTransaction(); + transaction = interaction.withSender(alice.address).useThenIncrementNonceOf(alice.account).buildTransaction(); await signTransaction({ transaction: transaction, wallet: alice }); let { bundle: executionResultsBundle } = await controller.execute(interaction, transaction); @@ -74,6 +79,99 @@ describe("test smart contract interactor", function () { assert.isTrue(executionResultsBundle.returnCode.equals(ReturnCode.Ok)); }); + it("should interact with 'answer' (local testnet) using the SmartContractTransactionsFactory", async function () { + this.timeout(80000); + + let abiRegistry = await loadAbiRegistry("src/testdata/answer.abi.json"); + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ + config: config, + abi: abiRegistry, + tokenComputer: new TokenComputer(), + }); + + const bytecode = await promises.readFile("src/testdata/answer.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + let contract = new SmartContract({ abi: abiRegistry, address: contractAddress }); + let controller = new ContractController(provider); + + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); + assert.isTrue(returnCode.isSuccess()); + + const interaction = ( + contract.methods + .getUltimateAnswer() + .withGasLimit(3000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + // Query + let queryResponseBundle = await controller.query(interaction); + assert.lengthOf(queryResponseBundle.values, 1); + assert.deepEqual(queryResponseBundle.firstValue!.valueOf(), new BigNumber(42)); + assert.isTrue(queryResponseBundle.returnCode.equals(ReturnCode.Ok)); + + let transaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "getUltimateAnswer", + gasLimit: 3000000n, + }); + transaction.nonce = BigInt(alice.account.nonce.valueOf()); + + transaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + ); + + alice.account.incrementNonce(); + + // await signTransaction({ transaction: transaction, wallet: alice }); + await provider.sendTransaction(transaction); + + // Execute, and wait for execution + transaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "getUltimateAnswer", + gasLimit: 3000000n, + }); + transaction.nonce = BigInt(alice.account.nonce.valueOf()); + + transaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + ); + + alice.account.incrementNonce(); + + let { bundle: executionResultsBundle } = await controller.execute(interaction, transaction); + + assert.lengthOf(executionResultsBundle.values, 1); + assert.deepEqual(executionResultsBundle.firstValue!.valueOf(), new BigNumber(42)); + assert.isTrue(executionResultsBundle.returnCode.equals(ReturnCode.Ok)); + }); + it("should interact with 'counter' (local testnet)", async function () { this.timeout(120000); @@ -91,10 +189,12 @@ describe("test smart contract interactor", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); - let { bundle: { returnCode } } = await controller.deploy(deployTransaction); + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); assert.isTrue(returnCode.isSuccess()); let getInteraction = contract.methods.get(); @@ -114,7 +214,9 @@ describe("test smart contract interactor", function () { // Increment, wait for execution. let incrementTransaction = incrementInteraction.useThenIncrementNonceOf(alice.account).buildTransaction(); await signTransaction({ transaction: incrementTransaction, wallet: alice }); - let { bundle: { firstValue: valueAfterIncrement } } = await controller.execute(incrementInteraction, incrementTransaction); + let { + bundle: { firstValue: valueAfterIncrement }, + } = await controller.execute(incrementInteraction, incrementTransaction); assert.deepEqual(valueAfterIncrement!.valueOf(), new BigNumber(2)); // Decrement twice. Wait for execution of the second transaction. @@ -124,7 +226,113 @@ describe("test smart contract interactor", function () { decrementTransaction = decrementInteraction.useThenIncrementNonceOf(alice.account).buildTransaction(); await signTransaction({ transaction: decrementTransaction, wallet: alice }); - let { bundle: { firstValue: valueAfterDecrement } } = await controller.execute(decrementInteraction, decrementTransaction); + let { + bundle: { firstValue: valueAfterDecrement }, + } = await controller.execute(decrementInteraction, decrementTransaction); + assert.deepEqual(valueAfterDecrement!.valueOf(), new BigNumber(0)); + }); + + it("should interact with 'counter' (local testnet) using the SmartContractTransactionsFactory", async function () { + this.timeout(120000); + + let abiRegistry = await loadAbiRegistry("src/testdata/counter.abi.json"); + // let contract = new SmartContract({ abi: abiRegistry }); + // let controller = new ContractController(provider); + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ + config: config, + abi: abiRegistry, + tokenComputer: new TokenComputer(), + }); + + const bytecode = await promises.readFile("src/testdata/counter.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + let contract = new SmartContract({ abi: abiRegistry, address: contractAddress }); + let controller = new ContractController(provider); + + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); + assert.isTrue(returnCode.isSuccess()); + + let getInteraction = contract.methods.get(); + + let incrementInteraction = (contract.methods.increment()) + .withGasLimit(3000000) + .withChainID(network.ChainID) + .withSender(alice.address); + let decrementInteraction = (contract.methods.decrement()) + .withGasLimit(3000000) + .withChainID(network.ChainID) + .withSender(alice.address); + + let incrementTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 3000000n, + }); + incrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + incrementTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(incrementTransaction)), + ); + + alice.account.incrementNonce(); + + // Query "get()" + let { firstValue: counterValue } = await controller.query(getInteraction); + assert.deepEqual(counterValue!.valueOf(), new BigNumber(1)); + + let { + bundle: { firstValue: valueAfterIncrement }, + } = await controller.execute(incrementInteraction, incrementTransaction); + assert.deepEqual(valueAfterIncrement!.valueOf(), new BigNumber(2)); + + let decrementTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "decrement", + gasLimit: 3000000n, + }); + decrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + decrementTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(decrementTransaction)), + ); + + alice.account.incrementNonce(); + + await provider.sendTransaction(decrementTransaction); + + decrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + decrementTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(decrementTransaction)), + ); + + let { + bundle: { firstValue: valueAfterDecrement }, + } = await controller.execute(decrementInteraction, decrementTransaction); assert.deepEqual(valueAfterDecrement!.valueOf(), new BigNumber(0)); }); @@ -145,35 +353,37 @@ describe("test smart contract interactor", function () { codePath: "src/testdata/lottery-esdt.wasm", gasLimit: 100000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); - let { bundle: { returnCode } } = await controller.deploy(deployTransaction); + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); assert.isTrue(returnCode.isSuccess()); - let startInteraction = contract.methods.start([ - "lucky", - "EGLD", - 1, - null, - null, - 1, - null, - null - ]) - .withGasLimit(30000000) - .withChainID(network.ChainID) - .withSender(alice.address); - - let lotteryStatusInteraction = contract.methods.status(["lucky"]) - .withGasLimit(5000000) - .withChainID(network.ChainID) - .withSender(alice.address); - - let getLotteryInfoInteraction = contract.methods.getLotteryInfo(["lucky"]) - .withGasLimit(5000000) - .withChainID(network.ChainID) - .withSender(alice.address); + let startInteraction = ( + contract.methods + .start(["lucky", "EGLD", 1, null, null, 1, null, null]) + .withGasLimit(30000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + let lotteryStatusInteraction = ( + contract.methods + .status(["lucky"]) + .withGasLimit(5000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + let getLotteryInfoInteraction = ( + contract.methods + .getLotteryInfo(["lucky"]) + .withGasLimit(5000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); // start() let startTransaction = startInteraction @@ -219,11 +429,150 @@ describe("test smart contract interactor", function () { tickets_left: new BigNumber(800), max_entries_per_user: new BigNumber(1), prize_distribution: Buffer.from([0x64]), - prize_pool: new BigNumber("0") + prize_pool: new BigNumber("0"), + }); + }); + + it("should interact with 'lottery-esdt' (local testnet) using the SmartContractTransactionsFactory", async function () { + this.timeout(140000); + + let abiRegistry = await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"); + let contract = new SmartContract({ abi: abiRegistry }); + let controller = new ContractController(provider); + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ + config: config, + abi: abiRegistry, + tokenComputer: new TokenComputer(), + }); + + const bytecode = await promises.readFile("src/testdata/lottery-esdt.wasm"); + + // Deploy the contract + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 100000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + let { + bundle: { returnCode }, + } = await controller.deploy(deployTransaction); + assert.isTrue(returnCode.isSuccess()); + + let startInteraction = ( + contract.methods + .start(["lucky", "EGLD", 1, null, null, 1, null, null]) + .withGasLimit(30000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + let lotteryStatusInteraction = ( + contract.methods + .status(["lucky"]) + .withGasLimit(5000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + let getLotteryInfoInteraction = ( + contract.methods + .getLotteryInfo(["lucky"]) + .withGasLimit(5000000) + .withChainID(network.ChainID) + .withSender(alice.address) + ); + + // start() + let startTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "start", + args: ["lucky", "EGLD", 1, null, null, 1, null, null], + gasLimit: 30000000n, + }); + startTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + startTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(startTransaction)), + ); + + alice.account.incrementNonce(); + + let { bundle: bundleStart } = await controller.execute(startInteraction, startTransaction); + assert.isTrue(bundleStart.returnCode.equals(ReturnCode.Ok)); + assert.lengthOf(bundleStart.values, 0); + + // status() + let lotteryStatusTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "status", + args: ["lucky"], + gasLimit: 5000000n, + }); + lotteryStatusTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + lotteryStatusTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(lotteryStatusTransaction)), + ); + + alice.account.incrementNonce(); + + let { bundle: bundleStatus } = await controller.execute(lotteryStatusInteraction, lotteryStatusTransaction); + assert.isTrue(bundleStatus.returnCode.equals(ReturnCode.Ok)); + assert.lengthOf(bundleStatus.values, 1); + assert.equal(bundleStatus.firstValue!.valueOf().name, "Running"); + + // lotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) + let lotteryInfoTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "getLotteryInfo", + args: ["lucky"], + gasLimit: 5000000n, + }); + lotteryInfoTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + lotteryInfoTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(lotteryInfoTransaction)), + ); + + alice.account.incrementNonce(); + + let { bundle: bundleLotteryInfo } = await controller.execute(getLotteryInfoInteraction, lotteryInfoTransaction); + assert.isTrue(bundleLotteryInfo.returnCode.equals(ReturnCode.Ok)); + assert.lengthOf(bundleLotteryInfo.values, 1); + + // Ignore "deadline" field in our test + let info = bundleLotteryInfo.firstValue!.valueOf(); + delete info.deadline; + + assert.deepEqual(info, { + token_identifier: "EGLD", + ticket_price: new BigNumber("1"), + tickets_left: new BigNumber(800), + max_entries_per_user: new BigNumber(1), + prize_distribution: Buffer.from([0x64]), + prize_pool: new BigNumber("0"), }); }); - async function signTransaction(options: { transaction: Transaction, wallet: TestWallet }) { + async function signTransaction(options: { transaction: Transaction; wallet: TestWallet }) { const transaction = options.transaction; const wallet = options.wallet; diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index e0a637474..d05500323 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -26,7 +26,9 @@ describe("test on local testnet", function () { ({ alice, bob, carol } = await loadTestWallets()); watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true) } + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }); }); @@ -48,7 +50,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // ++ @@ -56,7 +58,7 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 3000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrement.setNonce(alice.account.nonce); transactionIncrement.applySignature(await alice.signer.sign(transactionIncrement.serializeForSigning())); @@ -68,7 +70,7 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 100000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); simulateOne.setSender(alice.address); @@ -76,7 +78,7 @@ describe("test on local testnet", function () { func: new ContractFunction("foobar"), gasLimit: 500000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); simulateTwo.setSender(alice.address); @@ -105,6 +107,95 @@ describe("test on local testnet", function () { Logger.trace(JSON.stringify(await provider.simulateTransaction(simulateTwo), null, 4)); }); + it("counter: should deploy, then simulate transactions using SmartContractTransactionsFactory", async function () { + this.timeout(60000); + + TransactionWatcher.DefaultPollingInterval = 5000; + TransactionWatcher.DefaultTimeout = 50000; + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + + const bytecode = await promises.readFile("src/testdata/counter.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + const smartContractCallTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 3000000n, + }); + smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + smartContractCallTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(smartContractCallTransaction)), + ); + + alice.account.incrementNonce(); + + const simulateOne = factory.createTransactionForExecute({ + sender: alice.address, + functionName: "increment", + contract: contractAddress, + gasLimit: 100000n, + }); + + simulateOne.nonce = BigInt(alice.account.nonce.valueOf()); + simulateOne.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(simulateOne)), + ); + + alice.account.incrementNonce(); + + const simulateTwo = factory.createTransactionForExecute({ + sender: alice.address, + functionName: "foobar", + contract: contractAddress, + gasLimit: 500000n, + }); + + simulateTwo.nonce = BigInt(alice.account.nonce.valueOf()); + simulateTwo.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(simulateTwo)), + ); + + alice.account.incrementNonce(); + + // Broadcast & execute + const deployTxHash = await provider.sendTransaction(deployTransaction); + const callTxHash = await provider.sendTransaction(smartContractCallTransaction); + + await watcher.awaitCompleted(deployTxHash); + let transactionOnNetwork = await provider.getTransaction(deployTxHash); + let bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(bundle.returnCode.isSuccess()); + + await watcher.awaitCompleted(callTxHash); + transactionOnNetwork = await provider.getTransaction(callTxHash); + bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(bundle.returnCode.isSuccess()); + + // Simulate + Logger.trace(JSON.stringify(await provider.simulateTransaction(simulateOne), null, 4)); + Logger.trace(JSON.stringify(await provider.simulateTransaction(simulateTwo), null, 4)); + }); + it("counter: should deploy, call and query contract", async function () { this.timeout(80000); @@ -123,7 +214,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // ++ @@ -131,10 +222,12 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 2000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrementFirst.setNonce(alice.account.nonce); - transactionIncrementFirst.applySignature(await alice.signer.sign(transactionIncrementFirst.serializeForSigning())); + transactionIncrementFirst.applySignature( + await alice.signer.sign(transactionIncrementFirst.serializeForSigning()), + ); alice.account.incrementNonce(); @@ -143,10 +236,12 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 2000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrementSecond.setNonce(alice.account.nonce); - transactionIncrementSecond.applySignature(await alice.signer.sign(transactionIncrementSecond.serializeForSigning())); + transactionIncrementSecond.applySignature( + await alice.signer.sign(transactionIncrementSecond.serializeForSigning()), + ); alice.account.incrementNonce(); @@ -165,6 +260,77 @@ describe("test on local testnet", function () { assert.equal(3, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); }); + it("counter: should deploy, call and query contract using SmartContractTransactionsFactory", async function () { + this.timeout(80000); + + TransactionWatcher.DefaultPollingInterval = 5000; + TransactionWatcher.DefaultTimeout = 50000; + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + + const bytecode = await promises.readFile("src/testdata/counter.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + const firstScCallTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 3000000n, + }); + firstScCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + firstScCallTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(firstScCallTransaction)), + ); + + alice.account.incrementNonce(); + + const secondScCallTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 3000000n, + }); + secondScCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + secondScCallTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(secondScCallTransaction)), + ); + + alice.account.incrementNonce(); + + // Broadcast & execute + const deployTxHash = await provider.sendTransaction(deployTransaction); + const firstScCallHash = await provider.sendTransaction(firstScCallTransaction); + const secondScCallHash = await provider.sendTransaction(secondScCallTransaction); + + await watcher.awaitCompleted(deployTxHash); + await watcher.awaitCompleted(firstScCallHash); + await watcher.awaitCompleted(secondScCallHash); + + // Check counter + const contract = new SmartContract({ address: contractAddress }); + let query = contract.createQuery({ func: new ContractFunction("get") }); + let queryResponse = await provider.queryContract(query); + assert.equal(3, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + }); + it("erc20: should deploy, call and query contract", async function () { this.timeout(60000); @@ -183,7 +349,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/erc20.wasm", gasLimit: 50000000, initArguments: [new U32Value(10000)], - chainID: network.ChainID + chainID: network.ChainID, }); // Minting @@ -192,7 +358,7 @@ describe("test on local testnet", function () { gasLimit: 9000000, args: [new AddressValue(bob.address), new U32Value(1000)], chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); let transactionMintCarol = contract.call({ @@ -200,7 +366,7 @@ describe("test on local testnet", function () { gasLimit: 9000000, args: [new AddressValue(carol.address), new U32Value(1500)], chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); // Apply nonces and sign the remaining transactions @@ -228,7 +394,106 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(alice.address)] + args: [new AddressValue(alice.address)], + }); + queryResponse = await provider.queryContract(query); + + assert.equal(7500, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + + query = contract.createQuery({ + func: new ContractFunction("balanceOf"), + args: [new AddressValue(bob.address)], + }); + queryResponse = await provider.queryContract(query); + + assert.equal(1000, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + + query = contract.createQuery({ + func: new ContractFunction("balanceOf"), + args: [new AddressValue(carol.address)], + }); + queryResponse = await provider.queryContract(query); + + assert.equal(1500, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + }); + + it("erc20: should deploy, call and query contract using SmartContractTransactionsFactory", async function () { + this.timeout(60000); + + TransactionWatcher.DefaultPollingInterval = 5000; + TransactionWatcher.DefaultTimeout = 50000; + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + + const bytecode = await promises.readFile("src/testdata/erc20.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 50000000n, + args: [new U32Value(10000)], + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + const transactionMintBob = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "transferToken", + gasLimit: 9000000n, + args: [new AddressValue(bob.address), new U32Value(1000)], + }); + transactionMintBob.nonce = BigInt(alice.account.nonce.valueOf()); + transactionMintBob.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transactionMintBob)), + ); + + alice.account.incrementNonce(); + + const transactionMintCarol = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "transferToken", + gasLimit: 9000000n, + args: [new AddressValue(carol.address), new U32Value(1500)], + }); + transactionMintCarol.nonce = BigInt(alice.account.nonce.valueOf()); + transactionMintCarol.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transactionMintCarol)), + ); + + alice.account.incrementNonce(); + + // Broadcast & execute + const deployTxHash = await provider.sendTransaction(deployTransaction); + const mintBobTxHash = await provider.sendTransaction(transactionMintBob); + const mintCarolTxHash = await provider.sendTransaction(transactionMintCarol); + + await watcher.awaitCompleted(deployTxHash); + await watcher.awaitCompleted(mintBobTxHash); + await watcher.awaitCompleted(mintCarolTxHash); + + const contract = new SmartContract({ address: contractAddress }); + + // Query state, do some assertions + let query = contract.createQuery({ func: new ContractFunction("totalSupply") }); + let queryResponse = await provider.queryContract(query); + assert.equal(10000, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + + query = contract.createQuery({ + func: new ContractFunction("balanceOf"), + args: [new AddressValue(alice.address)], }); queryResponse = await provider.queryContract(query); @@ -236,7 +501,7 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(bob.address)] + args: [new AddressValue(bob.address)], }); queryResponse = await provider.queryContract(query); @@ -244,7 +509,7 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(carol.address)] + args: [new AddressValue(carol.address)], }); queryResponse = await provider.queryContract(query); @@ -269,7 +534,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/lottery-esdt.wasm", gasLimit: 50000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // Start @@ -285,7 +550,7 @@ describe("test on local testnet", function () { OptionValue.newProvided(new U32Value(1)), OptionValue.newMissing(), OptionValue.newMissing(), - OptionalValue.newMissing() + OptionalValue.newMissing(), ], chainID: network.ChainID, caller: alice.address, @@ -314,67 +579,103 @@ describe("test on local testnet", function () { // Query state, do some assertions let query = contract.createQuery({ func: new ContractFunction("status"), - args: [ - BytesValue.fromUTF8("lucky") - ] + args: [BytesValue.fromUTF8("lucky")], }); let queryResponse = await provider.queryContract(query); assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 1); query = contract.createQuery({ func: new ContractFunction("status"), - args: [ - BytesValue.fromUTF8("missingLottery") - ] + args: [BytesValue.fromUTF8("missingLottery")], }); queryResponse = await provider.queryContract(query); assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0); }); - it("counter: should deploy and call using the SmartContractFactory", async function () { - this.timeout(80000); + it("lottery: should deploy, call and query contract using SmartContractTransactionsFactory", async function () { + this.timeout(60000); TransactionWatcher.DefaultPollingInterval = 5000; TransactionWatcher.DefaultTimeout = 50000; - const network = await provider.getNetworkConfig(); + let network = await provider.getNetworkConfig(); await alice.sync(provider); - const transactionComputer = new TransactionComputer(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); - let bytecode = await promises.readFile("src/testdata/counter.wasm"); + const bytecode = await promises.readFile("src/testdata/lottery-esdt.wasm"); const deployTransaction = factory.createTransactionForDeploy({ sender: alice.address, bytecode: bytecode, - gasLimit: 3000000n, + gasLimit: 50000000n, }); deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); deployTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), ); - const deployTxHash = await provider.sendTransaction(deployTransaction); - await watcher.awaitCompleted(deployTxHash); - const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); - alice.account.incrementNonce(); - const smartContractCallTransaction = factory.createTransactionForExecute({ + const startTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", - gasLimit: 2000000n, + functionName: "start", + gasLimit: 10000000n, + args: [ + BytesValue.fromUTF8("lucky"), + new TokenIdentifierValue("EGLD"), + new BigUIntValue(1), + OptionValue.newMissing(), + OptionValue.newMissing(), + OptionValue.newProvided(new U32Value(1)), + OptionValue.newMissing(), + OptionValue.newMissing(), + OptionalValue.newMissing(), + ], }); - smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - smartContractCallTransaction.signature = await alice.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(smartContractCallTransaction)), + startTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + startTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(startTransaction)), ); - const scCallTxHash = await provider.sendTransaction(smartContractCallTransaction); - await watcher.awaitCompleted(scCallTxHash); + alice.account.incrementNonce(); + + // Broadcast & execute + const deployTx = await provider.sendTransaction(deployTransaction); + const startTx = await provider.sendTransaction(startTransaction); + + await watcher.awaitAllEvents(deployTx, ["SCDeploy"]); + await watcher.awaitAnyEvent(startTx, ["completedTxEvent"]); + + // Let's check the SCRs + let transactionOnNetwork = await provider.getTransaction(deployTx); + let bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(bundle.returnCode.isSuccess()); + + transactionOnNetwork = await provider.getTransaction(startTx); + bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(bundle.returnCode.isSuccess()); + + const contract = new SmartContract({ address: contractAddress }); + + // Query state, do some assertions + let query = contract.createQuery({ + func: new ContractFunction("status"), + args: [BytesValue.fromUTF8("lucky")], + }); + let queryResponse = await provider.queryContract(query); + assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 1); + + query = contract.createQuery({ + func: new ContractFunction("status"), + args: [BytesValue.fromUTF8("missingLottery")], + }); + queryResponse = await provider.queryContract(query); + assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0); }); }); diff --git a/src/smartcontracts/smartContractResults.local.net.spec.ts b/src/smartcontracts/smartContractResults.local.net.spec.ts index 885cb12f5..f465fc7c7 100644 --- a/src/smartcontracts/smartContractResults.local.net.spec.ts +++ b/src/smartcontracts/smartContractResults.local.net.spec.ts @@ -5,6 +5,11 @@ import { TransactionWatcher } from "../transactionWatcher"; import { ContractFunction } from "./function"; import { ResultsParser } from "./resultsParser"; import { SmartContract } from "./smartContract"; +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; +import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; +import { TokenComputer } from "../tokens"; +import { promises } from "fs"; +import { TransactionComputer } from "../transaction"; describe("fetch transactions from local testnet", function () { let alice: TestWallet; @@ -16,7 +21,9 @@ describe("fetch transactions from local testnet", function () { before(async function () { ({ alice } = await loadTestWallets()); watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true) } + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }); }); @@ -38,7 +45,7 @@ describe("fetch transactions from local testnet", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // ++ @@ -46,7 +53,7 @@ describe("fetch transactions from local testnet", function () { func: new ContractFunction("increment"), gasLimit: 3000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrement.setNonce(alice.account.nonce); @@ -70,4 +77,63 @@ describe("fetch transactions from local testnet", function () { bundle = resultsParser.parseUntypedOutcome(transactionOnNetworkIncrement); assert.isTrue(bundle.returnCode.isSuccess()); }); + + it("interact with counter smart contract using SmartContractTransactionsFactory", async function () { + this.timeout(60000); + + TransactionWatcher.DefaultPollingInterval = 5000; + TransactionWatcher.DefaultTimeout = 50000; + + let network = await provider.getNetworkConfig(); + await alice.sync(provider); + + const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); + const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + + const bytecode = await promises.readFile("src/testdata/counter.wasm"); + + const deployTransaction = factory.createTransactionForDeploy({ + sender: alice.address, + bytecode: bytecode, + gasLimit: 3000000n, + }); + deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + + const transactionComputer = new TransactionComputer(); + deployTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), + ); + + const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); + alice.account.incrementNonce(); + + const smartContractCallTransaction = factory.createTransactionForExecute({ + sender: alice.address, + contract: contractAddress, + functionName: "increment", + gasLimit: 3000000n, + }); + smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); + smartContractCallTransaction.signature = await alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(smartContractCallTransaction)), + ); + + alice.account.incrementNonce(); + + // Broadcast & execute + const deployTxHash = await provider.sendTransaction(deployTransaction); + const callTxHash = await provider.sendTransaction(smartContractCallTransaction); + + await watcher.awaitCompleted(deployTxHash); + await watcher.awaitCompleted(callTxHash); + + let transactionOnNetworkDeploy = await provider.getTransaction(deployTxHash); + let transactionOnNetworkIncrement = await provider.getTransaction(callTxHash); + + let bundle = resultsParser.parseUntypedOutcome(transactionOnNetworkDeploy); + assert.isTrue(bundle.returnCode.isSuccess()); + + bundle = resultsParser.parseUntypedOutcome(transactionOnNetworkIncrement); + assert.isTrue(bundle.returnCode.isSuccess()); + }); }); diff --git a/src/testutils/contractController.ts b/src/testutils/contractController.ts index 1d1b7ca19..0e1bcd071 100644 --- a/src/testutils/contractController.ts +++ b/src/testutils/contractController.ts @@ -3,7 +3,7 @@ import { Logger } from "../logger"; import { Interaction } from "../smartcontracts/interaction"; import { TypedOutcomeBundle, UntypedOutcomeBundle } from "../smartcontracts/interface"; import { ResultsParser } from "../smartcontracts/resultsParser"; -import { Transaction } from "../transaction"; +import { Transaction, TransactionComputer, TransactionNext } from "../transaction"; import { TransactionWatcher } from "../transactionWatcher"; import { INetworkProvider } from "./networkProviders"; @@ -20,27 +20,29 @@ export class ContractController { }); } - async deploy(transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: UntypedOutcomeBundle }> { - Logger.info(`ContractController.deploy [begin]: transaction = ${transaction.getHash()}`); + async deploy(transaction: Transaction | TransactionNext): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: UntypedOutcomeBundle }> { + const txHash = this.getTransactionHash(transaction); + Logger.info(`ContractController.deploy [begin]: transaction = ${txHash}`); await this.provider.sendTransaction(transaction); - let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex()); + let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(txHash); let bundle = this.parser.parseUntypedOutcome(transactionOnNetwork); - Logger.info(`ContractController.deploy [end]: transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`); + Logger.info(`ContractController.deploy [end]: transaction = ${txHash}, return code = ${bundle.returnCode}`); return { transactionOnNetwork, bundle }; } - async execute(interaction: Interaction, transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: TypedOutcomeBundle }> { - Logger.info(`ContractController.execute [begin]: function = ${interaction.getFunction()}, transaction = ${transaction.getHash()}`); + async execute(interaction: Interaction, transaction: Transaction | TransactionNext): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: TypedOutcomeBundle }> { + const txHash = this.getTransactionHash(transaction); + Logger.info(`ContractController.execute [begin]: function = ${interaction.getFunction()}, transaction = ${txHash}`); interaction.check(); await this.provider.sendTransaction(transaction); - let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(transaction.getHash().hex()); + let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(txHash); let bundle = this.parser.parseOutcome(transactionOnNetwork, interaction.getEndpoint()); - Logger.info(`ContractController.execute [end]: function = ${interaction.getFunction()}, transaction = ${transaction.getHash()}, return code = ${bundle.returnCode}`); + Logger.info(`ContractController.execute [end]: function = ${interaction.getFunction()}, transaction = ${txHash}, return code = ${bundle.returnCode}`); return { transactionOnNetwork, bundle }; } @@ -55,4 +57,14 @@ export class ContractController { Logger.debug(`ContractController.query [end]: function = ${interaction.getFunction()}, return code = ${bundle.returnCode}`); return bundle; } + + private getTransactionHash(transaction: Transaction | TransactionNext): string { + if ("toSendable" in transaction){ + return transaction.getHash().hex(); + } + + const transactionComputer = new TransactionComputer(); + const txHash = transactionComputer.computeTransactionHash(transaction); + return Buffer.from(txHash).toString("hex"); + } } diff --git a/src/testutils/networkProviders.ts b/src/testutils/networkProviders.ts index 48071d3f3..0445d6c9c 100644 --- a/src/testutils/networkProviders.ts +++ b/src/testutils/networkProviders.ts @@ -24,6 +24,6 @@ export interface INetworkProvider { getTransaction(txHash: string, withProcessStatus?: boolean): Promise; getTransactionStatus(txHash: string): Promise; sendTransaction(tx: Transaction | TransactionNext): Promise; - simulateTransaction(tx: Transaction): Promise; + simulateTransaction(tx: Transaction | TransactionNext): Promise; queryContract(query: Query): Promise; } From ef8c7ca89161cb235cb6f8e8096ed09c0fccf3d0 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 23 Feb 2024 18:22:23 +0200 Subject: [PATCH 121/275] remove commented code --- src/smartcontracts/interaction.local.net.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 69133d356..7fa0ff41c 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -236,8 +236,6 @@ describe("test smart contract interactor", function () { this.timeout(120000); let abiRegistry = await loadAbiRegistry("src/testdata/counter.abi.json"); - // let contract = new SmartContract({ abi: abiRegistry }); - // let controller = new ContractController(provider); let network = await provider.getNetworkConfig(); await alice.sync(provider); From f2ec87a954a2c2b42c4a4d80b293b8c85e37efe7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 23 Feb 2024 18:28:51 +0200 Subject: [PATCH 122/275] change factories constructor to ensure consistency --- src/transaction.local.net.spec.ts | 2 +- .../smartContractTransactionsFactory.ts | 8 ++++---- .../transferTransactionsFactory.spec.ts | 5 ++++- src/transactionsFactories/transferTransactionsFactory.ts | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index c00bbaa13..52302c5d5 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -152,7 +152,7 @@ describe("test transaction", function () { const network = await provider.getNetworkConfig(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); + const factory = new NextTransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); await alice.sync(provider); await bob.sync(provider); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 329634de5..bf0771796 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -35,10 +35,10 @@ export class SmartContractTransactionsFactory { private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { - this.config = config; - this.abiRegistry = abi; - this.tokenComputer = tokenComputer; + constructor(options: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { + this.config = options.config; + this.abiRegistry = options.abi; + this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 3cc865dbc..53e0330eb 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -7,7 +7,10 @@ import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); - const nextTransferFactory = new NextTransferTransactionsFactory(config, new TokenComputer()); + const nextTransferFactory = new NextTransferTransactionsFactory({ + config: config, + tokenComputer: new TokenComputer(), + }); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 226e238ed..9490647a5 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -30,9 +30,9 @@ export class NextTransferTransactionsFactory { private readonly dataArgsBuilder: TokenTransfersDataBuilder; private readonly tokenComputer: TokenComputer; - constructor(config: IConfig, tokenComputer: TokenComputer) { - this.config = config; - this.tokenComputer = tokenComputer; + constructor(options: { config: IConfig; tokenComputer: TokenComputer }) { + this.config = options.config; + this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } From 3605c69a6cb00733b8804504cf471ae56ad80e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 26 Feb 2024 13:53:28 +0200 Subject: [PATCH 123/275] Define BigNumber as peer dependency. --- package-lock.json | 8 +++++--- package.json | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56354a1d1..37071db97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,16 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.3", + "version": "13.0.0-beta.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.3", + "version": "13.0.0-beta.4", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", "bech32": "1.1.4", - "bignumber.js": "9.0.1", "blake2b": "2.1.3", "buffer": "6.0.3", "json-bigint": "1.0.0", @@ -39,6 +38,9 @@ "prettier": "3.2.4", "ts-node": "9.1.1", "typescript": "4.1.2" + }, + "peerDependencies": { + "bignumber.js": "^9.0.1" } }, "@multiversx/sdk-wallet:4.0.0-beta.3": { diff --git a/package.json b/package.json index 039fbbfd8..e4cc22866 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.3", + "version": "13.0.0-beta.4", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -29,7 +29,6 @@ "@multiversx/sdk-transaction-decoder": "1.0.2", "json-bigint": "1.0.0", "bech32": "1.1.4", - "bignumber.js": "9.0.1", "blake2b": "2.1.3", "buffer": "6.0.3", "json-duplicate-key-handle": "1.0.0", @@ -56,5 +55,8 @@ "eslint": "8.28.0", "eslint-config-prettier": "9.1.0", "prettier": "3.2.4" + }, + "peerDependencies": { + "bignumber.js": "^9.0.1" } } From 114ccd5a46f475f1b2fef420b0e54bb395eb9cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 5 Mar 2024 14:35:54 +0200 Subject: [PATCH 124/275] Sketch queries controller. --- src/smartContractQueriesController.spec.ts | 196 ++++++++++++++++++ src/smartContractQueriesController.ts | 130 ++++++++++++ src/smartContractQuery.ts | 35 ++++ src/smartcontracts/interaction.spec.ts | 4 +- src/smartcontracts/smartContract.spec.ts | 4 +- src/testutils/index.ts | 2 +- ...mockProvider.ts => mockNetworkProvider.ts} | 8 +- src/transactionWatcher.spec.ts | 4 +- 8 files changed, 372 insertions(+), 11 deletions(-) create mode 100644 src/smartContractQueriesController.spec.ts create mode 100644 src/smartContractQueriesController.ts create mode 100644 src/smartContractQuery.ts rename src/testutils/{mockProvider.ts => mockNetworkProvider.ts} (94%) diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts new file mode 100644 index 000000000..434277887 --- /dev/null +++ b/src/smartContractQueriesController.spec.ts @@ -0,0 +1,196 @@ +import { ContractQueryResponse } from "@multiversx/sdk-network-providers"; +import { assert } from "chai"; +import { SmartContractQueriesController } from "./smartContractQueriesController"; +import { SmartContractQueryResponse } from "./smartContractQuery"; +import { AbiRegistry, BigUIntValue, BooleanValue, BytesValue, Tuple, U16Value, U64Value } from "./smartcontracts"; +import { bigIntToBuffer } from "./smartcontracts/codec/utils"; +import { MockNetworkProvider, loadAbiRegistry } from "./testutils"; + +describe("test smart contract queries controller", () => { + describe("createQuery", () => { + it("works without ABI, when arguments are buffers", function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + }); + + const query = controller.createQuery({ + contract: "erd1foo", + function: "bar", + arguments: [bigIntToBuffer(42), Buffer.from("abba")], + }); + + assert.equal(query.contract, "erd1foo"); + assert.equal(query.function, "bar"); + assert.deepEqual(query.arguments, [bigIntToBuffer(42), Buffer.from("abba")]); + }); + + it("works without ABI, when arguments are typed values", function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + }); + + const query = controller.createQuery({ + contract: "erd1foo", + function: "bar", + arguments: [new BigUIntValue(42), BytesValue.fromUTF8("abba")], + }); + + assert.equal(query.contract, "erd1foo"); + assert.equal(query.function, "bar"); + assert.deepEqual(query.arguments, [bigIntToBuffer(42), Buffer.from("abba")]); + }); + + it("fails without ABI, when arguments aren't buffers, nor typed values", function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + }); + + assert.throws(() => { + controller.createQuery({ + contract: "erd1foo", + function: "bar", + arguments: [42, "abba"], + }); + }, "cannot encode arguments"); + }); + + it("works with ABI, when arguments are native JS objects", async function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + }); + + const query = controller.createQuery({ + contract: "erd1foo", + function: "getLotteryInfo", + arguments: ["myLottery"], + }); + + assert.equal(query.contract, "erd1foo"); + assert.equal(query.function, "getLotteryInfo"); + assert.deepEqual(query.arguments, [Buffer.from("myLottery")]); + }); + + it("works with ABI, when arguments typed values", async function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + }); + + const query = controller.createQuery({ + contract: "erd1foo", + function: "getLotteryInfo", + arguments: [BytesValue.fromUTF8("myLottery")], + }); + + assert.equal(query.contract, "erd1foo"); + assert.equal(query.function, "getLotteryInfo"); + assert.deepEqual(query.arguments, [Buffer.from("myLottery")]); + }); + + it("works with ABI, with mixed arguments", async function () { + const abi = AbiRegistry.create({ + endpoints: [ + { + name: "bar", + inputs: [ + { + type: "tuple", + }, + { + type: "tuple>", + }, + { + type: "List>", + }, + { + type: "u64", + }, + ], + outputs: [], + }, + ], + }); + + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + abi: abi, + }); + + const query = controller.createQuery({ + contract: "erd1foo", + function: "bar", + arguments: [ + // Typed value + Tuple.fromItems([new U16Value(42), new BooleanValue(true)]), + // Native JS objects + [43, false], + [ + [44, false], + [45, true], + ], + // Typed value + new U64Value(46), + ], + }); + + assert.equal(query.contract, "erd1foo"); + assert.equal(query.function, "bar"); + assert.deepEqual(query.arguments, [ + Buffer.from("002a01", "hex"), + Buffer.from("2b0100", "hex"), + Buffer.from("2c002d01", "hex"), + Buffer.from("2e", "hex"), + ]); + }); + }); + + describe("runQuery", () => { + it("calls queryContract on the network provider", async function () { + const networkProvider = new MockNetworkProvider(); + const controller = new SmartContractQueriesController({ + networkProvider: networkProvider, + }); + + networkProvider.mockQueryContractOnFunction( + "bar", + new ContractQueryResponse({ + returnData: [Buffer.from("abba").toString("base64")], + returnCode: "ok", + }), + ); + + const query = { + contract: "erd1qqqqqqqqqqqqqpgqvc7gdl0p4s97guh498wgz75k8sav6sjfjlwqh679jy", + function: "bar", + arguments: [], + }; + + const response = await controller.runQuery(query); + + assert.equal(response.returnCode, "ok"); + assert.deepEqual(response.returnDataParts, [Buffer.from("abba")]); + }); + }); + + describe("parseQueryResponse", () => { + it("works without ABI", function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + }); + + const response = new SmartContractQueryResponse({ + function: "bar", + returnCode: "ok", + returnMessage: "ok", + returnDataParts: [Buffer.from("abba")], + }); + + const parsed = controller.parseQueryResponse(response); + + assert.deepEqual(parsed, [Buffer.from("abba")]); + }); + + it("works with ABI", function () {}); + }); +}); diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts new file mode 100644 index 000000000..fc71b69c7 --- /dev/null +++ b/src/smartContractQueriesController.ts @@ -0,0 +1,130 @@ +import { Address } from "./address"; +import { Err } from "./errors"; +import { IAddress } from "./interface"; +import { IContractQueryResponse } from "./interfaceOfNetwork"; +import { SmartContractQuery, SmartContractQueryResponse } from "./smartContractQuery"; +import { ArgSerializer, ContractFunction, EndpointDefinition, NativeSerializer, ResultsParser } from "./smartcontracts"; + +interface Abi { + getEndpoint(name: string | ContractFunction): EndpointDefinition; +} + +interface INetworkProvider { + queryContract(query: ILegacyQuery): Promise; +} + +interface ILegacyQuery { + address: IAddress; + caller?: IAddress; + func: { toString(): string }; + value?: { toString(): string }; + getEncodedArguments(): string[]; +} + +export class SmartContractQueriesController { + private readonly abi?: Abi; + private readonly networkProvider: INetworkProvider; + private readonly legacyResultsParser: ResultsParser; + + constructor(options: { abi?: Abi; networkProvider: INetworkProvider }) { + this.abi = options.abi; + this.networkProvider = options.networkProvider; + this.legacyResultsParser = new ResultsParser(); + } + + createQuery(options: { + contract: string; + caller?: string; + value?: bigint; + function: string; + arguments: any[]; + }): SmartContractQuery { + const preparedArguments = this.encodeArguments(options.function, options.arguments); + + return new SmartContractQuery({ + contract: options.contract, + caller: options.caller, + function: options.function, + arguments: preparedArguments, + value: options.value, + }); + } + + private encodeArguments(functionName: string, args: any[]): Uint8Array[] { + const endpoint = this.abi?.getEndpoint(functionName); + + if (endpoint) { + const typedArgs = NativeSerializer.nativeToTypedValues(args, endpoint); + return new ArgSerializer().valuesToBuffers(typedArgs); + } + + if (this.areArgsOfTypedValue(args)) { + return new ArgSerializer().valuesToBuffers(args); + } + + if (this.areArgsBuffers(args)) { + return args.map((arg) => Buffer.from(arg)); + } + + throw new Err( + "cannot encode arguments: when ABI is not available, they must be either typed values or buffers", + ); + } + + private areArgsOfTypedValue(args: any[]): boolean { + for (const arg of args) { + if (!arg.belongsToTypesystem) { + return false; + } + } + + return true; + } + + private areArgsBuffers(args: any[]): boolean { + for (const arg of args) { + if (!ArrayBuffer.isView(arg)) { + return false; + } + } + + return true; + } + + async runQuery(query: SmartContractQuery): Promise { + const legacyQuery: ILegacyQuery = { + address: Address.fromBech32(query.contract), + caller: query.caller ? Address.fromBech32(query.caller) : undefined, + func: query.function, + value: query.value, + getEncodedArguments: () => query.arguments.map((arg) => Buffer.from(arg).toString("hex")), + }; + + const legacyQueryResponse = await this.networkProvider.queryContract(legacyQuery); + const queryResponse = new SmartContractQueryResponse({ + function: query.function, + returnCode: legacyQueryResponse.returnCode.toString(), + returnMessage: legacyQueryResponse.returnMessage, + returnDataParts: legacyQueryResponse.getReturnDataParts(), + }); + + return queryResponse; + } + + parseQueryResponse(response: SmartContractQueryResponse): any[] { + if (!this.abi) { + return response.returnDataParts; + } + + const legacyQueryResponse: IContractQueryResponse = { + returnCode: response.returnCode, + returnMessage: response.returnMessage, + getReturnDataParts: () => response.returnDataParts.map((part) => Buffer.from(part)), + }; + + const functionName = response.function; + const endpoint = this.abi.getEndpoint(functionName); + const legacyBundle = this.legacyResultsParser.parseQueryResponse(legacyQueryResponse, endpoint); + return legacyBundle.values; + } +} diff --git a/src/smartContractQuery.ts b/src/smartContractQuery.ts new file mode 100644 index 000000000..275d16bc8 --- /dev/null +++ b/src/smartContractQuery.ts @@ -0,0 +1,35 @@ +export class SmartContractQuery { + contract: string; + caller?: string; + value?: bigint; + function: string; + arguments: Uint8Array[]; + + constructor(options: { + contract: string; + caller?: string; + value?: bigint; + function: string; + arguments: Uint8Array[]; + }) { + this.contract = options.contract; + this.caller = options.caller; + this.value = options.value; + this.function = options.function; + this.arguments = options.arguments; + } +} + +export class SmartContractQueryResponse { + function: string; + returnCode: string; + returnMessage: string; + returnDataParts: Uint8Array[]; + + constructor(obj: { function: string; returnCode: string; returnMessage: string; returnDataParts: Uint8Array[] }) { + this.function = obj.function; + this.returnCode = obj.returnCode; + this.returnMessage = obj.returnMessage; + this.returnDataParts = obj.returnDataParts; + } +} diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 8cc6157c2..4b0f9f7bc 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -5,7 +5,7 @@ import { Address } from "../address"; import { loadAbiRegistry, loadTestWallets, - MockProvider, + MockNetworkProvider, setupUnitTestWatcherTimeouts, TestWallet } from "../testutils"; @@ -20,7 +20,7 @@ import { BytesValue } from "./typesystem/bytes"; describe("test smart contract interactor", function () { let dummyAddress = new Address("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); - let provider = new MockProvider(); + let provider = new MockNetworkProvider(); let alice: TestWallet; before(async function () { diff --git a/src/smartcontracts/smartContract.spec.ts b/src/smartcontracts/smartContract.spec.ts index 23ad37018..11ba86d75 100644 --- a/src/smartcontracts/smartContract.spec.ts +++ b/src/smartcontracts/smartContract.spec.ts @@ -1,7 +1,7 @@ import { TransactionStatus } from "@multiversx/sdk-network-providers"; import { assert } from "chai"; import { Address } from "../address"; -import { loadTestWallets, MarkCompleted, MockProvider, setupUnitTestWatcherTimeouts, TestWallet, Wait } from "../testutils"; +import { loadTestWallets, MarkCompleted, MockNetworkProvider, setupUnitTestWatcherTimeouts, TestWallet, Wait } from "../testutils"; import { TransactionWatcher } from "../transactionWatcher"; import { Code } from "./code"; import { ContractFunction } from "./function"; @@ -11,7 +11,7 @@ import { BytesValue } from "./typesystem/bytes"; describe("test contract", () => { - let provider = new MockProvider(); + let provider = new MockNetworkProvider(); let chainID = "test"; let alice: TestWallet; diff --git a/src/testutils/index.ts b/src/testutils/index.ts index 6a28a8ff0..7e9e84738 100644 --- a/src/testutils/index.ts +++ b/src/testutils/index.ts @@ -1,3 +1,3 @@ -export * from "./mockProvider"; +export * from "./mockNetworkProvider"; export * from "./utils"; export * from "./wallets"; diff --git a/src/testutils/mockProvider.ts b/src/testutils/mockNetworkProvider.ts similarity index 94% rename from src/testutils/mockProvider.ts rename to src/testutils/mockNetworkProvider.ts index fc867a6c0..4a842e0cc 100644 --- a/src/testutils/mockProvider.ts +++ b/src/testutils/mockNetworkProvider.ts @@ -20,7 +20,7 @@ import { Query } from "../smartcontracts/query"; import { Transaction, TransactionHash } from "../transaction"; import { createAccountBalance } from "./utils"; -export class MockProvider { +export class MockNetworkProvider { static AddressOfAlice = new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); static AddressOfBob = new Address("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); static AddressOfCarol = new Address("erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8"); @@ -35,9 +35,9 @@ export class MockProvider { this.transactions = new Map(); this.accounts = new Map(); - this.accounts.set(MockProvider.AddressOfAlice.bech32(), { nonce: 0, balance: createAccountBalance(1000) }); - this.accounts.set(MockProvider.AddressOfBob.bech32(), { nonce: 5, balance: createAccountBalance(500) }); - this.accounts.set(MockProvider.AddressOfCarol.bech32(), { nonce: 42, balance: createAccountBalance(300) }); + this.accounts.set(MockNetworkProvider.AddressOfAlice.bech32(), { nonce: 0, balance: createAccountBalance(1000) }); + this.accounts.set(MockNetworkProvider.AddressOfBob.bech32(), { nonce: 5, balance: createAccountBalance(500) }); + this.accounts.set(MockNetworkProvider.AddressOfCarol.bech32(), { nonce: 42, balance: createAccountBalance(300) }); } mockUpdateAccount(address: Address, mutate: (item: IAccountOnNetwork) => void) { diff --git a/src/transactionWatcher.spec.ts b/src/transactionWatcher.spec.ts index 058df41e9..7f329970c 100644 --- a/src/transactionWatcher.spec.ts +++ b/src/transactionWatcher.spec.ts @@ -1,6 +1,6 @@ import { TransactionOnNetwork, TransactionStatus } from "@multiversx/sdk-network-providers"; import { assert } from "chai"; -import { MarkCompleted, MockProvider, Wait } from "./testutils"; +import { MarkCompleted, MockNetworkProvider, Wait } from "./testutils"; import { TransactionHash } from "./transaction"; import { TransactionWatcher } from "./transactionWatcher"; @@ -8,7 +8,7 @@ import { TransactionWatcher } from "./transactionWatcher"; describe("test transactionWatcher", () => { it("should await status == executed", async () => { let hash = new TransactionHash("abba"); - let provider = new MockProvider(); + let provider = new MockNetworkProvider(); let watcher = new TransactionWatcher(provider, { pollingIntervalMilliseconds: 42, timeoutMilliseconds: 42 * 42 From 9c1b5c7cecfdd8f8a09dd9541e0ca8dc96d82c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 5 Mar 2024 15:05:18 +0200 Subject: [PATCH 125/275] Additional test. --- src/smartContractQueriesController.spec.ts | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index 434277887..69954b452 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -1,4 +1,5 @@ import { ContractQueryResponse } from "@multiversx/sdk-network-providers"; +import BigNumber from "bignumber.js"; import { assert } from "chai"; import { SmartContractQueriesController } from "./smartContractQueriesController"; import { SmartContractQueryResponse } from "./smartContractQuery"; @@ -191,6 +192,36 @@ describe("test smart contract queries controller", () => { assert.deepEqual(parsed, [Buffer.from("abba")]); }); - it("works with ABI", function () {}); + it("works with ABI", async function () { + const controller = new SmartContractQueriesController({ + networkProvider: new MockNetworkProvider(), + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + }); + + const response = new SmartContractQueryResponse({ + function: "getLotteryInfo", + returnCode: "ok", + returnMessage: "ok", + returnDataParts: [ + Buffer.from( + "0000000b6c75636b792d746f6b656e000000010100000000000000005fc2b9dbffffffff00000001640000000a140ec80fa7ee88000000", + "hex", + ), + ], + }); + + const parsed = controller.parseQueryResponse(response); + const plainData = parsed[0].valueOf(); + + assert.deepEqual(plainData, { + token_identifier: "lucky-token", + ticket_price: new BigNumber("1"), + tickets_left: new BigNumber(0), + deadline: new BigNumber("0x000000005fc2b9db", 16), + max_entries_per_user: new BigNumber(0xffffffff), + prize_distribution: Buffer.from([0x64]), + prize_pool: new BigNumber("94720000000000000000000"), + }); + }); }); }); From 832cb0822940dfa1ef2ac7e7d8c869f543980f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 5 Mar 2024 16:17:04 +0200 Subject: [PATCH 126/275] Fix after review. --- src/smartContractQueriesController.ts | 6 +++--- .../smartContractTransactionsFactory.ts | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts index fc71b69c7..64155645b 100644 --- a/src/smartContractQueriesController.ts +++ b/src/smartContractQueriesController.ts @@ -5,7 +5,7 @@ import { IContractQueryResponse } from "./interfaceOfNetwork"; import { SmartContractQuery, SmartContractQueryResponse } from "./smartContractQuery"; import { ArgSerializer, ContractFunction, EndpointDefinition, NativeSerializer, ResultsParser } from "./smartcontracts"; -interface Abi { +interface IAbi { getEndpoint(name: string | ContractFunction): EndpointDefinition; } @@ -22,11 +22,11 @@ interface ILegacyQuery { } export class SmartContractQueriesController { - private readonly abi?: Abi; + private readonly abi?: IAbi; private readonly networkProvider: INetworkProvider; private readonly legacyResultsParser: ResultsParser; - constructor(options: { abi?: Abi; networkProvider: INetworkProvider }) { + constructor(options: { abi?: IAbi; networkProvider: INetworkProvider }) { this.abi = options.abi; this.networkProvider = options.networkProvider; this.legacyResultsParser = new ResultsParser(); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 329634de5..1b86724c0 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -16,7 +16,7 @@ interface Config { gasLimitPerByte: bigint; } -interface Abi { +interface IAbi { constructorDefinition: EndpointDefinition; getEndpoint(name: string | ContractFunction): EndpointDefinition; @@ -31,13 +31,13 @@ interface TokenComputer { */ export class SmartContractTransactionsFactory { private readonly config: Config; - private readonly abiRegistry?: Abi; + private readonly abi?: IAbi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - constructor({ config, abi, tokenComputer }: { config: Config; abi?: Abi; tokenComputer: TokenComputer }) { + constructor({ config, abi, tokenComputer }: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { this.config = config; - this.abiRegistry = abi; + this.abi = abi; this.tokenComputer = tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } @@ -61,7 +61,7 @@ export class SmartContractTransactionsFactory { const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); + const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); return new TransactionNextBuilder({ @@ -111,7 +111,7 @@ export class SmartContractTransactionsFactory { } dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); - dataParts = dataParts.concat(this.argsToDataParts(args, this.abiRegistry?.getEndpoint(options.functionName))); + dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.functionName))); return new TransactionNextBuilder({ config: this.config, @@ -147,7 +147,7 @@ export class SmartContractTransactionsFactory { const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; - const preparedArgs = this.argsToDataParts(args, this.abiRegistry?.constructorDefinition); + const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); return new TransactionNextBuilder({ From 69a81560dda862a20903d1930fc4c860b788c8ec Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 6 Mar 2024 18:57:45 +0200 Subject: [PATCH 127/275] adapter for executing smart contract queries --- src/adaptors/index.ts | 1 + src/adaptors/smartContractQueriesAdaptor.ts | 51 +++++++++++++++++++++ src/smartContractQueriesController.spec.ts | 48 +++++++++++++------ src/smartContractQueriesController.ts | 31 +++++-------- 4 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 src/adaptors/index.ts create mode 100644 src/adaptors/smartContractQueriesAdaptor.ts diff --git a/src/adaptors/index.ts b/src/adaptors/index.ts new file mode 100644 index 000000000..9fa9c9a34 --- /dev/null +++ b/src/adaptors/index.ts @@ -0,0 +1 @@ +export * from "./smartContractQueriesAdaptor"; diff --git a/src/adaptors/smartContractQueriesAdaptor.ts b/src/adaptors/smartContractQueriesAdaptor.ts new file mode 100644 index 000000000..b8c2151ff --- /dev/null +++ b/src/adaptors/smartContractQueriesAdaptor.ts @@ -0,0 +1,51 @@ +import { Address } from "../address"; +import { IAddress } from "../interface"; +import { IContractQueryResponse } from "../interfaceOfNetwork"; +import { SmartContractQuery, SmartContractQueryResponse } from "../smartContractQuery"; +import { ContractFunction, EndpointDefinition } from "../smartcontracts"; + +interface INetworkProvider { + queryContract(query: ILegacyQuery): Promise; +} + +interface IAbi { + getEndpoint(name: string | ContractFunction): EndpointDefinition; +} + +interface ILegacyQuery { + address: IAddress; + caller?: IAddress; + func: { toString(): string }; + value?: { toString(): string }; + getEncodedArguments(): string[]; +} + +export class SmartContractQueriesAdaptor { + abi?: IAbi; + networkProvider: INetworkProvider; + + constructor(options: { abi?: IAbi; networkProvider: INetworkProvider }) { + this.abi = options.abi; + this.networkProvider = options.networkProvider; + } + + async queryContract(query: SmartContractQuery): Promise { + const legacyQuery: ILegacyQuery = { + address: Address.fromBech32(query.contract), + caller: query.caller ? Address.fromBech32(query.caller) : undefined, + func: query.function, + value: query.value, + getEncodedArguments: () => query.arguments.map((arg) => Buffer.from(arg).toString("hex")), + }; + + const legacyQueryResponse = await this.networkProvider.queryContract(legacyQuery); + const queryResponse = new SmartContractQueryResponse({ + function: query.function, + returnCode: legacyQueryResponse.returnCode.toString(), + returnMessage: legacyQueryResponse.returnMessage, + returnDataParts: legacyQueryResponse.getReturnDataParts(), + }); + + return queryResponse; + } +} diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index 69954b452..915c0c647 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -6,12 +6,14 @@ import { SmartContractQueryResponse } from "./smartContractQuery"; import { AbiRegistry, BigUIntValue, BooleanValue, BytesValue, Tuple, U16Value, U64Value } from "./smartcontracts"; import { bigIntToBuffer } from "./smartcontracts/codec/utils"; import { MockNetworkProvider, loadAbiRegistry } from "./testutils"; +import { SmartContractQueriesAdaptor } from "./adaptors/smartContractQueriesAdaptor"; describe("test smart contract queries controller", () => { describe("createQuery", () => { it("works without ABI, when arguments are buffers", function () { + const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + queryRunner: adapter, }); const query = controller.createQuery({ @@ -26,8 +28,9 @@ describe("test smart contract queries controller", () => { }); it("works without ABI, when arguments are typed values", function () { + const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + queryRunner: adapter, }); const query = controller.createQuery({ @@ -42,8 +45,9 @@ describe("test smart contract queries controller", () => { }); it("fails without ABI, when arguments aren't buffers, nor typed values", function () { + const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + queryRunner: adapter, }); assert.throws(() => { @@ -56,9 +60,12 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments are native JS objects", async function () { - const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + const adapter = new SmartContractQueriesAdaptor({ abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + networkProvider: new MockNetworkProvider(), + }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, }); const query = controller.createQuery({ @@ -73,9 +80,12 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments typed values", async function () { - const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + const adapter = new SmartContractQueriesAdaptor({ abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + networkProvider: new MockNetworkProvider(), + }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, }); const query = controller.createQuery({ @@ -113,9 +123,12 @@ describe("test smart contract queries controller", () => { ], }); - const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + const adapter = new SmartContractQueriesAdaptor({ abi: abi, + networkProvider: new MockNetworkProvider(), + }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, }); const query = controller.createQuery({ @@ -149,9 +162,12 @@ describe("test smart contract queries controller", () => { describe("runQuery", () => { it("calls queryContract on the network provider", async function () { const networkProvider = new MockNetworkProvider(); - const controller = new SmartContractQueriesController({ + const adapter = new SmartContractQueriesAdaptor({ networkProvider: networkProvider, }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, + }); networkProvider.mockQueryContractOnFunction( "bar", @@ -176,9 +192,12 @@ describe("test smart contract queries controller", () => { describe("parseQueryResponse", () => { it("works without ABI", function () { - const controller = new SmartContractQueriesController({ + const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider(), }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, + }); const response = new SmartContractQueryResponse({ function: "bar", @@ -193,9 +212,12 @@ describe("test smart contract queries controller", () => { }); it("works with ABI", async function () { - const controller = new SmartContractQueriesController({ - networkProvider: new MockNetworkProvider(), + const adapter = new SmartContractQueriesAdaptor({ abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + networkProvider: new MockNetworkProvider(), + }); + const controller = new SmartContractQueriesController({ + queryRunner: adapter, }); const response = new SmartContractQueryResponse({ diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts index 64155645b..afcf05216 100644 --- a/src/smartContractQueriesController.ts +++ b/src/smartContractQueriesController.ts @@ -21,14 +21,20 @@ interface ILegacyQuery { getEncodedArguments(): string[]; } +interface IQueryRunner { + abi?: IAbi; + networkProvider: INetworkProvider; + queryContract(query: SmartContractQuery): Promise; +} + export class SmartContractQueriesController { private readonly abi?: IAbi; - private readonly networkProvider: INetworkProvider; + private readonly queryRunner: IQueryRunner; private readonly legacyResultsParser: ResultsParser; - constructor(options: { abi?: IAbi; networkProvider: INetworkProvider }) { - this.abi = options.abi; - this.networkProvider = options.networkProvider; + constructor(options: { queryRunner: IQueryRunner }) { + this.abi = options.queryRunner.abi; + this.queryRunner = options.queryRunner; this.legacyResultsParser = new ResultsParser(); } @@ -92,22 +98,7 @@ export class SmartContractQueriesController { } async runQuery(query: SmartContractQuery): Promise { - const legacyQuery: ILegacyQuery = { - address: Address.fromBech32(query.contract), - caller: query.caller ? Address.fromBech32(query.caller) : undefined, - func: query.function, - value: query.value, - getEncodedArguments: () => query.arguments.map((arg) => Buffer.from(arg).toString("hex")), - }; - - const legacyQueryResponse = await this.networkProvider.queryContract(legacyQuery); - const queryResponse = new SmartContractQueryResponse({ - function: query.function, - returnCode: legacyQueryResponse.returnCode.toString(), - returnMessage: legacyQueryResponse.returnMessage, - returnDataParts: legacyQueryResponse.getReturnDataParts(), - }); - + const queryResponse = await this.queryRunner.queryContract(query); return queryResponse; } From 127937cf4de7f65cf08aa978db228d573693a806 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 7 Mar 2024 10:10:04 +0200 Subject: [PATCH 128/275] refactoring --- src/adapters/index.ts | 1 + .../smartContractQueriesAdapter.ts} | 11 ++------ src/adaptors/index.ts | 1 - src/smartContractQueriesController.spec.ts | 28 +++++++++---------- src/smartContractQueriesController.ts | 6 ++-- 5 files changed, 19 insertions(+), 28 deletions(-) create mode 100644 src/adapters/index.ts rename src/{adaptors/smartContractQueriesAdaptor.ts => adapters/smartContractQueriesAdapter.ts} (82%) delete mode 100644 src/adaptors/index.ts diff --git a/src/adapters/index.ts b/src/adapters/index.ts new file mode 100644 index 000000000..e6409c29e --- /dev/null +++ b/src/adapters/index.ts @@ -0,0 +1 @@ +export * from "./smartContractQueriesAdapter"; diff --git a/src/adaptors/smartContractQueriesAdaptor.ts b/src/adapters/smartContractQueriesAdapter.ts similarity index 82% rename from src/adaptors/smartContractQueriesAdaptor.ts rename to src/adapters/smartContractQueriesAdapter.ts index b8c2151ff..61e52704f 100644 --- a/src/adaptors/smartContractQueriesAdaptor.ts +++ b/src/adapters/smartContractQueriesAdapter.ts @@ -2,16 +2,11 @@ import { Address } from "../address"; import { IAddress } from "../interface"; import { IContractQueryResponse } from "../interfaceOfNetwork"; import { SmartContractQuery, SmartContractQueryResponse } from "../smartContractQuery"; -import { ContractFunction, EndpointDefinition } from "../smartcontracts"; interface INetworkProvider { queryContract(query: ILegacyQuery): Promise; } -interface IAbi { - getEndpoint(name: string | ContractFunction): EndpointDefinition; -} - interface ILegacyQuery { address: IAddress; caller?: IAddress; @@ -20,12 +15,10 @@ interface ILegacyQuery { getEncodedArguments(): string[]; } -export class SmartContractQueriesAdaptor { - abi?: IAbi; +export class SmartContractQueriesAdapter { networkProvider: INetworkProvider; - constructor(options: { abi?: IAbi; networkProvider: INetworkProvider }) { - this.abi = options.abi; + constructor(options: { networkProvider: INetworkProvider }) { this.networkProvider = options.networkProvider; } diff --git a/src/adaptors/index.ts b/src/adaptors/index.ts deleted file mode 100644 index 9fa9c9a34..000000000 --- a/src/adaptors/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./smartContractQueriesAdaptor"; diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index 915c0c647..36d71a33d 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -6,12 +6,12 @@ import { SmartContractQueryResponse } from "./smartContractQuery"; import { AbiRegistry, BigUIntValue, BooleanValue, BytesValue, Tuple, U16Value, U64Value } from "./smartcontracts"; import { bigIntToBuffer } from "./smartcontracts/codec/utils"; import { MockNetworkProvider, loadAbiRegistry } from "./testutils"; -import { SmartContractQueriesAdaptor } from "./adaptors/smartContractQueriesAdaptor"; +import { SmartContractQueriesAdapter } from "./adapters/smartContractQueriesAdapter"; describe("test smart contract queries controller", () => { describe("createQuery", () => { it("works without ABI, when arguments are buffers", function () { - const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -28,7 +28,7 @@ describe("test smart contract queries controller", () => { }); it("works without ABI, when arguments are typed values", function () { - const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -45,7 +45,7 @@ describe("test smart contract queries controller", () => { }); it("fails without ABI, when arguments aren't buffers, nor typed values", function () { - const adapter = new SmartContractQueriesAdaptor({ networkProvider: new MockNetworkProvider() }); + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -60,11 +60,11 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments are native JS objects", async function () { - const adapter = new SmartContractQueriesAdaptor({ - abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), queryRunner: adapter, }); @@ -80,11 +80,11 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments typed values", async function () { - const adapter = new SmartContractQueriesAdaptor({ - abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), queryRunner: adapter, }); @@ -123,11 +123,11 @@ describe("test smart contract queries controller", () => { ], }); - const adapter = new SmartContractQueriesAdaptor({ - abi: abi, + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ + abi: abi, queryRunner: adapter, }); @@ -162,7 +162,7 @@ describe("test smart contract queries controller", () => { describe("runQuery", () => { it("calls queryContract on the network provider", async function () { const networkProvider = new MockNetworkProvider(); - const adapter = new SmartContractQueriesAdaptor({ + const adapter = new SmartContractQueriesAdapter({ networkProvider: networkProvider, }); const controller = new SmartContractQueriesController({ @@ -192,7 +192,7 @@ describe("test smart contract queries controller", () => { describe("parseQueryResponse", () => { it("works without ABI", function () { - const adapter = new SmartContractQueriesAdaptor({ + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ @@ -212,11 +212,11 @@ describe("test smart contract queries controller", () => { }); it("works with ABI", async function () { - const adapter = new SmartContractQueriesAdaptor({ - abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), + const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ + abi: await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"), queryRunner: adapter, }); diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts index afcf05216..aceb1b570 100644 --- a/src/smartContractQueriesController.ts +++ b/src/smartContractQueriesController.ts @@ -1,4 +1,3 @@ -import { Address } from "./address"; import { Err } from "./errors"; import { IAddress } from "./interface"; import { IContractQueryResponse } from "./interfaceOfNetwork"; @@ -22,7 +21,6 @@ interface ILegacyQuery { } interface IQueryRunner { - abi?: IAbi; networkProvider: INetworkProvider; queryContract(query: SmartContractQuery): Promise; } @@ -32,8 +30,8 @@ export class SmartContractQueriesController { private readonly queryRunner: IQueryRunner; private readonly legacyResultsParser: ResultsParser; - constructor(options: { queryRunner: IQueryRunner }) { - this.abi = options.queryRunner.abi; + constructor(options: { abi?: IAbi; queryRunner: IQueryRunner }) { + this.abi = options.abi; this.queryRunner = options.queryRunner; this.legacyResultsParser = new ResultsParser(); } From f921d342f6eb9b105d8709fb900ad760c26290a2 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 7 Mar 2024 11:32:05 +0200 Subject: [PATCH 129/275] renamings --- src/adapters/index.ts | 2 +- ...ueriesAdapter.ts => queryRunnerAdapter.ts} | 12 +++++------ src/smartContractQueriesController.spec.ts | 20 +++++++++---------- src/smartContractQueriesController.ts | 18 ++--------------- 4 files changed, 19 insertions(+), 33 deletions(-) rename src/adapters/{smartContractQueriesAdapter.ts => queryRunnerAdapter.ts} (80%) diff --git a/src/adapters/index.ts b/src/adapters/index.ts index e6409c29e..e73a1b2d8 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1 +1 @@ -export * from "./smartContractQueriesAdapter"; +export * from "./queryRunnerAdapter"; diff --git a/src/adapters/smartContractQueriesAdapter.ts b/src/adapters/queryRunnerAdapter.ts similarity index 80% rename from src/adapters/smartContractQueriesAdapter.ts rename to src/adapters/queryRunnerAdapter.ts index 61e52704f..b78840c77 100644 --- a/src/adapters/smartContractQueriesAdapter.ts +++ b/src/adapters/queryRunnerAdapter.ts @@ -4,10 +4,10 @@ import { IContractQueryResponse } from "../interfaceOfNetwork"; import { SmartContractQuery, SmartContractQueryResponse } from "../smartContractQuery"; interface INetworkProvider { - queryContract(query: ILegacyQuery): Promise; + queryContract(query: IQuery): Promise; } -interface ILegacyQuery { +interface IQuery { address: IAddress; caller?: IAddress; func: { toString(): string }; @@ -15,15 +15,15 @@ interface ILegacyQuery { getEncodedArguments(): string[]; } -export class SmartContractQueriesAdapter { - networkProvider: INetworkProvider; +export class QueryRunnerAdapter { + private readonly networkProvider: INetworkProvider; constructor(options: { networkProvider: INetworkProvider }) { this.networkProvider = options.networkProvider; } - async queryContract(query: SmartContractQuery): Promise { - const legacyQuery: ILegacyQuery = { + async runQuery(query: SmartContractQuery): Promise { + const legacyQuery: IQuery = { address: Address.fromBech32(query.contract), caller: query.caller ? Address.fromBech32(query.caller) : undefined, func: query.function, diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index 36d71a33d..b1e6861c2 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -6,12 +6,12 @@ import { SmartContractQueryResponse } from "./smartContractQuery"; import { AbiRegistry, BigUIntValue, BooleanValue, BytesValue, Tuple, U16Value, U64Value } from "./smartcontracts"; import { bigIntToBuffer } from "./smartcontracts/codec/utils"; import { MockNetworkProvider, loadAbiRegistry } from "./testutils"; -import { SmartContractQueriesAdapter } from "./adapters/smartContractQueriesAdapter"; +import { QueryRunnerAdapter } from "./adapters/queryRunnerAdapter"; describe("test smart contract queries controller", () => { describe("createQuery", () => { it("works without ABI, when arguments are buffers", function () { - const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -28,7 +28,7 @@ describe("test smart contract queries controller", () => { }); it("works without ABI, when arguments are typed values", function () { - const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -45,7 +45,7 @@ describe("test smart contract queries controller", () => { }); it("fails without ABI, when arguments aren't buffers, nor typed values", function () { - const adapter = new SmartContractQueriesAdapter({ networkProvider: new MockNetworkProvider() }); + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider() }); const controller = new SmartContractQueriesController({ queryRunner: adapter, }); @@ -60,7 +60,7 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments are native JS objects", async function () { - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ @@ -80,7 +80,7 @@ describe("test smart contract queries controller", () => { }); it("works with ABI, when arguments typed values", async function () { - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ @@ -123,7 +123,7 @@ describe("test smart contract queries controller", () => { ], }); - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ @@ -162,7 +162,7 @@ describe("test smart contract queries controller", () => { describe("runQuery", () => { it("calls queryContract on the network provider", async function () { const networkProvider = new MockNetworkProvider(); - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: networkProvider, }); const controller = new SmartContractQueriesController({ @@ -192,7 +192,7 @@ describe("test smart contract queries controller", () => { describe("parseQueryResponse", () => { it("works without ABI", function () { - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ @@ -212,7 +212,7 @@ describe("test smart contract queries controller", () => { }); it("works with ABI", async function () { - const adapter = new SmartContractQueriesAdapter({ + const adapter = new QueryRunnerAdapter({ networkProvider: new MockNetworkProvider(), }); const controller = new SmartContractQueriesController({ diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts index aceb1b570..b676b09c4 100644 --- a/src/smartContractQueriesController.ts +++ b/src/smartContractQueriesController.ts @@ -1,5 +1,4 @@ import { Err } from "./errors"; -import { IAddress } from "./interface"; import { IContractQueryResponse } from "./interfaceOfNetwork"; import { SmartContractQuery, SmartContractQueryResponse } from "./smartContractQuery"; import { ArgSerializer, ContractFunction, EndpointDefinition, NativeSerializer, ResultsParser } from "./smartcontracts"; @@ -8,21 +7,8 @@ interface IAbi { getEndpoint(name: string | ContractFunction): EndpointDefinition; } -interface INetworkProvider { - queryContract(query: ILegacyQuery): Promise; -} - -interface ILegacyQuery { - address: IAddress; - caller?: IAddress; - func: { toString(): string }; - value?: { toString(): string }; - getEncodedArguments(): string[]; -} - interface IQueryRunner { - networkProvider: INetworkProvider; - queryContract(query: SmartContractQuery): Promise; + runQuery(query: SmartContractQuery): Promise; } export class SmartContractQueriesController { @@ -96,7 +82,7 @@ export class SmartContractQueriesController { } async runQuery(query: SmartContractQuery): Promise { - const queryResponse = await this.queryRunner.queryContract(query); + const queryResponse = await this.queryRunner.runQuery(query); return queryResponse; } From f0cbe0a639e29b68c4741bece8d73c534815951d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 8 Mar 2024 13:30:19 +0200 Subject: [PATCH 130/275] use smart contract query controller in localnet tests --- src/adapters/queryRunnerAdapter.ts | 14 +- .../interaction.local.net.spec.ts | 188 +++++++++--------- .../smartContract.local.net.spec.ts | 94 +++++---- 3 files changed, 152 insertions(+), 144 deletions(-) diff --git a/src/adapters/queryRunnerAdapter.ts b/src/adapters/queryRunnerAdapter.ts index b78840c77..db673de4c 100644 --- a/src/adapters/queryRunnerAdapter.ts +++ b/src/adapters/queryRunnerAdapter.ts @@ -23,7 +23,7 @@ export class QueryRunnerAdapter { } async runQuery(query: SmartContractQuery): Promise { - const legacyQuery: IQuery = { + const adaptedQuery: IQuery = { address: Address.fromBech32(query.contract), caller: query.caller ? Address.fromBech32(query.caller) : undefined, func: query.function, @@ -31,14 +31,12 @@ export class QueryRunnerAdapter { getEncodedArguments: () => query.arguments.map((arg) => Buffer.from(arg).toString("hex")), }; - const legacyQueryResponse = await this.networkProvider.queryContract(legacyQuery); - const queryResponse = new SmartContractQueryResponse({ + const adaptedQueryResponse = await this.networkProvider.queryContract(adaptedQuery); + return new SmartContractQueryResponse({ function: query.function, - returnCode: legacyQueryResponse.returnCode.toString(), - returnMessage: legacyQueryResponse.returnMessage, - returnDataParts: legacyQueryResponse.getReturnDataParts(), + returnCode: adaptedQueryResponse.returnCode.toString(), + returnMessage: adaptedQueryResponse.returnMessage, + returnDataParts: adaptedQueryResponse.getReturnDataParts(), }); - - return queryResponse; } } diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 7fa0ff41c..6650e9075 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -11,13 +11,19 @@ import { TransactionsFactoryConfig } from "../transactionsFactories/transactions import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TokenComputer } from "../tokens"; import { promises } from "fs"; +import { ResultsParser } from "./resultsParser"; +import { TransactionWatcher } from "../transactionWatcher"; +import { SmartContractQueriesController } from "../smartContractQueriesController"; +import { QueryRunnerAdapter } from "../adapters/queryRunnerAdapter"; describe("test smart contract interactor", function () { let provider = createLocalnetProvider(); let alice: TestWallet; + let resultsParser: ResultsParser; before(async function () { ({ alice } = await loadTestWallets()); + resultsParser = new ResultsParser(); }); it("should interact with 'answer' (local testnet)", async function () { @@ -111,28 +117,33 @@ describe("test smart contract interactor", function () { const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); alice.account.incrementNonce(); - let contract = new SmartContract({ abi: abiRegistry, address: contractAddress }); - let controller = new ContractController(provider); + const transactionCompletionAwaiter = new TransactionWatcher({ + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, + }); - let { - bundle: { returnCode }, - } = await controller.deploy(deployTransaction); - assert.isTrue(returnCode.isSuccess()); + const deployTxHash = await provider.sendTransaction(deployTransaction); + let transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(deployTxHash); + const untypedBundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(untypedBundle.returnCode.isSuccess()); - const interaction = ( - contract.methods - .getUltimateAnswer() - .withGasLimit(3000000) - .withChainID(network.ChainID) - .withSender(alice.address) - ); + const queryRunner = new QueryRunnerAdapter({ networkProvider: provider }); + const queryController = new SmartContractQueriesController({ abi: abiRegistry, queryRunner: queryRunner }); - // Query - let queryResponseBundle = await controller.query(interaction); - assert.lengthOf(queryResponseBundle.values, 1); - assert.deepEqual(queryResponseBundle.firstValue!.valueOf(), new BigNumber(42)); - assert.isTrue(queryResponseBundle.returnCode.equals(ReturnCode.Ok)); + const query = queryController.createQuery({ + contract: contractAddress.bech32(), + caller: alice.address.bech32(), + function: "getUltimateAnswer", + arguments: [], + }); + + const queryResponse = await queryController.runQuery(query); + const parsed = queryController.parseQueryResponse(queryResponse); + assert.lengthOf(parsed, 1); + assert.deepEqual(parsed[0].valueOf(), new BigNumber(42)); + // Query let transaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, @@ -140,14 +151,12 @@ describe("test smart contract interactor", function () { gasLimit: 3000000n, }); transaction.nonce = BigInt(alice.account.nonce.valueOf()); - transaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(transaction)), ); alice.account.incrementNonce(); - // await signTransaction({ transaction: transaction, wallet: alice }); await provider.sendTransaction(transaction); // Execute, and wait for execution @@ -158,18 +167,22 @@ describe("test smart contract interactor", function () { gasLimit: 3000000n, }); transaction.nonce = BigInt(alice.account.nonce.valueOf()); - transaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(transaction)), ); alice.account.incrementNonce(); - let { bundle: executionResultsBundle } = await controller.execute(interaction, transaction); + const executeTxHash = await provider.sendTransaction(transaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(executeTxHash); + const typedBundle = resultsParser.parseOutcome( + transactionOnNetwork, + abiRegistry.getEndpoint("getUltimateAnswer"), + ); - assert.lengthOf(executionResultsBundle.values, 1); - assert.deepEqual(executionResultsBundle.firstValue!.valueOf(), new BigNumber(42)); - assert.isTrue(executionResultsBundle.returnCode.equals(ReturnCode.Ok)); + assert.lengthOf(typedBundle.values, 1); + assert.deepEqual(typedBundle.firstValue!.valueOf(), new BigNumber(42)); + assert.isTrue(typedBundle.returnCode.equals(ReturnCode.Ok)); }); it("should interact with 'counter' (local testnet)", async function () { @@ -264,24 +277,19 @@ describe("test smart contract interactor", function () { const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); alice.account.incrementNonce(); - let contract = new SmartContract({ abi: abiRegistry, address: contractAddress }); - let controller = new ContractController(provider); + const transactionCompletionAwaiter = new TransactionWatcher({ + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, + }); - let { - bundle: { returnCode }, - } = await controller.deploy(deployTransaction); - assert.isTrue(returnCode.isSuccess()); + const deployTxHash = await provider.sendTransaction(deployTransaction); + let transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(deployTxHash); + const untypedBundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(untypedBundle.returnCode.isSuccess()); - let getInteraction = contract.methods.get(); - - let incrementInteraction = (contract.methods.increment()) - .withGasLimit(3000000) - .withChainID(network.ChainID) - .withSender(alice.address); - let decrementInteraction = (contract.methods.decrement()) - .withGasLimit(3000000) - .withChainID(network.ChainID) - .withSender(alice.address); + const queryRunner = new QueryRunnerAdapter({ networkProvider: provider }); + const queryController = new SmartContractQueriesController({ abi: abiRegistry, queryRunner: queryRunner }); let incrementTransaction = factory.createTransactionForExecute({ sender: alice.address, @@ -298,13 +306,19 @@ describe("test smart contract interactor", function () { alice.account.incrementNonce(); // Query "get()" - let { firstValue: counterValue } = await controller.query(getInteraction); - assert.deepEqual(counterValue!.valueOf(), new BigNumber(1)); + const query = queryController.createQuery({ + contract: contractAddress.bech32(), + function: "get", + arguments: [], + }); + const queryResponse = await queryController.runQuery(query); + const parsed = queryController.parseQueryResponse(queryResponse); + assert.deepEqual(parsed[0].valueOf(), new BigNumber(1)); - let { - bundle: { firstValue: valueAfterIncrement }, - } = await controller.execute(incrementInteraction, incrementTransaction); - assert.deepEqual(valueAfterIncrement!.valueOf(), new BigNumber(2)); + const incrementTxHash = await provider.sendTransaction(incrementTransaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(incrementTxHash); + let typedBundle = resultsParser.parseOutcome(transactionOnNetwork, abiRegistry.getEndpoint("increment")); + assert.deepEqual(typedBundle.firstValue!.valueOf(), new BigNumber(2)); let decrementTransaction = factory.createTransactionForExecute({ sender: alice.address, @@ -313,7 +327,6 @@ describe("test smart contract interactor", function () { gasLimit: 3000000n, }); decrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - decrementTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(decrementTransaction)), ); @@ -323,15 +336,13 @@ describe("test smart contract interactor", function () { await provider.sendTransaction(decrementTransaction); decrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - decrementTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(decrementTransaction)), ); - let { - bundle: { firstValue: valueAfterDecrement }, - } = await controller.execute(decrementInteraction, decrementTransaction); - assert.deepEqual(valueAfterDecrement!.valueOf(), new BigNumber(0)); + const decrementTxHash = await provider.sendTransaction(decrementTransaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(decrementTxHash); + typedBundle = resultsParser.parseOutcome(transactionOnNetwork, abiRegistry.getEndpoint("decrement")); }); it("should interact with 'lottery-esdt' (local testnet)", async function () { @@ -435,8 +446,6 @@ describe("test smart contract interactor", function () { this.timeout(140000); let abiRegistry = await loadAbiRegistry("src/testdata/lottery-esdt.abi.json"); - let contract = new SmartContract({ abi: abiRegistry }); - let controller = new ContractController(provider); let network = await provider.getNetworkConfig(); await alice.sync(provider); @@ -466,34 +475,16 @@ describe("test smart contract interactor", function () { const contractAddress = SmartContract.computeAddress(alice.address, alice.account.nonce); alice.account.incrementNonce(); - let { - bundle: { returnCode }, - } = await controller.deploy(deployTransaction); - assert.isTrue(returnCode.isSuccess()); - - let startInteraction = ( - contract.methods - .start(["lucky", "EGLD", 1, null, null, 1, null, null]) - .withGasLimit(30000000) - .withChainID(network.ChainID) - .withSender(alice.address) - ); - - let lotteryStatusInteraction = ( - contract.methods - .status(["lucky"]) - .withGasLimit(5000000) - .withChainID(network.ChainID) - .withSender(alice.address) - ); + const transactionCompletionAwaiter = new TransactionWatcher({ + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, + }); - let getLotteryInfoInteraction = ( - contract.methods - .getLotteryInfo(["lucky"]) - .withGasLimit(5000000) - .withChainID(network.ChainID) - .withSender(alice.address) - ); + const deployTxHash = await provider.sendTransaction(deployTransaction); + let transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(deployTxHash); + const untypedBundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + assert.isTrue(untypedBundle.returnCode.isSuccess()); // start() let startTransaction = factory.createTransactionForExecute({ @@ -504,16 +495,17 @@ describe("test smart contract interactor", function () { gasLimit: 30000000n, }); startTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - startTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(startTransaction)), ); alice.account.incrementNonce(); - let { bundle: bundleStart } = await controller.execute(startInteraction, startTransaction); - assert.isTrue(bundleStart.returnCode.equals(ReturnCode.Ok)); - assert.lengthOf(bundleStart.values, 0); + const startTxHash = await provider.sendTransaction(startTransaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(startTxHash); + let typedBundle = resultsParser.parseOutcome(transactionOnNetwork, abiRegistry.getEndpoint("start")); + assert.equal(typedBundle.returnCode.valueOf(), "ok"); + assert.lengthOf(typedBundle.values, 0); // status() let lotteryStatusTransaction = factory.createTransactionForExecute({ @@ -524,19 +516,20 @@ describe("test smart contract interactor", function () { gasLimit: 5000000n, }); lotteryStatusTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - lotteryStatusTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(lotteryStatusTransaction)), ); alice.account.incrementNonce(); - let { bundle: bundleStatus } = await controller.execute(lotteryStatusInteraction, lotteryStatusTransaction); - assert.isTrue(bundleStatus.returnCode.equals(ReturnCode.Ok)); - assert.lengthOf(bundleStatus.values, 1); - assert.equal(bundleStatus.firstValue!.valueOf().name, "Running"); + const statusTxHash = await provider.sendTransaction(lotteryStatusTransaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(statusTxHash); + typedBundle = resultsParser.parseOutcome(transactionOnNetwork, abiRegistry.getEndpoint("status")); + assert.equal(typedBundle.returnCode.valueOf(), "ok"); + assert.lengthOf(typedBundle.values, 1); + assert.equal(typedBundle.firstValue!.valueOf().name, "Running"); - // lotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) + // getlotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) let lotteryInfoTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, @@ -545,19 +538,20 @@ describe("test smart contract interactor", function () { gasLimit: 5000000n, }); lotteryInfoTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - lotteryInfoTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(lotteryInfoTransaction)), ); alice.account.incrementNonce(); - let { bundle: bundleLotteryInfo } = await controller.execute(getLotteryInfoInteraction, lotteryInfoTransaction); - assert.isTrue(bundleLotteryInfo.returnCode.equals(ReturnCode.Ok)); - assert.lengthOf(bundleLotteryInfo.values, 1); + const infoTxHash = await provider.sendTransaction(lotteryInfoTransaction); + transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(infoTxHash); + typedBundle = resultsParser.parseOutcome(transactionOnNetwork, abiRegistry.getEndpoint("getLotteryInfo")); + assert.equal(typedBundle.returnCode.valueOf(), "ok"); + assert.lengthOf(typedBundle.values, 1); // Ignore "deadline" field in our test - let info = bundleLotteryInfo.firstValue!.valueOf(); + let info = typedBundle.firstValue!.valueOf(); delete info.deadline; assert.deepEqual(info, { diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index d05500323..d2e8c3aa2 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -15,6 +15,8 @@ import { SmartContractTransactionsFactory } from "../transactionsFactories/smart import { TokenComputer } from "../tokens"; import { promises } from "fs"; import { TransactionComputer } from "../transaction"; +import { QueryRunnerAdapter } from "../adapters/queryRunnerAdapter"; +import { SmartContractQueriesController } from "../smartContractQueriesController"; describe("test on local testnet", function () { let alice: TestWallet, bob: TestWallet, carol: TestWallet; @@ -325,10 +327,17 @@ describe("test on local testnet", function () { await watcher.awaitCompleted(secondScCallHash); // Check counter - const contract = new SmartContract({ address: contractAddress }); - let query = contract.createQuery({ func: new ContractFunction("get") }); - let queryResponse = await provider.queryContract(query); - assert.equal(3, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + const queryRunner = new QueryRunnerAdapter({ networkProvider: provider }); + const smartContractQueriesController = new SmartContractQueriesController({ queryRunner: queryRunner }); + + const query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "get", + arguments: [], + }); + + const queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(3, decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0]))); }); it("erc20: should deploy, call and query contract", async function () { @@ -438,7 +447,6 @@ describe("test on local testnet", function () { args: [new U32Value(10000)], }); deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); - const transactionComputer = new TransactionComputer(); deployTransaction.signature = await alice.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(deployTransaction)), @@ -484,36 +492,41 @@ describe("test on local testnet", function () { await watcher.awaitCompleted(mintBobTxHash); await watcher.awaitCompleted(mintCarolTxHash); - const contract = new SmartContract({ address: contractAddress }); - // Query state, do some assertions - let query = contract.createQuery({ func: new ContractFunction("totalSupply") }); - let queryResponse = await provider.queryContract(query); - assert.equal(10000, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + const queryRunner = new QueryRunnerAdapter({ networkProvider: provider }); + const smartContractQueriesController = new SmartContractQueriesController({ queryRunner: queryRunner }); - query = contract.createQuery({ - func: new ContractFunction("balanceOf"), - args: [new AddressValue(alice.address)], + let query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "totalSupply", + arguments: [], }); - queryResponse = await provider.queryContract(query); - - assert.equal(7500, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + let queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(10000, decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0]))); - query = contract.createQuery({ - func: new ContractFunction("balanceOf"), - args: [new AddressValue(bob.address)], + query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "balanceOf", + arguments: [new AddressValue(alice.address)], }); - queryResponse = await provider.queryContract(query); + queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(7500, decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0]))); - assert.equal(1000, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); - - query = contract.createQuery({ - func: new ContractFunction("balanceOf"), - args: [new AddressValue(carol.address)], + query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "balanceOf", + arguments: [new AddressValue(bob.address)], }); - queryResponse = await provider.queryContract(query); + queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(1000, decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0]))); - assert.equal(1500, decodeUnsignedNumber(queryResponse.getReturnDataParts()[0])); + query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "balanceOf", + arguments: [new AddressValue(carol.address)], + }); + queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(1500, decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0]))); }); it("lottery: should deploy, call and query contract", async function () { @@ -661,21 +674,24 @@ describe("test on local testnet", function () { bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); assert.isTrue(bundle.returnCode.isSuccess()); - const contract = new SmartContract({ address: contractAddress }); - // Query state, do some assertions - let query = contract.createQuery({ - func: new ContractFunction("status"), - args: [BytesValue.fromUTF8("lucky")], + const queryRunner = new QueryRunnerAdapter({ networkProvider: provider }); + const smartContractQueriesController = new SmartContractQueriesController({ queryRunner: queryRunner }); + + let query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "status", + arguments: [BytesValue.fromUTF8("lucky")], }); - let queryResponse = await provider.queryContract(query); - assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 1); + let queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0])), 1); - query = contract.createQuery({ - func: new ContractFunction("status"), - args: [BytesValue.fromUTF8("missingLottery")], + query = smartContractQueriesController.createQuery({ + contract: contractAddress.bech32(), + function: "status", + arguments: [BytesValue.fromUTF8("missingLottery")], }); - queryResponse = await provider.queryContract(query); - assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0); + queryResponse = await smartContractQueriesController.runQuery(query); + assert.equal(decodeUnsignedNumber(Buffer.from(queryResponse.returnDataParts[0])), 0); }); }); From 16c81fd9d337db8605a176d1a1314ed6171785be Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Sun, 10 Mar 2024 22:10:29 +0200 Subject: [PATCH 131/275] Merge TransactionNext into existing Transaction. --- src/transaction.ts | 1223 ++++++++--------- src/transactionNext.spec.ts | 4 +- .../relayedTransactionsFactory.ts | 2 +- 3 files changed, 608 insertions(+), 621 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 393037300..9c3173495 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,10 +1,22 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; -import { Compatibility } from "./compatibility"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; import * as errors from "./errors"; import { Hash } from "./hash"; -import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, IPlainTransactionObject, ISignature, ITransactionNext, ITransactionOptions, ITransactionPayload, ITransactionValue, ITransactionVersion } from "./interface"; +import { + IAddress, + IChainID, + IGasLimit, + IGasPrice, + INonce, + IPlainTransactionObject, + ISignature, + ITransactionNext, + ITransactionOptions, + ITransactionPayload, + ITransactionValue, + ITransactionVersion, +} from "./interface"; import { INetworkConfig } from "./interfaceOfNetwork"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; @@ -19,647 +31,624 @@ const TRANSACTION_HASH_LENGTH = 32; * An abstraction for creating, signing and broadcasting transactions. */ export class Transaction { - /** - * The nonce of the transaction (the account sequence number of the sender). - */ - private nonce: INonce; - - /** - * The value to transfer. - */ - private value: ITransactionValue; - - /** - * The address of the sender. - */ - private sender: IAddress; - - /** - * The address of the receiver. - */ - private readonly receiver: IAddress; - - /** - * The username of the sender. - */ - private senderUsername: string; - - /** - * The username of the receiver. - */ - private receiverUsername: string; - - /** - * The gas price to be used. - */ - private gasPrice: IGasPrice; - - /** - * The maximum amount of gas to be consumed when processing the transaction. - */ - private gasLimit: IGasLimit; - - /** - * The payload of the transaction. - */ - private readonly data: ITransactionPayload; - - /** - * The chain ID of the Network (e.g. "1" for Mainnet). - */ - private chainID: IChainID; - - /** - * The version, required by the Network in order to correctly interpret the contents of the transaction. - * @deprecated Use getVersion() and setVersion() instead. - */ - version: TransactionVersion; - - /** - * The options field, useful for describing different settings available for transactions - * @deprecated Use getOptions() and setOptions() instead. - */ - options: TransactionOptions; - - /** - * The address of the guardian. - */ - private guardian: IAddress; - - /** - * The signature. - */ - private signature: Buffer; - - /** - * The signature of the guardian. - */ - private guardianSignature: Buffer; - - /** - * The transaction hash, also used as a transaction identifier. - */ - private hash: TransactionHash; - - /** - * Creates a new Transaction object. - */ - public constructor({ - nonce, - value, - sender, - receiver, - senderUsername, - receiverUsername, - gasPrice, - gasLimit, - data, - chainID, - version, - options, - guardian, - }: { - nonce?: INonce; - value?: ITransactionValue; - sender: IAddress; - receiver: IAddress; - senderUsername?: string; - receiverUsername?: string; - gasPrice?: IGasPrice; - gasLimit: IGasLimit; - data?: ITransactionPayload; - chainID: IChainID; - version?: ITransactionVersion; - options?: ITransactionOptions; - guardian?: IAddress; - }) { - this.nonce = nonce || 0; - this.value = value ? new BigNumber(value.toString()).toFixed(0) : 0; - this.sender = sender; - this.receiver = receiver; - this.senderUsername = senderUsername || ""; - this.receiverUsername = receiverUsername || ""; - this.gasPrice = gasPrice || TRANSACTION_MIN_GAS_PRICE; - this.gasLimit = gasLimit; - this.data = data || new TransactionPayload(); - this.chainID = chainID; - this.version = version ? new TransactionVersion(version.valueOf()) : TransactionVersion.withDefaultVersion(); - this.options = options ? new TransactionOptions(options.valueOf()) : TransactionOptions.withDefaultOptions(); - this.guardian = guardian || Address.empty(); - - this.signature = Buffer.from([]); - this.guardianSignature = Buffer.from([]); - this.hash = TransactionHash.empty(); - } - - getNonce(): INonce { - return this.nonce; - } - - /** - * Sets the account sequence number of the sender. Must be done prior signing. - */ - setNonce(nonce: INonce) { - this.nonce = nonce; - } - - getValue(): ITransactionValue { - return this.value; - } - - setValue(value: ITransactionValue) { - this.value = value; - } - - getSender(): IAddress { - return this.sender; - } - - setSender(sender: IAddress) { - this.sender = sender; - } - - getReceiver(): IAddress { - return this.receiver; - } - - getSenderUsername(): string { - return this.senderUsername; - } - - setSenderUsername(senderUsername: string) { - this.senderUsername = senderUsername; - } - - getReceiverUsername(): string { - return this.receiverUsername; - } - - setReceiverUsername(receiverUsername: string) { - this.receiverUsername = receiverUsername; - } - - getGuardian(): IAddress { - return this.guardian; - } - - getGasPrice(): IGasPrice { - return this.gasPrice; - } - - setGasPrice(gasPrice: IGasPrice) { - this.gasPrice = gasPrice; - } - - getGasLimit(): IGasLimit { - return this.gasLimit; - } - - setGasLimit(gasLimit: IGasLimit) { - this.gasLimit = gasLimit; - } - - getData(): ITransactionPayload { - return this.data; - } - - getChainID(): IChainID { - return this.chainID; - } - - setChainID(chainID: IChainID) { - this.chainID = chainID; - } - - getVersion(): TransactionVersion { - return this.version; - } - - setVersion(version: ITransactionVersion) { - this.version = new TransactionVersion(version.valueOf()); - } - - getOptions(): TransactionOptions { - // Make sure that "sdk-core v12" is compatible (for a while) with (older) libraries that were previously setting the (soon to be private) "options" field directly, - // instead of using the "setOptions()" method. - const options = new TransactionOptions(this.options.valueOf()); - return options; - } - - setOptions(options: ITransactionOptions) { - this.options = new TransactionOptions(options.valueOf()); - } - - getSignature(): Buffer { - return this.signature; - } - - getGuardianSignature(): Buffer { - return this.guardianSignature; - } - - setGuardian(guardian: IAddress) { - this.guardian = guardian; - } - - getHash(): TransactionHash { - guardNotEmpty(this.hash, "hash"); - return this.hash; - } - - /** - * Serializes a transaction to a sequence of bytes, ready to be signed. - * This function is called internally by signers. - */ - serializeForSigning(): Buffer { - // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash - let plain = this.toPlainObject(); - // Make sure we never sign the transaction with another signature set up (useful when using the same method for verification) - if (plain.signature) { - delete plain.signature; - } - - if (plain.guardianSignature) { - delete plain.guardianSignature; - } - - if (!plain.guardian) { - delete plain.guardian - } - - let serialized = JSON.stringify(plain); - - return Buffer.from(serialized); - } - - /** - * Checks the integrity of the guarded transaction - */ - isGuardedTransaction(): boolean { - const hasGuardian = this.guardian.bech32().length > 0; - const hasGuardianSignature = this.guardianSignature.length > 0; - return this.getOptions().isWithGuardian() && hasGuardian && hasGuardianSignature; - } - - /** - * Converts the transaction object into a ready-to-serialize, plain JavaScript object. - * This function is called internally within the signing procedure. - */ - toPlainObject(): IPlainTransactionObject { - const plainObject = { - nonce: this.nonce.valueOf(), - value: this.value.toString(), - receiver: this.receiver.bech32(), - sender: this.sender.bech32(), - senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined, - receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined, - gasPrice: this.gasPrice.valueOf(), - gasLimit: this.gasLimit.valueOf(), - data: this.data.length() == 0 ? undefined : this.data.encoded(), - chainID: this.chainID.valueOf(), - version: this.getVersion().valueOf(), - options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(), - guardian: this.guardian?.bech32() ? (this.guardian.bech32() == "" ? undefined : this.guardian.bech32()) : undefined, - signature: this.signature.toString("hex") ? this.signature.toString("hex") : undefined, - guardianSignature: this.guardianSignature.toString("hex") ? this.guardianSignature.toString("hex") : undefined, - }; - - Compatibility.guardAddressIsSetAndNonZero(new Address(plainObject.sender), "'sender' of transaction", "pass the actual sender to the Transaction constructor") - - return plainObject; - } - - /** - * Converts a plain object transaction into a Transaction Object. - * - * @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject() - */ - static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction { - const tx = new Transaction({ - nonce: Number(plainObjectTransaction.nonce), - value: new BigNumber(plainObjectTransaction.value).toFixed(0), - receiver: Address.fromString(plainObjectTransaction.receiver), - receiverUsername: plainObjectTransaction.receiverUsername ? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString() : undefined, - sender: Address.fromString(plainObjectTransaction.sender), - senderUsername: plainObjectTransaction.senderUsername ? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString() : undefined, - guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined, - gasPrice: Number(plainObjectTransaction.gasPrice), - gasLimit: Number(plainObjectTransaction.gasLimit), - data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")), - chainID: String(plainObjectTransaction.chainID), - version: new TransactionVersion(plainObjectTransaction.version), - options: plainObjectTransaction.options != null ? new TransactionOptions(plainObjectTransaction.options) : undefined - }); - - if (plainObjectTransaction.signature) { - tx.applySignature( - new Signature(plainObjectTransaction.signature), - ); - } - - if (plainObjectTransaction.guardianSignature) { - tx.applyGuardianSignature( - new Signature(plainObjectTransaction.guardianSignature) - ); - } - - return tx; - } - - /** - * Applies the signature on the transaction. - * - * @param signature The signature, as computed by a signer. - */ - applySignature(signature: ISignature | Uint8Array) { - this.signature = interpretSignatureAsBuffer(signature); - this.hash = TransactionHash.compute(this); - } - - /** - * Applies the guardian signature on the transaction. - * - * @param guardianSignature The signature, as computed by a signer. - */ - applyGuardianSignature(guardianSignature: ISignature | Uint8Array) { - this.guardianSignature = interpretSignatureAsBuffer(guardianSignature); - this.hash = TransactionHash.compute(this); - } - - /** - * Converts a transaction to a ready-to-broadcast object. - * Called internally by the network provider. - */ - toSendable(): any { - return this.toPlainObject(); - } - - /** - * Computes the current transaction fee based on the {@link NetworkConfig} and transaction properties - * @param networkConfig {@link NetworkConfig} - */ - computeFee(networkConfig: INetworkConfig): BigNumber { - let moveBalanceGas = - networkConfig.MinGasLimit.valueOf() + - this.data.length() * networkConfig.GasPerDataByte.valueOf(); - if (moveBalanceGas > this.gasLimit.valueOf()) { - throw new errors.ErrNotEnoughGas(this.gasLimit.valueOf()); - } - - let gasPrice = new BigNumber(this.gasPrice.valueOf()); - let feeForMove = new BigNumber(moveBalanceGas).multipliedBy(gasPrice); - if (moveBalanceGas === this.gasLimit.valueOf()) { - return feeForMove; - } - - let diff = new BigNumber(this.gasLimit.valueOf() - moveBalanceGas); - let modifiedGasPrice = gasPrice.multipliedBy( - new BigNumber(networkConfig.GasPriceModifier.valueOf()) - ); - let processingFee = diff.multipliedBy(modifiedGasPrice); - - return feeForMove.plus(processingFee); - } - - /** - * Creates a new Transaction object from a TransactionNext object. - */ - static fromTransactionNext(transaction: ITransactionNext): Transaction { - const tx = new Transaction({ - sender: Address.fromBech32(transaction.sender), - receiver: Address.fromBech32(transaction.receiver), - gasLimit: Number(transaction.gasLimit), - chainID: transaction.chainID, - value: new BigNumber(transaction.value.toString()).toFixed(0), - data: new TransactionPayload(Buffer.from(transaction.data)), - nonce: Number(transaction.nonce), - gasPrice: Number(transaction.gasPrice), - receiverUsername: transaction.receiverUsername, - senderUsername: transaction.senderUsername, - options: transaction.options, - version: transaction.version - }); - - if (transaction.guardian) { - tx.guardian = Address.fromBech32(transaction.guardian) - } - - if (transaction.signature.length) { - tx.applySignature(transaction.signature); - } - - if (transaction.guardianSignature.length) { - tx.applyGuardianSignature(transaction.guardianSignature); - } - - return tx; - } + /** + * The nonce of the transaction (the account sequence number of the sender). + */ + public nonce: bigint; + + /** + * The value to transfer. + */ + public value: bigint; + + /** + * The address of the sender. + */ + public sender: string; + + /** + * The address of the receiver. + */ + public receiver: string; + + /** + * The username of the sender. + */ + public senderUsername: string; + + /** + * The username of the receiver. + */ + public receiverUsername: string; + + /** + * The gas price to be used. + */ + public gasPrice: bigint; + + /** + * The maximum amount of gas to be consumed when processing the transaction. + */ + public gasLimit: bigint; + + /** + * The payload of the transaction. + */ + public data: Uint8Array; + + /** + * The chain ID of the Network (e.g. "1" for Mainnet). + */ + public chainID: string; + + /** + * The version, required by the Network in order to correctly interpret the contents of the transaction. + */ + public version: number; + + /** + * The options field, useful for describing different settings available for transactions. + */ + public options: number; + + /** + * The address of the guardian. + */ + public guardian: string; + + /** + * The signature. + */ + public signature: Uint8Array; + + /** + * The signature of the guardian. + */ + public guardianSignature: Uint8Array; + + /** + * The transaction hash, also used as a transaction identifier. + */ + private hash: TransactionHash; + + /** + * Creates a new Transaction object. + */ + public constructor({ + nonce, + value, + sender, + receiver, + senderUsername, + receiverUsername, + gasPrice, + gasLimit, + data, + chainID, + version, + options, + guardian, + }: { + nonce?: INonce | bigint; + value?: ITransactionValue | bigint; + sender?: IAddress | string; + receiver?: IAddress | string; + senderUsername?: string; + receiverUsername?: string; + gasPrice?: IGasPrice | bigint; + gasLimit?: IGasLimit | bigint; + data?: ITransactionPayload | Uint8Array; + chainID?: IChainID | string; + version?: ITransactionVersion | number; + options?: ITransactionOptions | number; + guardian?: IAddress | string; + }) { + this.nonce = BigInt(nonce?.valueOf() || 0n); + // We still rely on "bigNumber" for value, because client code might be passing a BigNumber object as a legacy "ITransactionValue", + // and we want to keep compatibility. + this.value = value ? BigInt(new BigNumber(value.toString()).toFixed(0)) : 0n; + this.sender = sender ? (typeof sender === "string" ? sender : sender.bech32()) : ""; + this.receiver = receiver ? (typeof receiver === "string" ? receiver : receiver.bech32()) : ""; + this.senderUsername = senderUsername || ""; + this.receiverUsername = receiverUsername || ""; + this.gasPrice = BigInt(gasPrice?.valueOf() || TRANSACTION_MIN_GAS_PRICE); + this.gasLimit = BigInt(gasLimit?.valueOf() || 0n); + this.data = data?.valueOf() || new Uint8Array(); + this.chainID = chainID?.valueOf() || ""; + this.version = version?.valueOf() || TRANSACTION_VERSION_DEFAULT; + this.options = options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; + this.guardian = guardian ? (typeof guardian === "string" ? guardian : guardian.bech32()) : ""; + + this.signature = Buffer.from([]); + this.guardianSignature = Buffer.from([]); + this.hash = TransactionHash.empty(); + } + + /** + * Legacy method, use the "nonce" property instead. + */ + getNonce(): INonce { + return Number(this.nonce); + } + + /** + * Legacy method, use the "nonce" property instead. + * Sets the account sequence number of the sender. Must be done prior signing. + */ + setNonce(nonce: INonce | bigint) { + this.nonce = BigInt(nonce.valueOf()); + } + + /** + * Legacy method, use the "value" property instead. + */ + getValue(): ITransactionValue { + return this.value; + } + + /** + * Legacy method, use the "value" property instead. + */ + setValue(value: ITransactionValue | bigint) { + this.value = BigInt(value.toString()); + } + + /** + * Legacy method, use the "sender" property instead. + */ + getSender(): IAddress { + return Address.fromBech32(this.sender); + } + + /** + * Legacy method, use the "sender" property instead. + */ + setSender(sender: IAddress | string) { + this.sender = typeof sender === "string" ? sender : sender.bech32(); + } + + /** + * Legacy method, use the "receiver" property instead. + */ + getReceiver(): IAddress { + return Address.fromBech32(this.receiver); + } + + /** + * Legacy method, use the "senderUsername" property instead. + */ + getSenderUsername(): string { + return this.senderUsername; + } + + /** + * Legacy method, use the "senderUsername" property instead. + */ + setSenderUsername(senderUsername: string) { + this.senderUsername = senderUsername; + } + + /** + * Legacy method, use the "receiverUsername" property instead. + */ + getReceiverUsername(): string { + return this.receiverUsername; + } + + /** + * Legacy method, use the "receiverUsername" property instead. + */ + setReceiverUsername(receiverUsername: string) { + this.receiverUsername = receiverUsername; + } + + /** + * Legacy method, use the "guardian" property instead. + */ + getGuardian(): IAddress { + return new Address(this.guardian); + } + + /** + * Legacy method, use the "gasPrice" property instead. + */ + getGasPrice(): IGasPrice { + return Number(this.gasPrice); + } + + /** + * Legacy method, use the "gasPrice" property instead. + */ + setGasPrice(gasPrice: IGasPrice | bigint) { + this.gasPrice = BigInt(gasPrice.valueOf()); + } + + /** + * Legacy method, use the "gasLimit" property instead. + */ + getGasLimit(): IGasLimit { + return Number(this.gasLimit); + } + + /** + * Legacy method, use the "gasLimit" property instead. + */ + setGasLimit(gasLimit: IGasLimit | bigint) { + this.gasLimit = BigInt(gasLimit.valueOf()); + } + + /** + * Legacy method, use the "data" property instead. + */ + getData(): ITransactionPayload { + return new TransactionPayload(Buffer.from(this.data)); + } + + /** + * Legacy method, use the "chainID" property instead. + */ + getChainID(): IChainID { + return this.chainID; + } + + /** + * Legacy method, use the "chainID" property instead. + */ + setChainID(chainID: IChainID | string) { + this.chainID = chainID.valueOf(); + } + + /** + * Legacy method, use the "version" property instead. + */ + getVersion(): TransactionVersion { + return new TransactionVersion(this.version); + } + + /** + * Legacy method, use the "version" property instead. + */ + setVersion(version: ITransactionVersion | number) { + this.version = version.valueOf(); + } + + /** + * Legacy method, use the "options" property instead. + */ + getOptions(): TransactionOptions { + return new TransactionOptions(this.options.valueOf()); + } + + /** + * Legacy method, use the "options" property instead. + * + * Question for review: check how the options are set by sdk-dapp, wallet, ledger, extension. + */ + setOptions(options: ITransactionOptions | number) { + this.options = options.valueOf(); + } + + /** + * Legacy method, use the "signature" property instead. + */ + getSignature(): Buffer { + return Buffer.from(this.signature); + } + + /** + * Legacy method, use the "guardianSignature" property instead. + */ + getGuardianSignature(): Buffer { + return Buffer.from(this.guardianSignature); + } + + /** + * Legacy method, use the "guardian" property instead. + */ + setGuardian(guardian: IAddress | string) { + this.guardian = typeof guardian === "string" ? guardian : guardian.bech32(); + } + + /** + * Legacy method, use "TransactionComputer.computeTransactionHash()" instead. + */ + getHash(): TransactionHash { + guardNotEmpty(this.hash, "hash"); + return this.hash; + } + + /** + * Serializes a transaction to a sequence of bytes, ready to be signed. + * This function is called internally by signers. + */ + serializeForSigning(): Buffer { + // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash + let plain = this.toPlainObject(); + // Make sure we never sign the transaction with another signature set up (useful when using the same method for verification) + if (plain.signature) { + delete plain.signature; + } + + if (plain.guardianSignature) { + delete plain.guardianSignature; + } + + if (!plain.guardian) { + delete plain.guardian; + } + + let serialized = JSON.stringify(plain); + + return Buffer.from(serialized); + } + + /** + * Checks the integrity of the guarded transaction + */ + isGuardedTransaction(): boolean { + const hasGuardian = this.guardian.length > 0; + const hasGuardianSignature = this.guardianSignature.length > 0; + return this.getOptions().isWithGuardian() && hasGuardian && hasGuardianSignature; + } + + /** + * Legacy method, use the "converters" package instead. + * + * Converts the transaction object into a ready-to-serialize, plain JavaScript object. + * This function is called internally within the signing procedure. + */ + toPlainObject(): IPlainTransactionObject { + const plainObject = { + nonce: Number(this.nonce), + value: this.value.toString(), + receiver: this.receiver, + sender: this.sender, + senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined, + receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined, + gasPrice: Number(this.gasPrice), + gasLimit: Number(this.gasLimit), + data: this.data.length == 0 ? undefined : Buffer.from(this.data).toString("base64"), + chainID: this.chainID.valueOf(), + version: this.getVersion().valueOf(), + options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(), + guardian: this.guardian ? this.guardian : undefined, + signature: this.signature.length ? this.getSignature().toString("hex") : undefined, + guardianSignature: this.guardianSignature.length ? this.getGuardianSignature().toString("hex") : undefined, + }; + + return plainObject; + } + + /** + * Converts a plain object transaction into a Transaction Object. + * + * @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject() + */ + static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction { + const tx = new Transaction({ + nonce: Number(plainObjectTransaction.nonce), + value: new BigNumber(plainObjectTransaction.value).toFixed(0), + receiver: plainObjectTransaction.receiver, + receiverUsername: plainObjectTransaction.receiverUsername + ? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString() + : undefined, + sender: plainObjectTransaction.sender, + senderUsername: plainObjectTransaction.senderUsername + ? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString() + : undefined, + guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined, + gasPrice: Number(plainObjectTransaction.gasPrice), + gasLimit: Number(plainObjectTransaction.gasLimit), + data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")), + chainID: String(plainObjectTransaction.chainID), + version: plainObjectTransaction.version, + options: + plainObjectTransaction.options != null + ? new TransactionOptions(plainObjectTransaction.options) + : undefined, + }); + + if (plainObjectTransaction.signature) { + tx.applySignature(new Signature(plainObjectTransaction.signature)); + } + + if (plainObjectTransaction.guardianSignature) { + tx.applyGuardianSignature(new Signature(plainObjectTransaction.guardianSignature)); + } + + return tx; + } + + /** + * Applies the signature on the transaction. + * + * @param signature The signature, as computed by a signer. + */ + applySignature(signature: ISignature | Uint8Array) { + this.signature = interpretSignatureAsBuffer(signature); + this.hash = TransactionHash.compute(this); + } + + /** + * Applies the guardian signature on the transaction. + * + * @param guardianSignature The signature, as computed by a signer. + */ + applyGuardianSignature(guardianSignature: ISignature | Uint8Array) { + this.guardianSignature = interpretSignatureAsBuffer(guardianSignature); + this.hash = TransactionHash.compute(this); + } + + /** + * Converts a transaction to a ready-to-broadcast object. + * Called internally by the network provider. + */ + toSendable(): any { + return this.toPlainObject(); + } + + /** + * Legacy method, use "TransactionComputer.computeTransactionFee()" instead. + * + * Computes the current transaction fee based on the {@link NetworkConfig} and transaction properties + * @param networkConfig {@link NetworkConfig} + */ + computeFee(networkConfig: INetworkConfig): BigNumber { + const computer = new TransactionComputer(); + const fee = computer.computeTransactionFee(this, networkConfig); + return new BigNumber(fee.toString()); + } + + /** + * Creates a new Transaction object from a TransactionNext object. + */ + static fromTransactionNext(transaction: ITransactionNext): Transaction { + const tx = new Transaction({ + sender: Address.fromBech32(transaction.sender), + receiver: Address.fromBech32(transaction.receiver), + gasLimit: Number(transaction.gasLimit), + chainID: transaction.chainID, + value: new BigNumber(transaction.value.toString()).toFixed(0), + data: new TransactionPayload(Buffer.from(transaction.data)), + nonce: Number(transaction.nonce), + gasPrice: Number(transaction.gasPrice), + receiverUsername: transaction.receiverUsername, + senderUsername: transaction.senderUsername, + options: transaction.options, + version: transaction.version, + }); + + if (transaction.guardian) { + tx.guardian = transaction.guardian; + } + + if (transaction.signature.length) { + tx.applySignature(transaction.signature); + } + + if (transaction.guardianSignature.length) { + tx.applyGuardianSignature(transaction.guardianSignature); + } + + return tx; + } } /** * An abstraction for handling and computing transaction hashes. */ export class TransactionHash extends Hash { - constructor(hash: string) { - super(hash); - } - - /** - * Computes the hash of a transaction. - */ - static compute(transaction: Transaction): TransactionHash { - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(transaction); - let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) - .update(buffer) - .digest("hex"); - return new TransactionHash(hash); - } -} + constructor(hash: string) { + super(hash); + } -/** - * An abstraction for creating, signing and broadcasting transactions. - * Will replace the {@link Transaction} class in the future. - */ -export class TransactionNext { - /** - * The nonce of the transaction (the account sequence number of the sender). - */ - public nonce: bigint; - - /** - * The value to transfer. - */ - public value: bigint; - - /** - * The address of the sender. - */ - public sender: string; - - /** - * The address of the receiver. - */ - public receiver: string; - - /** - * The username of the sender. - */ - public senderUsername: string; - - /** - * The username of the receiver. - */ - public receiverUsername: string; - - /** - * The gas price to be used. - */ - public gasPrice: bigint; - - /** - * The maximum amount of gas to be consumed when processing the transaction. - */ - public gasLimit: bigint; - - /** - * The payload of the transaction. - */ - public data: Uint8Array; - - /** - * The chain ID of the Network (e.g. "1" for Mainnet). - */ - public chainID: string; - - /** - * The version, required by the Network in order to correctly interpret the contents of the transaction. - */ - public version: number; - - /** - * The options field of the transactions. - */ - public options: number; - - /** - * The address of the guardian. - */ - public guardian: string; - - /** - * The signature. - */ - public signature: Uint8Array; - - /** - * The signature of the guardian. - */ - public guardianSignature: Uint8Array; - - /** - * Creates a new Transaction object. - */ - public constructor(init: Partial) { - this.nonce = 0n; - this.value = 0n; - this.sender = ""; - this.receiver = ""; - this.senderUsername = ""; - this.receiverUsername = ""; - this.gasPrice = BigInt(TRANSACTION_MIN_GAS_PRICE); - this.gasLimit = 0n; - this.data = new Uint8Array(); - this.chainID = ""; - this.version = TRANSACTION_VERSION_DEFAULT; - this.options = TRANSACTION_OPTIONS_DEFAULT; - this.guardian = ""; - - this.signature = new Uint8Array(); - this.guardianSignature = new Uint8Array(); - - Object.assign(this, init); + /** + * Computes the hash of a transaction. + */ + static compute(transaction: Transaction): TransactionHash { + let serializer = new ProtoSerializer(); + let buffer = serializer.serializeTransaction(transaction); + let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); + return new TransactionHash(hash); } } +export class TransactionNext extends Transaction {} + /** * An utilitary class meant to work together with the {@link TransactionNext} class. */ export class TransactionComputer { - constructor() { } - - computeTransactionFee(transaction: ITransactionNext, networkConfig: INetworkConfig): bigint { - const moveBalanceGas = BigInt( - networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, - ); - if (moveBalanceGas > transaction.gasLimit) { - throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); + constructor() {} + + computeTransactionFee( + transaction: { gasPrice: bigint; gasLimit: bigint; data: Uint8Array }, + networkConfig: INetworkConfig, + ): bigint { + const moveBalanceGas = BigInt( + networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, + ); + if (moveBalanceGas > transaction.gasLimit) { + throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); + } + + const gasPrice = transaction.gasPrice; + const feeForMove = moveBalanceGas * gasPrice; + if (moveBalanceGas === transaction.gasLimit) { + return feeForMove; + } + + const diff = transaction.gasLimit - moveBalanceGas; + const modifiedGasPrice = BigInt( + new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), + ); + const processingFee = diff * modifiedGasPrice; + + return feeForMove + processingFee; } - const gasPrice = transaction.gasPrice; - const feeForMove = moveBalanceGas * gasPrice; - if (moveBalanceGas === transaction.gasLimit) { - return feeForMove; - } + computeBytesForSigning(transaction: ITransactionNext): Uint8Array { + // TODO: do some checks for the transaction e.g. sender, chain ID etc. - const diff = transaction.gasLimit - moveBalanceGas; - const modifiedGasPrice = BigInt( - new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), - ); - const processingFee = diff * modifiedGasPrice; + const plainTransaction = this.toPlainObject(transaction); - return feeForMove + processingFee; - } + if (plainTransaction.signature) { + delete plainTransaction.signature; + } - computeBytesForSigning(transaction: ITransactionNext): Uint8Array { - const plainTransaction = this.toPlainObject(transaction); + if (plainTransaction.guardianSignature) { + delete plainTransaction.guardianSignature; + } - if (plainTransaction.signature) { - delete plainTransaction.signature; - } + if (!plainTransaction.guardian) { + delete plainTransaction.guardian; + } - if (plainTransaction.guardianSignature) { - delete plainTransaction.guardianSignature; - } + const serialized = JSON.stringify(plainTransaction); - if (!plainTransaction.guardian) { - delete plainTransaction.guardian + return new Uint8Array(Buffer.from(serialized)); } - const serialized = JSON.stringify(plainTransaction); - - return new Uint8Array(Buffer.from(serialized)); - } - - computeTransactionHash(transaction: ITransactionNext): Uint8Array { - let serializer = new ProtoSerializer(); + computeTransactionHash(transaction: ITransactionNext): Uint8Array { + let serializer = new ProtoSerializer(); - const tx = Transaction.fromTransactionNext(transaction); - const buffer = serializer.serializeTransaction(tx); - const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH) - .update(buffer) - .digest("hex"); + const tx = Transaction.fromTransactionNext(transaction); + const buffer = serializer.serializeTransaction(tx); + const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); - return Buffer.from(hash, "hex"); - } + return Buffer.from(hash, "hex"); + } - private toPlainObject(transaction: ITransactionNext) { - return { - nonce: Number(transaction.nonce), - value: transaction.value.toString(), - receiver: transaction.receiver, - sender: transaction.sender, - senderUsername: transaction.senderUsername ? Buffer.from(transaction.senderUsername).toString("base64") : undefined, - receiverUsername: transaction.receiverUsername ? Buffer.from(transaction.receiverUsername).toString("base64") : undefined, - gasPrice: Number(transaction.gasPrice), - gasLimit: Number(transaction.gasLimit), - data: transaction.data && transaction.data.length === 0 ? undefined : Buffer.from(transaction.data).toString("base64"), - chainID: transaction.chainID, - version: transaction.version, - options: transaction.options ? transaction.options : undefined, - guardian: transaction.guardian ? transaction.guardian : undefined, - signature: transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), - guardianSignature: transaction.guardianSignature.length == 0 ? undefined : Buffer.from(transaction.guardianSignature).toString("hex") + private toPlainObject(transaction: ITransactionNext) { + return { + nonce: Number(transaction.nonce), + value: transaction.value.toString(), + receiver: transaction.receiver, + sender: transaction.sender, + senderUsername: transaction.senderUsername + ? Buffer.from(transaction.senderUsername).toString("base64") + : undefined, + receiverUsername: transaction.receiverUsername + ? Buffer.from(transaction.receiverUsername).toString("base64") + : undefined, + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), + data: + transaction.data && transaction.data.length === 0 + ? undefined + : Buffer.from(transaction.data).toString("base64"), + chainID: transaction.chainID, + version: transaction.version, + options: transaction.options ? transaction.options : undefined, + guardian: transaction.guardian ? transaction.guardian : undefined, + signature: + transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), + guardianSignature: + transaction.guardianSignature.length == 0 + ? undefined + : Buffer.from(transaction.guardianSignature).toString("hex"), + }; } - } + + // TODO: missing functions from specs, with setting options etc.? } diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts index 78a46832f..3b95f7f13 100644 --- a/src/transactionNext.spec.ts +++ b/src/transactionNext.spec.ts @@ -204,10 +204,8 @@ describe("test transaction next", async () => { await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), ); - const oldTransaction = Transaction.fromTransactionNext(transaction); - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(oldTransaction); + let buffer = serializer.serializeTransaction(transaction); assert.equal( buffer.toString("hex"), "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 5a58e1ab1..cef05df35 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -87,7 +87,7 @@ export class RelayedTransactionsFactory { }); } - private prepareInnerTransactionForRelayedV1(innerTransaction: TransactionNext): string { + private prepareInnerTransactionForRelayedV1(innerTransaction: ITransactionNext): string { const txObject = { nonce: innerTransaction.nonce, sender: Address.fromBech32(innerTransaction.sender).pubkey().toString("base64"), From 4ee60b4fd5c5dd92500f406ab8cf3d462ac52e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 11 Mar 2024 11:24:42 +0200 Subject: [PATCH 132/275] Use existing Transaction instead of NextTransaction. --- src/smartcontracts/smartContract.ts | 9 +- .../delegationTransactionsFactory.ts | 64 ++++++------- .../relayedTransactionsFactory.spec.ts | 18 ++-- .../relayedTransactionsFactory.ts | 14 +-- .../smartContractTransactionsFactory.spec.ts | 55 ++++++----- .../smartContractTransactionsFactory.ts | 26 +++--- ...anagementTransactionIntentsFactory.spec.ts | 24 ++--- .../tokenManagementTransactionsFactory.ts | 92 +++++++++---------- ...onNextBuilder.ts => transactionBuilder.ts} | 10 +- .../transferTransactionsFactory.spec.ts | 10 +- .../transferTransactionsFactory.ts | 12 +-- 11 files changed, 169 insertions(+), 165 deletions(-) rename src/transactionsFactories/{transactionNextBuilder.ts => transactionBuilder.ts} (92%) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 1fb72987e..0217c5f7f 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -127,7 +127,7 @@ export class SmartContract implements ISmartContract { const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const nextTx = scNextTransactionFactory.createTransactionForDeploy({ + const transaction = scNextTransactionFactory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: BigInt(gasLimit.valueOf()), @@ -138,7 +138,6 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }); - const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -187,7 +186,7 @@ export class SmartContract implements ISmartContract { const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const nextTx = scNextTransactionFactory.createTransactionForUpgrade({ + const transaction = scNextTransactionFactory.createTransactionForUpgrade({ sender: caller, contract: this.getAddress(), bytecode: bytecode, @@ -199,7 +198,6 @@ export class SmartContract implements ISmartContract { isPayableBySmartContract: metadataAsJson.payableBySc }) - const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value ?? 0); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) @@ -225,7 +223,7 @@ export class SmartContract implements ISmartContract { args = args || []; value = value || 0; - const nextTx = scNextTransactionFactory.createTransactionForExecute({ + const transaction = scNextTransactionFactory.createTransactionForExecute({ sender: caller, contract: receiver ? receiver : this.getAddress(), functionName: func.toString(), @@ -233,7 +231,6 @@ export class SmartContract implements ISmartContract { args: args }) - const transaction = Transaction.fromTransactionNext(nextTx); transaction.setChainID(chainID); transaction.setValue(value); transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index f66c51df0..d2bbe3619 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -1,10 +1,10 @@ -import { IAddress } from "../interface"; -import { numberToPaddedHex, byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; -import { TransactionNext } from "../transaction"; +import { IAddress } from "../interface"; +import { Transaction } from "../transaction"; +import { byteArrayToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; +import { TransactionBuilder } from "./transactionBuilder"; interface Config { chainID: string; @@ -38,7 +38,7 @@ export class DelegationTransactionsFactory { totalDelegationCap: bigint; serviceFee: bigint; amount: bigint; - }): TransactionNext { + }): Transaction { const dataParts = [ "createNewDelegationContract", numberToPaddedHex(options.totalDelegationCap.toString()), @@ -48,7 +48,7 @@ export class DelegationTransactionsFactory { const executionGasLimit = this.config.gasLimitCreateDelegationContract + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(DELEGATION_MANAGER_SC_ADDRESS), @@ -64,7 +64,7 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; signedMessages: Uint8Array[]; - }): TransactionNext { + }): Transaction { if (options.publicKeys.length !== options.signedMessages.length) { throw new Err("The number of public keys should match the number of signed messages"); } @@ -76,7 +76,7 @@ export class DelegationTransactionsFactory { dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); } - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -90,7 +90,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; - }): TransactionNext { + }): Transaction { const dataParts = ["removeNodes"]; for (const key of options.publicKeys) { @@ -98,7 +98,7 @@ export class DelegationTransactionsFactory { } const numNodes = options.publicKeys.length; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -112,7 +112,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; - }): TransactionNext { + }): Transaction { let dataParts = ["stakeNodes"]; for (const key of options.publicKeys) { @@ -125,7 +125,7 @@ export class DelegationTransactionsFactory { const executionGasLimit = additionalGasForAllNodes + this.config.gasLimitStake + this.config.gasLimitDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -139,7 +139,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; - }): TransactionNext { + }): Transaction { let dataParts = ["unBondNodes"]; for (const key of options.publicKeys) { @@ -152,7 +152,7 @@ export class DelegationTransactionsFactory { this.config.gasLimitUnbond + this.config.gasLimitDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -166,7 +166,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; - }): TransactionNext { + }): Transaction { let dataParts = ["unStakeNodes"]; for (const key of options.publicKeys) { @@ -179,7 +179,7 @@ export class DelegationTransactionsFactory { this.config.gasLimitUnstake + this.config.gasLimitDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -193,7 +193,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; publicKeys: IValidatorPublicKey[]; - }): TransactionNext { + }): Transaction { const dataParts = ["unJailNodes"]; for (const key of options.publicKeys) { @@ -201,7 +201,7 @@ export class DelegationTransactionsFactory { } const numNodes = options.publicKeys.length; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -215,12 +215,12 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; serviceFee: bigint; - }): TransactionNext { + }): Transaction { const dataParts = ["changeServiceFee", numberToPaddedHex(options.serviceFee)]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -234,12 +234,12 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; delegationCap: bigint; - }): TransactionNext { + }): Transaction { const dataParts = ["modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap)]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -252,12 +252,12 @@ export class DelegationTransactionsFactory { createTransactionForSettingAutomaticActivation(options: { sender: IAddress; delegationContract: IAddress; - }): TransactionNext { + }): Transaction { const dataParts = ["setAutomaticActivation", utf8ToHex("true")]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -270,12 +270,12 @@ export class DelegationTransactionsFactory { createTransactionForUnsettingAutomaticActivation(options: { sender: IAddress; delegationContract: IAddress; - }): TransactionNext { + }): Transaction { const dataParts = ["setAutomaticActivation", utf8ToHex("false")]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -288,12 +288,12 @@ export class DelegationTransactionsFactory { createTransactionForSettingCapCheckOnRedelegateRewards(options: { sender: IAddress; delegationContract: IAddress; - }): TransactionNext { + }): Transaction { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("true")]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -306,12 +306,12 @@ export class DelegationTransactionsFactory { createTransactionForUnsettingCapCheckOnRedelegateRewards(options: { sender: IAddress; delegationContract: IAddress; - }): TransactionNext { + }): Transaction { const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("false")]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, @@ -327,7 +327,7 @@ export class DelegationTransactionsFactory { name: string; website: string; identifier: string; - }): TransactionNext { + }): Transaction { const dataParts = [ "setMetaData", utf8ToHex(options.name), @@ -338,7 +338,7 @@ export class DelegationTransactionsFactory { const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.delegationContract, diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index c32d8a20b..32b80864c 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -1,6 +1,6 @@ import { assert } from "chai"; import { TestWallet, loadTestWallets } from "../testutils"; -import { TransactionComputer, TransactionNext } from "../transaction"; +import { Transaction, TransactionComputer } from "../transaction"; import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; @@ -15,7 +15,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should throw exception when creating relayed v1 transaction with invalid inner transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: alice.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", gasLimit: 10000000n, @@ -38,7 +38,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create relayed v1 transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", gasLimit: 60000000n, @@ -70,7 +70,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create relayed v1 transaction with usernames", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: carol.address.bech32(), receiver: alice.address.bech32(), gasLimit: 50000n, @@ -104,7 +104,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create relayed v1 transaction with big value", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: carol.address.bech32(), receiver: alice.address.bech32(), gasLimit: 50000n, @@ -138,7 +138,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create relayed v1 transaction with guarded inner transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", gasLimit: 60000000n, @@ -174,7 +174,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create guarded relayed v1 transaction with guarded inner transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqpgq54tsxmej537z9leghvp69hfu4f8gg5eu396q83gnnz", gasLimit: 60000000n, @@ -213,7 +213,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should throw exception when creating relayed v2 transaction with invalid inner transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: bob.address.bech32(), receiver: bob.address.bech32(), gasLimit: 50000n, @@ -242,7 +242,7 @@ describe("test relayed v1 transaction builder", function () { }); it("should create relayed v2 transaction", async function () { - let innerTransaction = new TransactionNext({ + let innerTransaction = new Transaction({ sender: bob.address.bech32(), receiver: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", gasLimit: 0n, diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index cef05df35..e012899cf 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -1,9 +1,9 @@ import BigNumber from "bignumber.js"; -import { TransactionNext } from "../transaction"; -import { IAddress, ITransactionNext } from "../interface"; -import { ErrInvalidInnerTransaction } from "../errors"; import { Address } from "../address"; +import { ErrInvalidInnerTransaction } from "../errors"; +import { IAddress, ITransactionNext } from "../interface"; import { AddressValue, ArgSerializer, BytesValue, U64Value } from "../smartcontracts"; +import { Transaction } from "../transaction"; const JSONbig = require("json-bigint"); @@ -26,7 +26,7 @@ export class RelayedTransactionsFactory { createRelayedV1Transaction(options: { innerTransaction: ITransactionNext; relayerAddress: IAddress; - }): TransactionNext { + }): Transaction { if (!options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit is not set for the inner transaction"); } @@ -41,7 +41,7 @@ export class RelayedTransactionsFactory { const additionalGasForDataLength = this.config.gasLimitPerByte * BigInt(data.length); const gasLimit = this.config.minGasLimit + additionalGasForDataLength + options.innerTransaction.gasLimit; - return new TransactionNext({ + return new Transaction({ chainID: this.config.chainID, sender: options.relayerAddress.bech32(), receiver: options.innerTransaction.sender, @@ -54,7 +54,7 @@ export class RelayedTransactionsFactory { innerTransaction: ITransactionNext; innerTransactionGasLimit: bigint; relayerAddress: IAddress; - }): TransactionNext { + }): Transaction { if (options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit should not be set for the inner transaction"); } @@ -75,7 +75,7 @@ export class RelayedTransactionsFactory { const additionalGasForDataLength = this.config.gasLimitPerByte * BigInt(data.length); const gasLimit = options.innerTransactionGasLimit + this.config.minGasLimit + additionalGasForDataLength; - return new TransactionNext({ + return new Transaction({ sender: options.relayerAddress.bech32(), receiver: options.innerTransaction.sender, value: 0n, diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 8e5870b91..74fb18033 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -51,7 +51,7 @@ describe("test smart contract transactions factory", function () { ); }); - it("should create 'TransactionNext' for deploy", async function () { + it("should create 'Transaction' for deploy", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000n; const args = [new U32Value(0)]; @@ -62,7 +62,8 @@ describe("test smart contract transactions factory", function () { gasLimit: gasLimit, args: args, }); - const abiDeployNext = abiAwareFactory.createTransactionForDeploy({ + + const transactionAbiAware = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, @@ -75,10 +76,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit.valueOf(), gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiDeployNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute without transfer", async function () { + it("should create 'Transaction' for execute without transfer", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -92,7 +93,8 @@ describe("test smart contract transactions factory", function () { gasLimit: gasLimit, args: args, }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -106,10 +108,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute and transfer native token", async function () { + it("should create 'Transaction' for execute and transfer native token", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -124,7 +126,8 @@ describe("test smart contract transactions factory", function () { args: [new U32Value(7)], nativeTransferAmount: egldAmount, }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -139,10 +142,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 1000000000000000000n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute and transfer single esdt", async function () { + it("should create 'Transaction' for execute and transfer single esdt", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -159,7 +162,8 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [transfer], }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -174,10 +178,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute and transfer multiple esdts", async function () { + it("should create 'Transaction' for execute and transfer multiple esdts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3"); const func = "add"; @@ -197,7 +201,8 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [fooTransfer, barTransfer], }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -219,10 +224,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute and transfer single nft", async function () { + it("should create 'Transaction' for execute and transfer single nft", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -240,7 +245,8 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [transfer], }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -263,10 +269,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for execute and transfer multiple nfts", async function () { + it("should create 'Transaction' for execute and transfer multiple nfts", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const func = "add"; @@ -286,7 +292,8 @@ describe("test smart contract transactions factory", function () { args: args, tokenTransfers: [firstTransfer, secondTransfer], }); - const abiExecuteNext = abiAwareFactory.createTransactionForExecute({ + + const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, functionName: func, @@ -309,10 +316,10 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiExecuteNext); + assert.deepEqual(transaction, transactionAbiAware); }); - it("should create 'TransactionNext' for upgrade", async function () { + it("should create 'Transaction' for upgrade", async function () { const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"); const gasLimit = 6000000n; @@ -326,7 +333,7 @@ describe("test smart contract transactions factory", function () { args: args, }); - const abiUpgradeNext = abiAwareFactory.createTransactionForUpgrade({ + const transactionAbiAware = abiAwareFactory.createTransactionForUpgrade({ sender: sender, contract: contract, bytecode: adderByteCode.valueOf(), @@ -340,6 +347,6 @@ describe("test smart contract transactions factory", function () { assert.equal(transaction.gasLimit, gasLimit); assert.equal(transaction.value, 0n); - assert.deepEqual(transaction, abiUpgradeNext); + assert.deepEqual(transaction, transactionAbiAware); }); }); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 1b86724c0..ba190f81b 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -1,14 +1,14 @@ +import { Address } from "../address"; +import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; +import { Err, ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; -import { byteArrayToHex, utf8ToHex } from "../utils.codec"; -import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; -import { Err, ErrBadUsage } from "../errors"; -import { Address } from "../address"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; -import { Token, NextTokenTransfer } from "../tokens"; +import { NextTokenTransfer, Token } from "../tokens"; +import { Transaction } from "../transaction"; +import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; -import { TransactionNext } from "../transaction"; +import { TransactionBuilder } from "./transactionBuilder"; interface Config { chainID: string; @@ -52,7 +52,7 @@ export class SmartContractTransactionsFactory { isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; - }): TransactionNext { + }): Transaction { const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const isUpgradeable = options.isUpgradeable ?? true; const isReadable = options.isReadable ?? true; @@ -64,7 +64,7 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(CONTRACT_DEPLOY_ADDRESS), @@ -83,7 +83,7 @@ export class SmartContractTransactionsFactory { args?: any[]; nativeTransferAmount?: bigint; tokenTransfers?: NextTokenTransfer[]; - }): TransactionNext { + }): Transaction { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; const nativeTransferAmount = options.nativeTransferAmount ?? 0n; @@ -113,7 +113,7 @@ export class SmartContractTransactionsFactory { dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.functionName))); - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: receiver, @@ -135,7 +135,7 @@ export class SmartContractTransactionsFactory { isReadable?: boolean; isPayable?: boolean; isPayableBySmartContract?: boolean; - }): TransactionNext { + }): Transaction { const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const isUpgradeable = options.isUpgradeable ?? true; @@ -150,7 +150,7 @@ export class SmartContractTransactionsFactory { const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.contract, diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 0cb816422..f626d452a 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -15,7 +15,7 @@ describe("test token management transactions factory", () => { tokenManagementFactory = new TokenManagementTransactionsFactory(config); }); - it("should create 'TransactionNext' for registering and setting roles", () => { + it("should create 'Transaction' for registering and setting roles", () => { const transaction = tokenManagementFactory.createTransactionForRegisteringAndSettingRoles({ sender: frank.address, tokenName: "TEST", @@ -31,8 +31,8 @@ describe("test token management transactions factory", () => { assert.deepEqual(transaction.gasLimit, 60125000n); }); - it("should create 'TransactionNext' for issuing fungible token", () => { - const next = tokenManagementFactory.createTransactionForIssuingFungible({ + it("should create 'Transaction' for issuing fungible token", () => { + const transaction = tokenManagementFactory.createTransactionForIssuingFungible({ sender: frank.address, tokenName: "FRANK", tokenTicker: "FRANK", @@ -47,17 +47,17 @@ describe("test token management transactions factory", () => { }); assert.deepEqual( - next.data, + transaction.data, Buffer.from( "issue@4652414e4b@4652414e4b@64@00@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", ), ); - assert.equal(next.sender, frank.address.toString()); - assert.equal(next.receiver, ESDT_CONTRACT_ADDRESS); - assert.deepEqual(next.value, config.issueCost); + assert.equal(transaction.sender, frank.address.toString()); + assert.equal(transaction.receiver, ESDT_CONTRACT_ADDRESS); + assert.deepEqual(transaction.value, config.issueCost); }); - it("should create 'TransactionNext' for issuing semi-fungible token", () => { + it("should create 'Transaction' for issuing semi-fungible token", () => { const transaction = tokenManagementFactory.createTransactionForIssuingSemiFungible({ sender: frank.address, tokenName: "FRANK", @@ -82,7 +82,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(transaction.value, config.issueCost); }); - it("should create 'TransactionNext' for issuing non-fungible token", () => { + it("should create 'Transaction' for issuing non-fungible token", () => { const transaction = tokenManagementFactory.createTransactionForIssuingNonFungible({ sender: frank.address, tokenName: "FRANK", @@ -107,7 +107,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(transaction.value, config.issueCost); }); - it("should create 'TransactionNext' for registering metaEsdt", () => { + it("should create 'Transaction' for registering metaEsdt", () => { const transaction = tokenManagementFactory.createTransactionForRegisteringMetaESDT({ sender: frank.address, tokenName: "FRANK", @@ -133,7 +133,7 @@ describe("test token management transactions factory", () => { assert.deepEqual(transaction.value, config.issueCost); }); - it("should create 'TransactionNext' for setting spcial role on non-fungible token", () => { + it("should create 'Transaction' for setting spcial role on non-fungible token", () => { const transaction = tokenManagementFactory.createTransactionForSettingSpecialRoleOnNonFungibleToken({ sender: frank.address, user: grace.address, @@ -156,7 +156,7 @@ describe("test token management transactions factory", () => { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for creating nft", () => { + it("should create 'Transaction' for creating nft", () => { const transaction = tokenManagementFactory.createTransactionForCreatingNFT({ sender: grace.address, tokenIdentifier: "FRANK-aa9e8d", diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index c2c17a899..c7acb2e6e 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -2,9 +2,9 @@ import { Address } from "../address"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { IAddress } from "../interface"; import { Logger } from "../logger"; -import { addressToHex, byteArrayToHex, utf8ToHex, numberToPaddedHex } from "../utils.codec"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; -import { TransactionNext } from "../transaction"; +import { Transaction } from "../transaction"; +import { addressToHex, byteArrayToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; +import { TransactionBuilder } from "./transactionBuilder"; interface Config { chainID: string; @@ -54,7 +54,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionNext { + }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -77,7 +77,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -99,7 +99,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionNext { + }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -122,7 +122,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -144,7 +144,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionNext { + }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -167,7 +167,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -190,7 +190,7 @@ export class TokenManagementTransactionsFactory { canChangeOwner: boolean; canUpgrade: boolean; canAddSpecialRoles: boolean; - }): TransactionNext { + }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -214,7 +214,7 @@ export class TokenManagementTransactionsFactory { options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -231,7 +231,7 @@ export class TokenManagementTransactionsFactory { tokenTicker: string; tokenType: RegisterAndSetAllRolesTokenType; numDecimals: bigint; - }): TransactionNext { + }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); const dataParts = [ @@ -242,7 +242,7 @@ export class TokenManagementTransactionsFactory { numberToPaddedHex(options.numDecimals), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -256,10 +256,10 @@ export class TokenManagementTransactionsFactory { createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; - }): TransactionNext { + }): Transaction { const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -272,10 +272,10 @@ export class TokenManagementTransactionsFactory { createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string; - }): TransactionNext { + }): Transaction { const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -291,7 +291,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; addRoleLocalMint: boolean; addRoleLocalBurn: boolean; - }): TransactionNext { + }): Transaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -300,7 +300,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -318,7 +318,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): TransactionNext { + }): Transaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -329,7 +329,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -347,7 +347,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTBurn: boolean; addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; - }): TransactionNext { + }): Transaction { return this.createTransactionForSettingSpecialRoleOnSemiFungibleToken(options); } @@ -360,7 +360,7 @@ export class TokenManagementTransactionsFactory { addRoleNFTUpdateAttributes: boolean; addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; - }): TransactionNext { + }): Transaction { const dataParts = [ "setSpecialRole", utf8ToHex(options.tokenIdentifier), @@ -372,7 +372,7 @@ export class TokenManagementTransactionsFactory { ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: Address.fromBech32(ESDT_CONTRACT_ADDRESS), @@ -391,7 +391,7 @@ export class TokenManagementTransactionsFactory { hash: string; attributes: Uint8Array; uris: string[]; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTNFTCreate", utf8ToHex(options.tokenIdentifier), @@ -407,7 +407,7 @@ export class TokenManagementTransactionsFactory { const nftData = options.name + options.hash + options.attributes + options.uris.join(""); const storageGasLimit = this.config.gasLimitPerByte + BigInt(nftData.length); - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -417,10 +417,10 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { + createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -430,10 +430,10 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): TransactionNext { + createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -447,10 +447,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionNext { + }): Transaction { const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -464,10 +464,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionNext { + }): Transaction { const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -481,10 +481,10 @@ export class TokenManagementTransactionsFactory { sender: IAddress; user: IAddress; tokenIdentifier: string; - }): TransactionNext { + }): Transaction { const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -498,14 +498,14 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; supplyToMint: bigint; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTLocalMint", utf8ToHex(options.tokenIdentifier), numberToPaddedHex(options.supplyToMint), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -519,14 +519,14 @@ export class TokenManagementTransactionsFactory { sender: IAddress; tokenIdentifier: string; supplyToBurn: bigint; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTLocalBurn", utf8ToHex(options.tokenIdentifier), numberToPaddedHex(options.supplyToBurn), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -541,7 +541,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: bigint; attributes: Uint8Array; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTNFTUpdateAttributes", utf8ToHex(options.tokenIdentifier), @@ -549,7 +549,7 @@ export class TokenManagementTransactionsFactory { byteArrayToHex(options.attributes), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -564,7 +564,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: bigint; quantityToAdd: bigint; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTNFTAddQuantity", utf8ToHex(options.tokenIdentifier), @@ -572,7 +572,7 @@ export class TokenManagementTransactionsFactory { numberToPaddedHex(options.quantityToAdd), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -587,7 +587,7 @@ export class TokenManagementTransactionsFactory { tokenIdentifier: string; tokenNonce: bigint; quantityToBurn: bigint; - }): TransactionNext { + }): Transaction { const dataParts = [ "ESDTNFTBurn", utf8ToHex(options.tokenIdentifier), @@ -595,7 +595,7 @@ export class TokenManagementTransactionsFactory { numberToPaddedHex(options.quantityToBurn), ]; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, diff --git a/src/transactionsFactories/transactionNextBuilder.ts b/src/transactionsFactories/transactionBuilder.ts similarity index 92% rename from src/transactionsFactories/transactionNextBuilder.ts rename to src/transactionsFactories/transactionBuilder.ts index ec37ec884..910bfb2aa 100644 --- a/src/transactionsFactories/transactionNextBuilder.ts +++ b/src/transactionsFactories/transactionBuilder.ts @@ -1,7 +1,7 @@ -import { IAddress, ITransactionPayload } from "../interface"; import { ARGUMENTS_SEPARATOR } from "../constants"; +import { IAddress, ITransactionPayload } from "../interface"; +import { Transaction } from "../transaction"; import { TransactionPayload } from "../transactionPayload"; -import { TransactionNext } from "../transaction"; interface Config { chainID: string; @@ -9,7 +9,7 @@ interface Config { gasLimitPerByte: bigint; } -export class TransactionNextBuilder { +export class TransactionBuilder { private config: Config; private sender: IAddress; private receiver: IAddress; @@ -51,11 +51,11 @@ export class TransactionNextBuilder { return new TransactionPayload(data); } - build(): TransactionNext { + build(): Transaction { const data = this.buildTransactionPayload(); const gasLimit = this.computeGasLimit(data); - return new TransactionNext({ + return new Transaction({ sender: this.sender.bech32(), receiver: this.receiver.bech32(), gasLimit: gasLimit, diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 3cc865dbc..301360a4d 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -28,7 +28,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create 'TransactionNext' for native token transfer without data", async () => { + it("should create 'Transaction' for native token transfer without data", async () => { const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -42,7 +42,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, new Uint8Array()); }); - it("should create 'TransactionNext' for native token transfer with data", async () => { + it("should create 'Transaction' for native token transfer with data", async () => { const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, @@ -57,7 +57,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data, Buffer.from("test data")); }); - it("should create 'TransactionNext' for esdt transfer", async () => { + it("should create 'Transaction' for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0n); const transfer = new NextTokenTransfer(fooToken, 1000000n); @@ -74,7 +74,7 @@ describe("test transfer transcations factory", function () { assert.deepEqual(transaction.data.toString(), "ESDTTransfer@464f4f2d313233343536@0f4240"); }); - it("should create 'TransactionNext' for nft transfer", async () => { + it("should create 'Transaction' for nft transfer", async () => { const nft = new Token("NFT-123456", 10n); const transfer = new NextTokenTransfer(nft, 1n); @@ -94,7 +94,7 @@ describe("test transfer transcations factory", function () { ); }); - it("should create 'TransactionNext' for multiple nft transfers", async () => { + it("should create 'Transaction' for multiple nft transfers", async () => { const firstNft = new Token("NFT-123456", 10n); const firstTransfer = new NextTokenTransfer(firstNft, 1n); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 226e238ed..8d1292b15 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,9 +1,9 @@ -import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; +import { ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; import { NextTokenTransfer, Token } from "../tokens"; -import { ErrBadUsage } from "../errors"; -import { TransactionNextBuilder } from "./transactionNextBuilder"; import { TransactionNext } from "../transaction"; +import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; +import { TransactionBuilder } from "./transactionBuilder"; const ADDITIONAL_GAS_FOR_ESDT_TRANSFER = 100000; const ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER = 800000; @@ -44,7 +44,7 @@ export class NextTransferTransactionsFactory { }): TransactionNext { const data = options.data || ""; - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.receiver, @@ -79,7 +79,7 @@ export class NextTransferTransactionsFactory { this.config.gasLimitMultiESDTNFTTransfer * BigInt(numberOfTransfers) + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: options.sender, @@ -108,7 +108,7 @@ export class NextTransferTransactionsFactory { receiver = options.sender; } - return new TransactionNextBuilder({ + return new TransactionBuilder({ config: this.config, sender: options.sender, receiver: receiver, From 7f55dd5d2a3b8f1f8d48dee5845e3bdfc972a635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 11 Mar 2024 11:33:19 +0200 Subject: [PATCH 133/275] No more "TransactionNext". --- src/transaction.spec.ts | 163 +++++++++++------- src/transaction.ts | 2 - src/transactionNext.spec.ts | 22 +-- .../transferTransactionsFactory.ts | 8 +- 4 files changed, 111 insertions(+), 84 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 755529b64..87581fc24 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -4,10 +4,8 @@ import { Address } from "./address"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction, TransactionNext } from "./transaction"; +import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; -import { TRANSACTION_MIN_GAS_PRICE } from "./constants"; - describe("test transaction construction", async () => { let wallets: Record; @@ -18,29 +16,6 @@ describe("test transaction construction", async () => { wallets = await loadTestWallets(); }); - it("create transaction from transaction next", async () => { - const plainTransactionNextObject = { - sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - gasLimit: 56000n, - value: 1000000000000000000n, - data: Buffer.from("test"), - chainID: "T" - }; - const nextTransaction = new TransactionNext(plainTransactionNextObject); - - const transaction = Transaction.fromTransactionNext(nextTransaction); - assert.deepEqual(transaction.getSender(), Address.fromBech32(plainTransactionNextObject.sender)); - assert.deepEqual(transaction.getReceiver(), Address.fromBech32(plainTransactionNextObject.receiver)); - assert.equal(transaction.getGasLimit().valueOf().toFixed(0), plainTransactionNextObject.gasLimit.toString()); - assert.equal(transaction.getValue().toString(), plainTransactionNextObject.value.toString()); - assert.equal(transaction.getData().toString(), plainTransactionNextObject.data.toString()); - assert.equal(transaction.getChainID().valueOf(), plainTransactionNextObject.chainID); - assert.equal(transaction.getNonce().valueOf(), 0); - assert.equal(transaction.getGasPrice().valueOf(), TRANSACTION_MIN_GAS_PRICE); - assert.deepEqual(transaction.getSignature(), Buffer.from([])); - }); - it("with no data, no value", async () => { let transaction = new Transaction({ nonce: 89, @@ -49,12 +24,18 @@ describe("test transaction construction", async () => { receiver: wallets.bob.address, gasPrice: minGasPrice, gasLimit: minGasLimit, - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); - assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); + assert.equal( + transaction.getSignature().toString("hex"), + "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", + ); + assert.equal( + transaction.getHash().toString(), + "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", + ); }); it("with data, no value", async () => { @@ -66,12 +47,18 @@ describe("test transaction construction", async () => { gasPrice: minGasPrice, gasLimit: 80000, data: new TransactionPayload("hello"), - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e"); - assert.equal(transaction.getHash().toString(), "10a2bd6f9c358d2c9645368081999efd2a4cc7f24bdfdd75e8f57485fd702001"); + assert.equal( + transaction.getSignature().toString("hex"), + "f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e", + ); + assert.equal( + transaction.getHash().toString(), + "10a2bd6f9c358d2c9645368081999efd2a4cc7f24bdfdd75e8f57485fd702001", + ); }); it("with data, with opaque, unused options (the protocol ignores the options when version == 1)", async () => { @@ -84,12 +71,18 @@ describe("test transaction construction", async () => { gasLimit: minGasLimit, chainID: "local-testnet", version: new TransactionVersion(1), - options: new TransactionOptions(1) + options: new TransactionOptions(1), }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal("c83e69b853a891bf2130c1839362fe2a7a8db327dcc0c9f130497a4f24b0236140b394801bb2e04ce061a6f873cb432bf1bb1e6072e295610904662ac427a30a", transaction.getSignature().toString("hex")); - assert.equal(transaction.getHash().toString(), "32fb1681bd532b226b5bdeed61ae62ce9416bf5e92e48caf96253ff72d1670ac"); + assert.equal( + "c83e69b853a891bf2130c1839362fe2a7a8db327dcc0c9f130497a4f24b0236140b394801bb2e04ce061a6f873cb432bf1bb1e6072e295610904662ac427a30a", + transaction.getSignature().toString("hex"), + ); + assert.equal( + transaction.getHash().toString(), + "32fb1681bd532b226b5bdeed61ae62ce9416bf5e92e48caf96253ff72d1670ac", + ); }); it("with data, with value", async () => { @@ -101,12 +94,18 @@ describe("test transaction construction", async () => { gasPrice: minGasPrice, gasLimit: 100000, data: new TransactionPayload("for the book"), - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "b45f22e9f57a6df22670fcc3566723a0711a05ac2547456de59fd222a54940e4a1d99bd414897ccbf5c02a842ad86e638989b7f4d30edd26c99a8cd1eb092304"); - assert.equal(transaction.getHash().toString(), "84125d7154d81a723642100bdf74e6df99f7c069c016d1e6bbeb408fd4e961bf"); + assert.equal( + transaction.getSignature().toString("hex"), + "b45f22e9f57a6df22670fcc3566723a0711a05ac2547456de59fd222a54940e4a1d99bd414897ccbf5c02a842ad86e638989b7f4d30edd26c99a8cd1eb092304", + ); + assert.equal( + transaction.getHash().toString(), + "84125d7154d81a723642100bdf74e6df99f7c069c016d1e6bbeb408fd4e961bf", + ); }); it("with data, with large value", async () => { @@ -118,12 +117,18 @@ describe("test transaction construction", async () => { gasPrice: minGasPrice, gasLimit: 100000, data: new TransactionPayload("for the spaceship"), - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "01f05aa8cb0614e12a94ab9dcbde5e78370a4e05d23ef25a1fb9d5fcf1cb3b1f33b919cd8dafb1704efb18fa233a8aa0d3344fb6ee9b613a7d7a403786ffbd0a"); - assert.equal(transaction.getHash().toString(), "321e1f1a0e3d06edade34fd0fdf3b4859e4328a73706a442c2439968a074113c"); + assert.equal( + transaction.getSignature().toString("hex"), + "01f05aa8cb0614e12a94ab9dcbde5e78370a4e05d23ef25a1fb9d5fcf1cb3b1f33b919cd8dafb1704efb18fa233a8aa0d3344fb6ee9b613a7d7a403786ffbd0a", + ); + assert.equal( + transaction.getHash().toString(), + "321e1f1a0e3d06edade34fd0fdf3b4859e4328a73706a442c2439968a074113c", + ); }); it("with nonce = 0", async () => { @@ -136,12 +141,18 @@ describe("test transaction construction", async () => { gasLimit: 80000, data: new TransactionPayload("hello"), chainID: "local-testnet", - version: new TransactionVersion(1) + version: new TransactionVersion(1), }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04"); - assert.equal(transaction.getHash().toString(), "6ffa1a75f98aaf336bfb87ef13b9b5a477a017158285d34ee2a503668767e69e"); + assert.equal( + transaction.getSignature().toString("hex"), + "dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04", + ); + assert.equal( + transaction.getHash().toString(), + "6ffa1a75f98aaf336bfb87ef13b9b5a477a017158285d34ee2a503668767e69e", + ); }); it("without options field, should be omitted", async () => { @@ -152,12 +163,18 @@ describe("test transaction construction", async () => { receiver: wallets.bob.address, gasPrice: minGasPrice, gasLimit: minGasLimit, - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); - assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); + assert.equal( + transaction.getSignature().toString("hex"), + "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", + ); + assert.equal( + transaction.getHash().toString(), + "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", + ); let result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); @@ -171,12 +188,18 @@ describe("test transaction construction", async () => { receiver: wallets.bob.address, gasPrice: minGasPrice, gasLimit: minGasLimit, - chainID: "local-testnet" + chainID: "local-testnet", }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503"); - assert.equal(transaction.getHash().toString(), "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8"); + assert.equal( + transaction.getSignature().toString("hex"), + "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", + ); + assert.equal( + transaction.getHash().toString(), + "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", + ); let result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); @@ -191,12 +214,18 @@ describe("test transaction construction", async () => { senderUsername: "carol", receiverUsername: "alice", gasLimit: 50000, - chainID: "T" + chainID: "T", }); transaction.applySignature(await wallets.carol.signer.sign(transaction.serializeForSigning())); - assert.equal(transaction.getSignature().toString("hex"), "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06"); - assert.equal(transaction.getHash().toString(), "edc84d776bfd655ddbd6fce24a83e379496ac47890d00be9c8bb2c6666fa3fd8"); + assert.equal( + transaction.getSignature().toString("hex"), + "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06", + ); + assert.equal( + transaction.getHash().toString(), + "edc84d776bfd655ddbd6fce24a83e379496ac47890d00be9c8bb2c6666fa3fd8", + ); }); it("computes correct fee", () => { @@ -207,14 +236,14 @@ describe("test transaction construction", async () => { receiver: wallets.bob.address, gasPrice: 500, gasLimit: 20, - chainID: "local-testnet" + chainID: "local-testnet", }); let networkConfig = { MinGasLimit: 10, GasPerDataByte: 1500, GasPriceModifier: 0.01, - ChainID: "local-testnet" + ChainID: "local-testnet", }; let fee = transaction.computeFee(networkConfig); @@ -230,14 +259,14 @@ describe("test transaction construction", async () => { data: new TransactionPayload("testdata"), gasPrice: 500, gasLimit: 12010, - chainID: "local-testnet" + chainID: "local-testnet", }); let networkConfig = { MinGasLimit: 10, GasPerDataByte: 1500, GasPriceModifier: 0.01, - ChainID: "T" + ChainID: "T", }; let fee = transaction.computeFee(networkConfig); @@ -256,7 +285,7 @@ describe("test transaction construction", async () => { gasPrice: minGasPrice, gasLimit: 80000, data: new TransactionPayload("hello"), - chainID: "local-testnet" + chainID: "local-testnet", }); const plainObject = transaction.toPlainObject(); @@ -270,7 +299,7 @@ describe("test transaction construction", async () => { sender: wallets.alice.address, receiver: wallets.bob.address, gasLimit: 50000, - chainID: "local-testnet" + chainID: "local-testnet", }); assert.equal(tx1.getValue().toString(), "123456789000000000000000000000"); @@ -279,19 +308,19 @@ describe("test transaction construction", async () => { sender: wallets.alice.address, receiver: wallets.bob.address, gasLimit: 50000, - chainID: "local-testnet" + chainID: "local-testnet", }); assert.equal(tx2.getValue().toString(), "123456789000000000000000000000"); const tx3 = new Transaction({ - // Passing a BigNumber is not recommended. + // Passing a BigNumber is not recommended. // However, ITransactionValue interface is permissive, and developers may mistakenly pass such objects as values. // TokenTransfer objects or simple strings (see above) are preferred, instead. value: new BigNumber("123456789000000000000000000000"), sender: wallets.alice.address, receiver: wallets.bob.address, gasLimit: 50000, - chainID: "local-testnet" + chainID: "local-testnet", }); assert.equal(tx3.getValue().toString(), "123456789000000000000000000000"); }); @@ -321,7 +350,7 @@ describe("test transaction construction", async () => { data: new TransactionPayload("hello"), chainID: "local-testnet", version: new TransactionVersion(1), - options: TransactionOptions.withOptions({ guarded: true }) + options: TransactionOptions.withOptions({ guarded: true }), }); assert.isFalse(transaction.isGuardedTransaction()); @@ -335,7 +364,7 @@ describe("test transaction construction", async () => { data: new TransactionPayload("hello"), chainID: "local-testnet", version: new TransactionVersion(2), - options: TransactionOptions.withOptions({ guarded: true }) + options: TransactionOptions.withOptions({ guarded: true }), }); assert.isFalse(transaction.isGuardedTransaction()); @@ -349,7 +378,7 @@ describe("test transaction construction", async () => { data: new TransactionPayload("hello"), chainID: "local-testnet", version: new TransactionVersion(2), - options: TransactionOptions.withOptions({ guarded: true }) + options: TransactionOptions.withOptions({ guarded: true }), }); assert.isFalse(transaction.isGuardedTransaction()); @@ -364,7 +393,7 @@ describe("test transaction construction", async () => { data: new TransactionPayload("hello"), chainID: "local-testnet", version: new TransactionVersion(2), - options: TransactionOptions.withOptions({ guarded: true }) + options: TransactionOptions.withOptions({ guarded: true }), }); assert.isFalse(transaction.isGuardedTransaction()); @@ -379,7 +408,7 @@ describe("test transaction construction", async () => { data: new TransactionPayload("hello"), chainID: "local-testnet", version: new TransactionVersion(2), - options: TransactionOptions.withOptions({ guarded: true }) + options: TransactionOptions.withOptions({ guarded: true }), }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); transaction.applyGuardianSignature(transaction.getSignature()); diff --git a/src/transaction.ts b/src/transaction.ts index 9c3173495..75384b71d 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -553,8 +553,6 @@ export class TransactionHash extends Hash { } } -export class TransactionNext extends Transaction {} - /** * An utilitary class meant to work together with the {@link TransactionNext} class. */ diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts index 3b95f7f13..b8d988340 100644 --- a/src/transactionNext.spec.ts +++ b/src/transactionNext.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; -import { TestWallet, loadTestWallets } from "./testutils"; -import { TransactionNext, TransactionComputer, Transaction } from "./transaction"; import { ProtoSerializer } from "./proto"; +import { TestWallet, loadTestWallets } from "./testutils"; +import { Transaction, TransactionComputer } from "./transaction"; class NetworkConfig { MinGasLimit: number; @@ -30,7 +30,7 @@ describe("test transaction next", async () => { const sender = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; const receiver = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; - let transaction = new TransactionNext({ + let transaction = new Transaction({ chainID: networkConfig.ChainID, sender: sender, receiver: receiver, @@ -48,7 +48,7 @@ describe("test transaction next", async () => { `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}`, ); - transaction = new TransactionNext({ + transaction = new Transaction({ chainID: networkConfig.ChainID, sender: sender, receiver: receiver, @@ -69,7 +69,7 @@ describe("test transaction next", async () => { }); it("should serialize transaction with usernames", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: "T", sender: wallets.carol.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -93,7 +93,7 @@ describe("test transaction next", async () => { }); it("should compute transaction hash", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -116,7 +116,7 @@ describe("test transaction next", async () => { }); it("should compute transaction hash with usernames", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -141,7 +141,7 @@ describe("test transaction next", async () => { }); it("should throw `NotEnoughGas` error", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -155,7 +155,7 @@ describe("test transaction next", async () => { }); it("should compute transaction fee", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -169,7 +169,7 @@ describe("test transaction next", async () => { }); it("should compute transaction fee for transaction with data field", async () => { - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), @@ -186,7 +186,7 @@ describe("test transaction next", async () => { it("should compute guarded transaction", async () => { const alice = wallets.alice; - const transaction = new TransactionNext({ + const transaction = new Transaction({ chainID: "local-testnet", sender: alice.address.bech32(), receiver: wallets.bob.address.bech32(), diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 8d1292b15..2ca3ccdff 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,7 +1,7 @@ import { ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; import { NextTokenTransfer, Token } from "../tokens"; -import { TransactionNext } from "../transaction"; +import { Transaction } from "../transaction"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionBuilder } from "./transactionBuilder"; @@ -41,7 +41,7 @@ export class NextTransferTransactionsFactory { receiver: IAddress; nativeAmount: bigint; data?: string; - }): TransactionNext { + }): Transaction { const data = options.data || ""; return new TransactionBuilder({ @@ -59,7 +59,7 @@ export class NextTransferTransactionsFactory { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; - }): TransactionNext { + }): Transaction { const numberOfTransfers = options.tokenTransfers.length; if (numberOfTransfers === 0) { @@ -93,7 +93,7 @@ export class NextTransferTransactionsFactory { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; - }): TransactionNext { + }): Transaction { let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; let extraGasForTransfer = 0n; From 21ff0ee01b16fecdb228e7ad635936458b7bce49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 11 Mar 2024 12:02:11 +0200 Subject: [PATCH 134/275] No more transactionNext. --- src/interface.ts | 2 +- src/testutils/networkProviders.ts | 4 +- src/transaction.ts | 59 ++++++------------- .../delegationTransactionsFactory.spec.ts | 34 +++++------ .../relayedTransactionsFactory.ts | 8 +-- 5 files changed, 42 insertions(+), 65 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index 1b26134ef..fab671c24 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -85,7 +85,7 @@ export interface ITokenTransfer { */ export type ITokenPayment = ITokenTransfer; -export interface ITransactionNext { +export interface ITransaction { sender: string; receiver: string; gasLimit: bigint; diff --git a/src/testutils/networkProviders.ts b/src/testutils/networkProviders.ts index 48071d3f3..736a9bedb 100644 --- a/src/testutils/networkProviders.ts +++ b/src/testutils/networkProviders.ts @@ -8,7 +8,7 @@ import { ITransactionStatus, } from "../interfaceOfNetwork"; import { Query } from "../smartcontracts/query"; -import { Transaction, TransactionNext } from "../transaction"; +import { Transaction } from "../transaction"; export function createLocalnetProvider(): INetworkProvider { return new ProxyNetworkProvider("http://localhost:7950", { timeout: 5000 }); @@ -23,7 +23,7 @@ export interface INetworkProvider { getAccount(address: IAddress): Promise; getTransaction(txHash: string, withProcessStatus?: boolean): Promise; getTransactionStatus(txHash: string): Promise; - sendTransaction(tx: Transaction | TransactionNext): Promise; + sendTransaction(tx: Transaction): Promise; simulateTransaction(tx: Transaction): Promise; queryContract(query: Query): Promise; } diff --git a/src/transaction.ts b/src/transaction.ts index 75384b71d..b6fa42d8a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -11,7 +11,7 @@ import { INonce, IPlainTransactionObject, ISignature, - ITransactionNext, + ITransaction, ITransactionOptions, ITransactionPayload, ITransactionValue, @@ -128,6 +128,8 @@ export class Transaction { version, options, guardian, + signature, + guardianSignature, }: { nonce?: INonce | bigint; value?: ITransactionValue | bigint; @@ -142,6 +144,8 @@ export class Transaction { version?: ITransactionVersion | number; options?: ITransactionOptions | number; guardian?: IAddress | string; + signature?: Uint8Array; + guardianSignature?: Uint8Array; }) { this.nonce = BigInt(nonce?.valueOf() || 0n); // We still rely on "bigNumber" for value, because client code might be passing a BigNumber object as a legacy "ITransactionValue", @@ -162,6 +166,14 @@ export class Transaction { this.signature = Buffer.from([]); this.guardianSignature = Buffer.from([]); this.hash = TransactionHash.empty(); + + // Legacy logic, will be kept for some time, to avoid breaking changes in behavior. + if (signature?.length) { + this.applySignature(signature); + } + if (guardianSignature?.length) { + this.applyGuardianSignature(guardianSignature); + } } /** @@ -498,40 +510,6 @@ export class Transaction { const fee = computer.computeTransactionFee(this, networkConfig); return new BigNumber(fee.toString()); } - - /** - * Creates a new Transaction object from a TransactionNext object. - */ - static fromTransactionNext(transaction: ITransactionNext): Transaction { - const tx = new Transaction({ - sender: Address.fromBech32(transaction.sender), - receiver: Address.fromBech32(transaction.receiver), - gasLimit: Number(transaction.gasLimit), - chainID: transaction.chainID, - value: new BigNumber(transaction.value.toString()).toFixed(0), - data: new TransactionPayload(Buffer.from(transaction.data)), - nonce: Number(transaction.nonce), - gasPrice: Number(transaction.gasPrice), - receiverUsername: transaction.receiverUsername, - senderUsername: transaction.senderUsername, - options: transaction.options, - version: transaction.version, - }); - - if (transaction.guardian) { - tx.guardian = transaction.guardian; - } - - if (transaction.signature.length) { - tx.applySignature(transaction.signature); - } - - if (transaction.guardianSignature.length) { - tx.applyGuardianSignature(transaction.guardianSignature); - } - - return tx; - } } /** @@ -554,7 +532,7 @@ export class TransactionHash extends Hash { } /** - * An utilitary class meant to work together with the {@link TransactionNext} class. + * An utilitary class meant to work together with the {@link Transaction} class. */ export class TransactionComputer { constructor() {} @@ -585,7 +563,7 @@ export class TransactionComputer { return feeForMove + processingFee; } - computeBytesForSigning(transaction: ITransactionNext): Uint8Array { + computeBytesForSigning(transaction: ITransaction): Uint8Array { // TODO: do some checks for the transaction e.g. sender, chain ID etc. const plainTransaction = this.toPlainObject(transaction); @@ -607,17 +585,16 @@ export class TransactionComputer { return new Uint8Array(Buffer.from(serialized)); } - computeTransactionHash(transaction: ITransactionNext): Uint8Array { + computeTransactionHash(transaction: ITransaction): Uint8Array { let serializer = new ProtoSerializer(); - const tx = Transaction.fromTransactionNext(transaction); - const buffer = serializer.serializeTransaction(tx); + const buffer = serializer.serializeTransaction(new Transaction(transaction)); const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); return Buffer.from(hash, "hex"); } - private toPlainObject(transaction: ITransactionNext) { + private toPlainObject(transaction: ITransaction) { return { nonce: Number(transaction.nonce), value: transaction.value.toString(), diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index d65c36777..09a671fc2 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -1,15 +1,15 @@ -import { Address } from "../address"; -import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; +import { ValidatorPublicKey } from "@multiversx/sdk-wallet"; import { assert } from "chai"; +import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; -import { ValidatorPublicKey } from "@multiversx/sdk-wallet"; +import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); const delegationFactory = new DelegationTransactionsFactory(config); - it("should create 'TransactionNext' for new delegation contract", async function () { + it("should create 'Transaction' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delagationCap = 5000000000000000000000n; const serviceFee = 10n; @@ -31,7 +31,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.chainID, config.chainID); }); - it("should create 'TransactionNext' for adding nodes", async function () { + it("should create 'Transaction' for adding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const publicKey = new ValidatorPublicKey( @@ -68,7 +68,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for removing nodes", async function () { + it("should create 'Transaction' for removing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -91,7 +91,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for staking nodes", async function () { + it("should create 'Transaction' for staking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -114,7 +114,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for unbonding nodes", async function () { + it("should create 'Transaction' for unbonding nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -138,7 +138,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.gasLimit, 12080000n); }); - it("should create 'TransactionNext' for unstaking nodes", async function () { + it("should create 'Transaction' for unstaking nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -162,7 +162,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.gasLimit, 12081500n); }); - it("should create 'TransactionNext' for unjailing nodes", async function () { + it("should create 'Transaction' for unjailing nodes", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -185,7 +185,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for changing service fee", async function () { + it("should create 'Transaction' for changing service fee", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const serviceFee = 10n; @@ -203,7 +203,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for changing delegation cap", async function () { + it("should create 'Transaction' for changing delegation cap", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); const delegationCap = 5000000000000000000000n; @@ -221,7 +221,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for setting automatic activation", async function () { + it("should create 'Transaction' for setting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -237,7 +237,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for unsetting automatic activation", async function () { + it("should create 'Transaction' for unsetting automatic activation", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -253,7 +253,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for setting cap check on redelegate rewards", async function () { + it("should create 'Transaction' for setting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -269,7 +269,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for unsetting cap check on redelegate rewards", async function () { + it("should create 'Transaction' for unsetting cap check on redelegate rewards", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); @@ -285,7 +285,7 @@ describe("test delegation transactions factory", function () { assert.equal(transaction.value, 0n); }); - it("should create 'TransactionNext' for setting metadata", async function () { + it("should create 'Transaction' for setting metadata", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); const delegationContract = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtllllls002zgc"); diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index e012899cf..5a4ef5c78 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -1,7 +1,7 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; import { ErrInvalidInnerTransaction } from "../errors"; -import { IAddress, ITransactionNext } from "../interface"; +import { IAddress, ITransaction } from "../interface"; import { AddressValue, ArgSerializer, BytesValue, U64Value } from "../smartcontracts"; import { Transaction } from "../transaction"; @@ -24,7 +24,7 @@ export class RelayedTransactionsFactory { } createRelayedV1Transaction(options: { - innerTransaction: ITransactionNext; + innerTransaction: ITransaction; relayerAddress: IAddress; }): Transaction { if (!options.innerTransaction.gasLimit) { @@ -51,7 +51,7 @@ export class RelayedTransactionsFactory { } createRelayedV2Transaction(options: { - innerTransaction: ITransactionNext; + innerTransaction: ITransaction; innerTransactionGasLimit: bigint; relayerAddress: IAddress; }): Transaction { @@ -87,7 +87,7 @@ export class RelayedTransactionsFactory { }); } - private prepareInnerTransactionForRelayedV1(innerTransaction: ITransactionNext): string { + private prepareInnerTransactionForRelayedV1(innerTransaction: ITransaction): string { const txObject = { nonce: innerTransaction.nonce, sender: Address.fromBech32(innerTransaction.sender).pubkey().toString("base64"), From 413c3880fa0a4b191580de27ca6f9a8b5b6cbd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 11 Mar 2024 15:45:00 +0200 Subject: [PATCH 135/275] Merge tests. --- src/transaction.spec.ts | 227 +++++++++++++++++++++++++++++++++++- src/transactionNext.spec.ts | 220 ---------------------------------- 2 files changed, 222 insertions(+), 225 deletions(-) delete mode 100644 src/transactionNext.spec.ts diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 87581fc24..d5cbd33b0 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -2,20 +2,128 @@ import BigNumber from "bignumber.js"; import { assert } from "chai"; import { Address } from "./address"; import { TransactionOptions, TransactionVersion } from "./networkParams"; +import { ProtoSerializer } from "./proto"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction } from "./transaction"; +import { Transaction, TransactionComputer } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +class NetworkConfig { + MinGasLimit: number; + GasPerDataByte: number; + GasPriceModifier: number; + ChainID: string; + + constructor(minGasLimit: number = 50000) { + this.MinGasLimit = minGasLimit; + this.GasPerDataByte = 1500; + this.GasPriceModifier = 0.01; + this.ChainID = "D"; + } +} + describe("test transaction construction", async () => { let wallets: Record; let minGasLimit = 50000; let minGasPrice = 1000000000; + const transactionComputer = new TransactionComputer(); before(async function () { wallets = await loadTestWallets(); }); + it("should serialize transaction for signing", async () => { + const networkConfig = new NetworkConfig(); + const sender = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + const receiver = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; + + let transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: sender, + receiver: receiver, + gasLimit: 50000n, + value: 0n, + version: 2, + nonce: 89n, + }); + + let serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + let serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + + assert.equal( + serializedTransaction, + `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}`, + ); + + transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: sender, + receiver: receiver, + gasLimit: 70000n, + value: 1000000000000000000n, + version: 2, + nonce: 90n, + data: new Uint8Array(Buffer.from("hello")), + }); + + serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + + assert.equal( + serializedTransaction, + `{"nonce":90,"value":"1000000000000000000","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":70000,"data":"aGVsbG8=","chainID":"D","version":2}`, + ); + }); + + it("should serialize transaction with usernames", async () => { + const transaction = new Transaction({ + chainID: "T", + sender: wallets.carol.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 50000n, + value: 1000000000000000000n, + version: 2, + nonce: 204n, + senderUsername: "carol", + receiverUsername: "alice", + }); + + transaction.signature = await wallets.carol.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + ); + console.log(Buffer.from(transaction.signature).toString("hex")); + + assert.equal( + Buffer.from(transaction.signature).toString("hex"), + "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06", + ); + }); + + it("should compute transaction hash", async () => { + const networkConfig = new NetworkConfig(); + + const transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 100000n, + value: 1000000000000n, + version: 2, + nonce: 17243n, + data: Buffer.from("testtx"), + }); + transaction.signature = Buffer.from( + "eaa9e4dfbd21695d9511e9754bde13e90c5cfb21748a339a79be11f744c71872e9fe8e73c6035c413f5f08eef09e5458e9ea6fc315ff4da0ab6d000b450b2a07", + "hex", + ); + + const hash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(hash).toString("hex"), + "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03", + ); + }); + it("with no data, no value", async () => { let transaction = new Transaction({ nonce: 89, @@ -205,7 +313,7 @@ describe("test transaction construction", async () => { assert.isFalse(result.toString().includes("options")); }); - it("with usernames", async () => { + it("with usernames (legacy)", async () => { const transaction = new Transaction({ nonce: 204, value: "1000000000000000000", @@ -228,8 +336,35 @@ describe("test transaction construction", async () => { ); }); - it("computes correct fee", () => { - let transaction = new Transaction({ + it("should compute transaction hash with usernames", async () => { + const networkConfig = new NetworkConfig(); + + const transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 100000n, + value: 1000000000000n, + version: 2, + nonce: 17244n, + data: Buffer.from("testtx"), + senderUsername: "alice", + receiverUsername: "alice", + }); + transaction.signature = Buffer.from( + "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", + "hex", + ); + + const hash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(hash).toString("hex"), + "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29", + ); + }); + + it("computes transaction fee (legacy)", () => { + const transaction = new Transaction({ nonce: 92, value: TokenTransfer.egldFromBigInteger("123456789000000000000000000000"), sender: wallets.alice.address, @@ -250,7 +385,37 @@ describe("test transaction construction", async () => { assert.equal(fee.toString(), "5050"); }); - it("computes correct fee with data field", () => { + it("compute transaction fee", async () => { + const transaction = new Transaction({ + chainID: "D", + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 20n, + gasPrice: 500n, + }); + + const config = new NetworkConfig(10); + const gasLimit = transactionComputer.computeTransactionFee(transaction, config); + assert.equal(gasLimit.toString(), "5050"); + }); + + it("should throw `NotEnoughGas` error", async () => { + const networkConfig = new NetworkConfig(); + + const transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 50000n, + data: Buffer.from("toolittlegaslimit"), + }); + + assert.throws(() => { + transactionComputer.computeTransactionFee(transaction, networkConfig); + }); + }); + + it("computes correct fee with data field (legacy)", () => { let transaction = new Transaction({ nonce: 92, value: TokenTransfer.egldFromBigInteger("123456789000000000000000000000"), @@ -273,6 +438,23 @@ describe("test transaction construction", async () => { assert.equal(fee.toString(), "6005000"); }); + it("should compute transaction fee for transaction with data field", async () => { + const networkConfig = new NetworkConfig(); + + const transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 12010n, + gasPrice: 500n, + data: Buffer.from("testdata"), + }); + + const config = new NetworkConfig(10); + const gasLimit = transactionComputer.computeTransactionFee(transaction, config); + assert.equal(gasLimit.toString(), "6005000"); + }); + it("should convert transaction to plain object and back", () => { const sender = wallets.alice.address; const transaction = new Transaction({ @@ -325,6 +507,41 @@ describe("test transaction construction", async () => { assert.equal(tx3.getValue().toString(), "123456789000000000000000000000"); }); + it("should compute guarded transaction", async () => { + const alice = wallets.alice; + + const transaction = new Transaction({ + chainID: "local-testnet", + sender: alice.address.bech32(), + receiver: wallets.bob.address.bech32(), + gasLimit: 150000n, + gasPrice: 1000000000n, + data: new Uint8Array(Buffer.from("test data field")), + version: 2, + options: 2, + nonce: 92n, + value: 123456789000000000000000000000n, + guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", + }); + transaction.guardianSignature = new Uint8Array(64); + transaction.signature = new Uint8Array( + await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), + ); + + let serializer = new ProtoSerializer(); + let buffer = serializer.serializeTransaction(transaction); + assert.equal( + buffer.toString("hex"), + "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + ); + + const txHash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(txHash).toString("hex"), + "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c", + ); + }); + it("checks correctly the version and options of the transaction", async () => { let transaction = new Transaction({ nonce: 90, diff --git a/src/transactionNext.spec.ts b/src/transactionNext.spec.ts deleted file mode 100644 index b8d988340..000000000 --- a/src/transactionNext.spec.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { assert } from "chai"; -import { ProtoSerializer } from "./proto"; -import { TestWallet, loadTestWallets } from "./testutils"; -import { Transaction, TransactionComputer } from "./transaction"; - -class NetworkConfig { - MinGasLimit: number; - GasPerDataByte: number; - GasPriceModifier: number; - ChainID: string; - - constructor(minGasLimit: number = 50000) { - this.MinGasLimit = minGasLimit; - this.GasPerDataByte = 1500; - this.GasPriceModifier = 0.01; - this.ChainID = "D"; - } -} - -describe("test transaction next", async () => { - let wallets: Record; - const networkConfig = new NetworkConfig(); - const transactionComputer = new TransactionComputer(); - - before(async function () { - wallets = await loadTestWallets(); - }); - - it("should serialize transaction for signing", async () => { - const sender = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; - const receiver = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; - - let transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: sender, - receiver: receiver, - gasLimit: 50000n, - value: 0n, - version: 2, - nonce: 89n, - }); - - let serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); - let serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); - - assert.equal( - serializedTransaction, - `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}`, - ); - - transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: sender, - receiver: receiver, - gasLimit: 70000n, - value: 1000000000000000000n, - version: 2, - nonce: 90n, - data: new Uint8Array(Buffer.from("hello")), - }); - - serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); - serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); - - assert.equal( - serializedTransaction, - `{"nonce":90,"value":"1000000000000000000","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":70000,"data":"aGVsbG8=","chainID":"D","version":2}`, - ); - }); - - it("should serialize transaction with usernames", async () => { - const transaction = new Transaction({ - chainID: "T", - sender: wallets.carol.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 50000n, - value: 1000000000000000000n, - version: 2, - nonce: 204n, - senderUsername: "carol", - receiverUsername: "alice", - }); - - transaction.signature = await wallets.carol.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(transaction)), - ); - console.log(Buffer.from(transaction.signature).toString("hex")); - - assert.equal( - Buffer.from(transaction.signature).toString("hex"), - "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06", - ); - }); - - it("should compute transaction hash", async () => { - const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 100000n, - value: 1000000000000n, - version: 2, - nonce: 17243n, - data: Buffer.from("testtx"), - }); - transaction.signature = Buffer.from( - "eaa9e4dfbd21695d9511e9754bde13e90c5cfb21748a339a79be11f744c71872e9fe8e73c6035c413f5f08eef09e5458e9ea6fc315ff4da0ab6d000b450b2a07", - "hex", - ); - - const hash = transactionComputer.computeTransactionHash(transaction); - assert.equal( - Buffer.from(hash).toString("hex"), - "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03", - ); - }); - - it("should compute transaction hash with usernames", async () => { - const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 100000n, - value: 1000000000000n, - version: 2, - nonce: 17244n, - data: Buffer.from("testtx"), - senderUsername: "alice", - receiverUsername: "alice", - }); - transaction.signature = Buffer.from( - "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", - "hex", - ); - - const hash = transactionComputer.computeTransactionHash(transaction); - assert.equal( - Buffer.from(hash).toString("hex"), - "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29", - ); - }); - - it("should throw `NotEnoughGas` error", async () => { - const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 50000n, - data: Buffer.from("toolittlegaslimit"), - }); - - assert.throws(() => { - transactionComputer.computeTransactionFee(transaction, networkConfig); - }); - }); - - it("should compute transaction fee", async () => { - const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 20n, - gasPrice: 500n, - }); - - const config = new NetworkConfig(10); - const gasLimit = transactionComputer.computeTransactionFee(transaction, config); - assert.equal(gasLimit.toString(), "5050"); - }); - - it("should compute transaction fee for transaction with data field", async () => { - const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 12010n, - gasPrice: 500n, - data: Buffer.from("testdata"), - }); - - const config = new NetworkConfig(10); - const gasLimit = transactionComputer.computeTransactionFee(transaction, config); - assert.equal(gasLimit.toString(), "6005000"); - }); - - it("should compute guarded transaction", async () => { - const alice = wallets.alice; - - const transaction = new Transaction({ - chainID: "local-testnet", - sender: alice.address.bech32(), - receiver: wallets.bob.address.bech32(), - gasLimit: 150000n, - gasPrice: 1000000000n, - data: new Uint8Array(Buffer.from("test data field")), - version: 2, - options: 2, - nonce: 92n, - value: 123456789000000000000000000000n, - guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", - }); - transaction.guardianSignature = new Uint8Array(64); - transaction.signature = new Uint8Array( - await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), - ); - - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(transaction); - assert.equal( - buffer.toString("hex"), - "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - ); - - const txHash = transactionComputer.computeTransactionHash(transaction); - assert.equal( - Buffer.from(txHash).toString("hex"), - "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c", - ); - }); -}); From 4506ee0fda49311f46d4afbeaff73ab26a5c6aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 11 Mar 2024 16:52:10 +0200 Subject: [PATCH 136/275] Adjust / rename tests. --- src/transaction.spec.ts | 342 +++++++++++++++++++--------------------- 1 file changed, 162 insertions(+), 180 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index d5cbd33b0..ba5044657 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -8,57 +8,49 @@ import { TokenTransfer } from "./tokenTransfer"; import { Transaction, TransactionComputer } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; -class NetworkConfig { - MinGasLimit: number; - GasPerDataByte: number; - GasPriceModifier: number; - ChainID: string; - - constructor(minGasLimit: number = 50000) { - this.MinGasLimit = minGasLimit; - this.GasPerDataByte = 1500; - this.GasPriceModifier = 0.01; - this.ChainID = "D"; - } -} - -describe("test transaction construction", async () => { +describe("test transaction", async () => { let wallets: Record; - let minGasLimit = 50000; - let minGasPrice = 1000000000; + const minGasLimit = 50000; + const minGasPrice = 1000000000; + const transactionComputer = new TransactionComputer(); + const networkConfig = { + MinGasLimit: 50000, + GasPerDataByte: 1500, + GasPriceModifier: 0.01, + ChainID: "D", + }; + before(async function () { wallets = await loadTestWallets(); }); - it("should serialize transaction for signing", async () => { - const networkConfig = new NetworkConfig(); - const sender = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; - const receiver = "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"; - - let transaction = new Transaction({ + it("should serialize transaction for signing (without data)", async () => { + const transaction = new Transaction({ chainID: networkConfig.ChainID, - sender: sender, - receiver: receiver, + sender: wallets.alice.address.bech32(), + receiver: wallets.bob.address.bech32(), gasLimit: 50000n, value: 0n, version: 2, nonce: 89n, }); - let serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); - let serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + const serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + const serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); assert.equal( serializedTransaction, `{"nonce":89,"value":"0","receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx","sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th","gasPrice":1000000000,"gasLimit":50000,"chainID":"D","version":2}`, ); + }); - transaction = new Transaction({ + it("should serialize transaction for signing (with data)", async () => { + const transaction = new Transaction({ chainID: networkConfig.ChainID, - sender: sender, - receiver: receiver, + sender: wallets.alice.address.bech32(), + receiver: wallets.bob.address.bech32(), gasLimit: 70000n, value: 1000000000000000000n, version: 2, @@ -66,8 +58,8 @@ describe("test transaction construction", async () => { data: new Uint8Array(Buffer.from("hello")), }); - serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); - serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); + const serializedTransactionBytes = transactionComputer.computeBytesForSigning(transaction); + const serializedTransaction = Buffer.from(serializedTransactionBytes).toString(); assert.equal( serializedTransaction, @@ -75,7 +67,54 @@ describe("test transaction construction", async () => { ); }); - it("should serialize transaction with usernames", async () => { + it("should sign transaction (with no data, no value) (legacy)", async () => { + const transaction = new Transaction({ + nonce: 89, + value: "0", + sender: wallets.alice.address, + receiver: wallets.bob.address, + gasPrice: minGasPrice, + gasLimit: minGasLimit, + chainID: "local-testnet", + }); + + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + + assert.equal( + transaction.getSignature().toString("hex"), + "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", + ); + assert.equal( + transaction.getHash().toString(), + "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", + ); + }); + + it("should sign transaction (with data, no value) (legacy)", async () => { + const transaction = new Transaction({ + nonce: 90, + value: "0", + sender: wallets.alice.address, + receiver: wallets.bob.address, + gasPrice: minGasPrice, + gasLimit: 80000, + data: new TransactionPayload("hello"), + chainID: "local-testnet", + }); + + transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + + assert.equal( + transaction.getSignature().toString("hex"), + "f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e", + ); + assert.equal( + transaction.getHash().toString(), + "10a2bd6f9c358d2c9645368081999efd2a4cc7f24bdfdd75e8f57485fd702001", + ); + }); + + it("should sign transaction (with usernames)", async () => { const transaction = new Transaction({ chainID: "T", sender: wallets.carol.address.bech32(), @@ -91,7 +130,6 @@ describe("test transaction construction", async () => { transaction.signature = await wallets.carol.signer.sign( Buffer.from(transactionComputer.computeBytesForSigning(transaction)), ); - console.log(Buffer.from(transaction.signature).toString("hex")); assert.equal( Buffer.from(transaction.signature).toString("hex"), @@ -99,9 +137,7 @@ describe("test transaction construction", async () => { ); }); - it("should compute transaction hash", async () => { - const networkConfig = new NetworkConfig(); - + it("should compute hash", async () => { const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), @@ -112,65 +148,49 @@ describe("test transaction construction", async () => { nonce: 17243n, data: Buffer.from("testtx"), }); + transaction.signature = Buffer.from( "eaa9e4dfbd21695d9511e9754bde13e90c5cfb21748a339a79be11f744c71872e9fe8e73c6035c413f5f08eef09e5458e9ea6fc315ff4da0ab6d000b450b2a07", "hex", ); const hash = transactionComputer.computeTransactionHash(transaction); + assert.equal( Buffer.from(hash).toString("hex"), "169b76b752b220a76a93aeebc462a1192db1dc2ec9d17e6b4d7b0dcc91792f03", ); }); - it("with no data, no value", async () => { - let transaction = new Transaction({ - nonce: 89, - value: "0", - sender: wallets.alice.address, - receiver: wallets.bob.address, - gasPrice: minGasPrice, - gasLimit: minGasLimit, - chainID: "local-testnet", + it("should compute hash (with usernames)", async () => { + const transaction = new Transaction({ + chainID: networkConfig.ChainID, + sender: wallets.alice.address.bech32(), + receiver: wallets.alice.address.bech32(), + gasLimit: 100000n, + value: 1000000000000n, + version: 2, + nonce: 17244n, + data: Buffer.from("testtx"), + senderUsername: "alice", + receiverUsername: "alice", }); - transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - assert.equal( - transaction.getSignature().toString("hex"), - "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", - ); - assert.equal( - transaction.getHash().toString(), - "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", + transaction.signature = Buffer.from( + "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", + "hex", ); - }); - it("with data, no value", async () => { - let transaction = new Transaction({ - nonce: 90, - value: "0", - sender: wallets.alice.address, - receiver: wallets.bob.address, - gasPrice: minGasPrice, - gasLimit: 80000, - data: new TransactionPayload("hello"), - chainID: "local-testnet", - }); + const hash = transactionComputer.computeTransactionHash(transaction); - transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); assert.equal( - transaction.getSignature().toString("hex"), - "f9e8c1caf7f36b99e7e76ee1118bf71b55cde11a2356e2b3adf15f4ad711d2e1982469cbba7eb0afbf74e8a8f78e549b9410cd86eeaa88fcba62611ac9f6e30e", - ); - assert.equal( - transaction.getHash().toString(), - "10a2bd6f9c358d2c9645368081999efd2a4cc7f24bdfdd75e8f57485fd702001", + Buffer.from(hash).toString("hex"), + "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29", ); }); - it("with data, with opaque, unused options (the protocol ignores the options when version == 1)", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (with data, with opaque, unused options) (legacy)", async () => { + const transaction = new Transaction({ nonce: 89, value: "0", sender: wallets.alice.address, @@ -178,11 +198,13 @@ describe("test transaction construction", async () => { gasPrice: minGasPrice, gasLimit: minGasLimit, chainID: "local-testnet", + // The protocol ignores the options when version == 1 version: new TransactionVersion(1), options: new TransactionOptions(1), }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( "c83e69b853a891bf2130c1839362fe2a7a8db327dcc0c9f130497a4f24b0236140b394801bb2e04ce061a6f873cb432bf1bb1e6072e295610904662ac427a30a", transaction.getSignature().toString("hex"), @@ -193,8 +215,8 @@ describe("test transaction construction", async () => { ); }); - it("with data, with value", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (with data, with value) (legacy)", async () => { + const transaction = new Transaction({ nonce: 91, value: TokenTransfer.egldFromAmount(10), sender: wallets.alice.address, @@ -206,6 +228,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "b45f22e9f57a6df22670fcc3566723a0711a05ac2547456de59fd222a54940e4a1d99bd414897ccbf5c02a842ad86e638989b7f4d30edd26c99a8cd1eb092304", @@ -216,8 +239,8 @@ describe("test transaction construction", async () => { ); }); - it("with data, with large value", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (with data, with large value) (legacy)", async () => { + const transaction = new Transaction({ nonce: 92, value: TokenTransfer.egldFromBigInteger("123456789000000000000000000000"), sender: wallets.alice.address, @@ -229,6 +252,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "01f05aa8cb0614e12a94ab9dcbde5e78370a4e05d23ef25a1fb9d5fcf1cb3b1f33b919cd8dafb1704efb18fa233a8aa0d3344fb6ee9b613a7d7a403786ffbd0a", @@ -239,8 +263,8 @@ describe("test transaction construction", async () => { ); }); - it("with nonce = 0", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (with nonce = 0) (legacy)", async () => { + const transaction = new Transaction({ nonce: 0, value: 0, sender: wallets.alice.address, @@ -253,6 +277,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "dfa3e9f2fdec60dcb353bac3b3435b4a2ff251e7e98eaf8620f46c731fc70c8ba5615fd4e208b05e75fe0f7dc44b7a99567e29f94fcd91efac7e67b182cd2a04", @@ -263,8 +288,8 @@ describe("test transaction construction", async () => { ); }); - it("without options field, should be omitted", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (without options field, should be omitted) (legacy)", async () => { + const transaction = new Transaction({ nonce: 89, value: 0, sender: wallets.alice.address, @@ -275,6 +300,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", @@ -284,12 +310,12 @@ describe("test transaction construction", async () => { "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", ); - let result = transaction.serializeForSigning(); + const result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); }); - it("with guardian field, should be omitted", async () => { - let transaction = new Transaction({ + it("should sign & compute hash (with guardian field, should be omitted) (legacy)", async () => { + const transaction = new Transaction({ nonce: 89, value: 0, sender: wallets.alice.address, @@ -300,6 +326,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "3f08a1dd64fbb627d10b048e0b45b1390f29bb0e457762a2ccb710b029f299022a67a4b8e45cf62f4314afec2e56b5574c71e38df96cc41fae757b7ee5062503", @@ -309,11 +336,11 @@ describe("test transaction construction", async () => { "1359fb9d5b0b47ca9f3b4adce6e4a524fa74099dd4732743b9226774a4cb0ad8", ); - let result = transaction.serializeForSigning(); + const result = transaction.serializeForSigning(); assert.isFalse(result.toString().includes("options")); }); - it("with usernames (legacy)", async () => { + it("should sign & compute hash (with usernames) (legacy)", async () => { const transaction = new Transaction({ nonce: 204, value: "1000000000000000000", @@ -326,6 +353,7 @@ describe("test transaction construction", async () => { }); transaction.applySignature(await wallets.carol.signer.sign(transaction.serializeForSigning())); + assert.equal( transaction.getSignature().toString("hex"), "51e6cd78fb3ab4b53ff7ad6864df27cb4a56d70603332869d47a5cf6ea977c30e696103e41e8dddf2582996ad335229fdf4acb726564dbc1a0bc9e705b511f06", @@ -336,72 +364,71 @@ describe("test transaction construction", async () => { ); }); - it("should compute transaction hash with usernames", async () => { - const networkConfig = new NetworkConfig(); + it("should sign & compute hash (guarded transaction)", async () => { + const alice = wallets.alice; const transaction = new Transaction({ - chainID: networkConfig.ChainID, - sender: wallets.alice.address.bech32(), - receiver: wallets.alice.address.bech32(), - gasLimit: 100000n, - value: 1000000000000n, + chainID: "local-testnet", + sender: alice.address.bech32(), + receiver: wallets.bob.address.bech32(), + gasLimit: 150000n, + gasPrice: 1000000000n, + data: new Uint8Array(Buffer.from("test data field")), version: 2, - nonce: 17244n, - data: Buffer.from("testtx"), - senderUsername: "alice", - receiverUsername: "alice", + options: 2, + nonce: 92n, + value: 123456789000000000000000000000n, + guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", }); - transaction.signature = Buffer.from( - "807bcd7de5553ea6dfc57c0510e84d46813c5963d90fec50991c500091408fcf6216dca48dae16a579a1611ed8b2834bae8bd0027dc17eb557963f7151b82c07", - "hex", + transaction.guardianSignature = new Uint8Array(64); + transaction.signature = new Uint8Array( + await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), ); - const hash = transactionComputer.computeTransactionHash(transaction); + const serializer = new ProtoSerializer(); + const buffer = serializer.serializeTransaction(transaction); + assert.equal( - Buffer.from(hash).toString("hex"), - "41b5acf7ebaf4a9165a64206b6ebc02021b3adda55ffb2a2698aac2e7004dc29", + buffer.toString("hex"), + "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + ); + + const txHash = transactionComputer.computeTransactionHash(transaction); + assert.equal( + Buffer.from(txHash).toString("hex"), + "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c", ); }); - it("computes transaction fee (legacy)", () => { + it("computes fee (legacy)", () => { const transaction = new Transaction({ nonce: 92, value: TokenTransfer.egldFromBigInteger("123456789000000000000000000000"), sender: wallets.alice.address, receiver: wallets.bob.address, - gasPrice: 500, - gasLimit: 20, + gasPrice: minGasPrice, + gasLimit: minGasLimit, chainID: "local-testnet", }); - let networkConfig = { - MinGasLimit: 10, - GasPerDataByte: 1500, - GasPriceModifier: 0.01, - ChainID: "local-testnet", - }; - - let fee = transaction.computeFee(networkConfig); - assert.equal(fee.toString(), "5050"); + const fee = transaction.computeFee(networkConfig); + assert.equal(fee.toString(), "50000000000000"); }); - it("compute transaction fee", async () => { + it("computes fee", async () => { const transaction = new Transaction({ chainID: "D", sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 20n, - gasPrice: 500n, + gasLimit: 50000n, + gasPrice: minGasPrice, }); - const config = new NetworkConfig(10); - const gasLimit = transactionComputer.computeTransactionFee(transaction, config); - assert.equal(gasLimit.toString(), "5050"); + const gasLimit = transactionComputer.computeTransactionFee(transaction, networkConfig); + assert.equal(gasLimit.toString(), "50000000000000"); }); - it("should throw `NotEnoughGas` error", async () => { - const networkConfig = new NetworkConfig(); - + it("computes fee, but should throw `NotEnoughGas` error", async () => { const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), @@ -415,44 +442,34 @@ describe("test transaction construction", async () => { }); }); - it("computes correct fee with data field (legacy)", () => { + it("computes fee (with data field) (legacy)", () => { let transaction = new Transaction({ nonce: 92, value: TokenTransfer.egldFromBigInteger("123456789000000000000000000000"), sender: wallets.alice.address, receiver: wallets.bob.address, data: new TransactionPayload("testdata"), - gasPrice: 500, - gasLimit: 12010, + gasPrice: minGasPrice, + gasLimit: minGasLimit + 12010, chainID: "local-testnet", }); - let networkConfig = { - MinGasLimit: 10, - GasPerDataByte: 1500, - GasPriceModifier: 0.01, - ChainID: "T", - }; - let fee = transaction.computeFee(networkConfig); - assert.equal(fee.toString(), "6005000"); + assert.equal(fee.toString(), "62000100000000"); }); - it("should compute transaction fee for transaction with data field", async () => { - const networkConfig = new NetworkConfig(); - + it("computes fee (with data field)", async () => { const transaction = new Transaction({ chainID: networkConfig.ChainID, sender: wallets.alice.address.bech32(), receiver: wallets.alice.address.bech32(), - gasLimit: 12010n, - gasPrice: 500n, + gasLimit: 50000n + 12010n, + gasPrice: minGasPrice, data: Buffer.from("testdata"), }); - const config = new NetworkConfig(10); - const gasLimit = transactionComputer.computeTransactionFee(transaction, config); - assert.equal(gasLimit.toString(), "6005000"); + const gasLimit = transactionComputer.computeTransactionFee(transaction, networkConfig); + assert.equal(gasLimit.toString(), "62000100000000"); }); it("should convert transaction to plain object and back", () => { @@ -507,41 +524,6 @@ describe("test transaction construction", async () => { assert.equal(tx3.getValue().toString(), "123456789000000000000000000000"); }); - it("should compute guarded transaction", async () => { - const alice = wallets.alice; - - const transaction = new Transaction({ - chainID: "local-testnet", - sender: alice.address.bech32(), - receiver: wallets.bob.address.bech32(), - gasLimit: 150000n, - gasPrice: 1000000000n, - data: new Uint8Array(Buffer.from("test data field")), - version: 2, - options: 2, - nonce: 92n, - value: 123456789000000000000000000000n, - guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", - }); - transaction.guardianSignature = new Uint8Array(64); - transaction.signature = new Uint8Array( - await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), - ); - - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(transaction); - assert.equal( - buffer.toString("hex"), - "085c120e00018ee90ff6181f3761632000001a208049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f82a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1388094ebdc0340f093094a0f746573742064617461206669656c64520d6c6f63616c2d746573746e657458026240e574d78b19e1481a6b9575c162e66f2f906a3178aec537509356385c4f1a5330a9b73a87a456fc6d7041e93b5f8a1231a92fb390174872a104a0929215600c0c6802722032a3f14cf53c4d0543954f6cf1bda0369d13e661dec095107627dc0f6d33612f7a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - ); - - const txHash = transactionComputer.computeTransactionHash(transaction); - assert.equal( - Buffer.from(txHash).toString("hex"), - "242022e9dcfa0ee1d8199b0043314dbda8601619f70069ebc441b9f03349a35c", - ); - }); - it("checks correctly the version and options of the transaction", async () => { let transaction = new Transaction({ nonce: 90, From 73f989e20caf47f5d51a64dc4f41444a1cac5b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 14:25:08 +0200 Subject: [PATCH 137/275] Re-write type expression parser. --- package.json | 3 +- src/abi/typeFormula.ts | 18 +++ src/abi/typeFormulaParser.spec.ts | 25 +++ src/abi/typeFormulaParser.ts | 109 +++++++++++++ .../typesystem/typeExpressionParser.spec.ts | 146 ++++++++++++------ .../typesystem/typeExpressionParser.ts | 98 ++---------- 6 files changed, 273 insertions(+), 126 deletions(-) create mode 100644 src/abi/typeFormula.ts create mode 100644 src/abi/typeFormulaParser.spec.ts create mode 100644 src/abi/typeFormulaParser.ts diff --git a/package.json b/package.json index e4cc22866..a8e6852b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.4", + "version": "13.0.0-beta.5", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -31,7 +31,6 @@ "bech32": "1.1.4", "blake2b": "2.1.3", "buffer": "6.0.3", - "json-duplicate-key-handle": "1.0.0", "keccak": "3.0.2", "protobufjs": "7.2.4" }, diff --git a/src/abi/typeFormula.ts b/src/abi/typeFormula.ts new file mode 100644 index 000000000..ca24926b8 --- /dev/null +++ b/src/abi/typeFormula.ts @@ -0,0 +1,18 @@ +export class TypeFormula { + name: string; + typeParameters: TypeFormula[]; + + constructor(name: string, typeParameters: TypeFormula[]) { + this.name = name; + this.typeParameters = typeParameters; + } + + toString(): string { + if (this.typeParameters.length > 0) { + const typeParameters = this.typeParameters.map((typeParameter) => typeParameter.toString()).join(", "); + return `${this.name}<${typeParameters}>`; + } else { + return this.name; + } + } +} diff --git a/src/abi/typeFormulaParser.spec.ts b/src/abi/typeFormulaParser.spec.ts new file mode 100644 index 000000000..7271b86b9 --- /dev/null +++ b/src/abi/typeFormulaParser.spec.ts @@ -0,0 +1,25 @@ +import { assert } from "chai"; +import { TypeFormulaParser } from "./typeFormulaParser"; + +describe("test type formula parser", () => { + it("should parse expression", async () => { + const parser = new TypeFormulaParser(); + + const testVectors = [ + ["i64", "i64"], + [" i64 ", "i64"], + ["utf-8 string", "utf-8 string"], + ["MultiResultVec>", "MultiResultVec>"], + ["tuple3>", "tuple3>"], + ["tuple2", "tuple2"], + ["tuple2 ", "tuple2"], + ["tuple, List>", "tuple, List>"], + ]; + + for (const [inputExpression, expectedExpression] of testVectors) { + const typeFormula = parser.parseExpression(inputExpression); + const outputExpression = typeFormula.toString(); + assert.equal(outputExpression, expectedExpression); + } + }); +}); diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts new file mode 100644 index 000000000..0399ab5f6 --- /dev/null +++ b/src/abi/typeFormulaParser.ts @@ -0,0 +1,109 @@ +import { TypeFormula } from "./typeFormula"; + +export class TypeFormulaParser { + static BEGIN_TYPE_PARAMETERS = "<"; + static END_TYPE_PARAMETERS = ">"; + static COMMA = ","; + static PUNCTUATION = [ + TypeFormulaParser.COMMA, + TypeFormulaParser.BEGIN_TYPE_PARAMETERS, + TypeFormulaParser.END_TYPE_PARAMETERS, + ]; + + parseExpression(expression: string): TypeFormula { + expression = expression.trim(); + + const tokens = this.tokenizeExpression(expression).filter((token) => token !== TypeFormulaParser.COMMA); + + const stack: any[] = []; + + for (const token of tokens) { + if (TypeFormulaParser.PUNCTUATION.includes(token)) { + if (token === TypeFormulaParser.END_TYPE_PARAMETERS) { + const type_parameters: TypeFormula[] = []; + + while (true) { + if (stack.length === 0) { + throw new Error("Badly specified type parameters."); + } + + if (stack[stack.length - 1] === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { + break; + } + + let item = stack.pop(); + let type_formula: TypeFormula; + + if (item instanceof TypeFormula) { + type_formula = item; + } else { + type_formula = new TypeFormula(item, []); + } + + type_parameters.push(type_formula); + } + + stack.pop(); // pop "<" symbol + const type_name = stack.pop(); + const type_formula = new TypeFormula(type_name, type_parameters.reverse()); + stack.push(type_formula); + } else if (token === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { + // The symbol is pushed as a simple string, + // as it will never be interpreted, anyway. + stack.push(token); + } else { + throw new Error(`Unexpected token (punctuation): ${token}`); + } + } else { + // It's a type name. We push it as a simple string. + stack.push(token); + } + } + + if (stack.length !== 1) { + throw new Error(`Unexpected stack length at end of parsing: ${stack.length}`); + } + if (TypeFormulaParser.PUNCTUATION.includes(stack[0])) { + throw new Error("Unexpected root element."); + } + + const item = stack[0]; + + if (typeof item === "string") { + // Expression contained a simple, non-generic type + return new TypeFormula(item, []); + } else if (item instanceof TypeFormula) { + return item; + } else { + throw new Error(`Unexpected item on stack: ${item}`); + } + } + + private tokenizeExpression(expression: string): string[] { + const tokens: string[] = []; + let currentToken = ""; + + for (let i = 0; i < expression.length; i++) { + const character = expression[i]; + + if (!TypeFormulaParser.PUNCTUATION.includes(character)) { + // Non-punctuation character + currentToken += character; + } else { + if (currentToken) { + tokens.push(currentToken.trim()); + currentToken = ""; + } + + // Punctuation character + tokens.push(character); + } + } + + if (currentToken) { + tokens.push(currentToken.trim()); + } + + return tokens; + } +} diff --git a/src/smartcontracts/typesystem/typeExpressionParser.spec.ts b/src/smartcontracts/typesystem/typeExpressionParser.spec.ts index 0465a1b54..0aa09ae2c 100644 --- a/src/smartcontracts/typesystem/typeExpressionParser.spec.ts +++ b/src/smartcontracts/typesystem/typeExpressionParser.spec.ts @@ -1,7 +1,7 @@ -import * as errors from "../../errors"; import { assert } from "chai"; -import { Type } from "./types"; +import { ErrTypingSystem } from "../../errors"; import { TypeExpressionParser } from "./typeExpressionParser"; +import { Type } from "./types"; describe("test parser", () => { let parser = new TypeExpressionParser(); @@ -102,54 +102,53 @@ describe("test parser", () => { ], }); - type = parser.parse("MultiArg, List>"); assert.deepEqual(type.toJSON(), { - "name": "MultiArg", - "typeParameters": [ + name: "MultiArg", + typeParameters: [ { - "name": "Option", - "typeParameters": [ + name: "Option", + typeParameters: [ { - "name": "u8", - "typeParameters": [] - } - ] + name: "u8", + typeParameters: [], + }, + ], }, { - "name": "List", - "typeParameters": [ + name: "List", + typeParameters: [ { - "name": "u16", - "typeParameters": [] - } - ] - } - ] + name: "u16", + typeParameters: [], + }, + ], + }, + ], }); type = parser.parse("variadic>"); assert.deepEqual(type.toJSON(), { - "name": "variadic", - "typeParameters": [ + name: "variadic", + typeParameters: [ { - "name": "multi", - "typeParameters": [ + name: "multi", + typeParameters: [ { - "name": "array32", - "typeParameters": [] + name: "array32", + typeParameters: [], }, { - "name": "u32", - "typeParameters": [] + name: "u32", + typeParameters: [], }, { - "name": "array64", - "typeParameters": [] - } - ] - } - ] + name: "array64", + typeParameters: [], + }, + ], + }, + ], }); }); @@ -195,8 +194,6 @@ describe("test parser", () => { ], }); - // TODO: In a future PR, replace the JSON-based parsing logic with a better one and enable this test. - // This test currently fails because JSON key de-duplication takes place: i32 is incorrectly de-duplicated by the parser. type = parser.parse("tuple2"); assert.deepEqual(type.toJSON(), { name: "tuple2", @@ -222,7 +219,7 @@ describe("test parser", () => { { name: "u64", typeParameters: [], - } + }, ], }, { @@ -231,13 +228,78 @@ describe("test parser", () => { { name: "u64", typeParameters: [], - } + }, + ], + }, + ], + }); + }); + + it("should parse ", () => { + let type: Type; + type = parser.parse("variadic>"); + assert.deepEqual(type.toJSON(), { + name: "variadic", + typeParameters: [ + { + name: "multi", + typeParameters: [ + { + name: "BigUint", + typeParameters: [], + }, + { + name: "BigUint", + typeParameters: [], + }, + { + name: "u64", + typeParameters: [], + }, + { + name: "BigUint", + typeParameters: [], + }, ], }, ], }); }); + it("should parse multi", () => { + const type = parser.parse("multi"); + + assert.deepEqual(type.toJSON(), { + name: "multi", + typeParameters: [ + { + name: "u8", + typeParameters: [], + }, + { + name: "utf-8 string", + typeParameters: [], + }, + { + name: "u8", + typeParameters: [], + }, + { + name: "utf-8 string", + typeParameters: [], + }, + { + name: "u8", + typeParameters: [], + }, + { + name: "utf-8 string", + typeParameters: [], + }, + ], + }); + }); + it("should handle utf-8 string types which contain spaces", () => { let type: Type; @@ -264,14 +326,12 @@ describe("test parser", () => { }, ], }); - }); it("should not parse expression", () => { - assert.throw(() => parser.parse("<>"), errors.ErrTypingSystem); - assert.throw(() => parser.parse("<"), errors.ErrTypingSystem); - // TODO: In a future PR replace Json Parsing logic with a better one and enable this test - //assert.throw(() => parser.parse("MultiResultVec"), errors.ErrTypingSystem); - assert.throw(() => parser.parse("a, b"), errors.ErrTypingSystem); + assert.throw(() => parser.parse("<>"), ErrTypingSystem); + assert.throw(() => parser.parse("<"), ErrTypingSystem); + assert.throw(() => parser.parse("MultiResultVec"), ErrTypingSystem); + assert.throw(() => parser.parse("a, b"), ErrTypingSystem); }); }); diff --git a/src/smartcontracts/typesystem/typeExpressionParser.ts b/src/smartcontracts/typesystem/typeExpressionParser.ts index 564bf8bef..62d2216c5 100644 --- a/src/smartcontracts/typesystem/typeExpressionParser.ts +++ b/src/smartcontracts/typesystem/typeExpressionParser.ts @@ -1,95 +1,31 @@ -import * as errors from "../../errors"; +import { TypeFormula } from "../../abi/typeFormula"; +import { TypeFormulaParser } from "../../abi/typeFormulaParser"; +import { ErrTypingSystem } from "../../errors"; import { Type } from "./types"; -const jsonHandler = require("json-duplicate-key-handle"); export class TypeExpressionParser { - parse(expression: string): Type { - let root = this.doParse(expression); - let rootKeys = Object.keys(root); - - if (rootKeys.length != 1) { - throw new errors.ErrTypingSystem(`bad type expression: ${expression}`); - } + private readonly backingTypeFormulaParser: TypeFormulaParser; - let name = rootKeys[0]; - let type = this.nodeToType(name, root[name]); - return type; + constructor() { + this.backingTypeFormulaParser = new TypeFormulaParser(); } - private doParse(expression: string): any { - let jsoned = this.getJsonedString(expression); - + parse(expression: string): Type { try { - return jsonHandler.parse(jsoned); - } catch (error) { - throw new errors.ErrTypingSystem(`cannot parse type expression: ${expression}. internal json: ${jsoned}.`); + return this.doParse(expression); + } catch (e) { + throw new ErrTypingSystem(`Failed to parse type expression: ${expression}. Error: ${e}`); } } - /** - * Converts a raw type expression to a JSON, parsing-friendly format. - * This is a workaround, so that the parser implementation is simpler (thus we actually rely on the JSON parser). - * - * @param expression a string such as: - * - * ``` - * - Option> - * - VarArgs> - * - MultiResultVec - * ``` - */ - private getJsonedString(expression: string) { - let jsoned = ""; - - for (let i = 0; i < expression.length; i++) { - let char = expression.charAt(i); - let previousChar = expression.charAt(i - 1); - let nextChar = expression.charAt(i + 1); - - if (char == "<") { - jsoned += ": {"; - } else if (char == ">") { - if (previousChar != ">") { - jsoned += ": {} }"; - } else { - jsoned += "}"; - } - } else if (char == ",") { - if (nextChar == ">") { - // Skip superfluous comma - } else if (previousChar == ">") { - jsoned += ","; - } else { - jsoned += ": {},"; - } - } else { - jsoned += char; - } - } - - // Split by the delimiters, but exclude the spaces that are found in the middle of "utf-8 string" - let symbolsRegex = /(:|\{|\}|,|\s)/; - let tokens = jsoned - // Hack for Safari compatibility, where we can't use negative lookbehind - .replace(/utf\-8\sstring/ig, "utf-8-string") - .split(symbolsRegex) - .filter((token) => token); - - jsoned = tokens.map((token) => (symbolsRegex.test(token) ? token : `"${token}"`)) - .map((token) => token.replace(/utf\-8\-string/ig, "utf-8 string")) - .join(""); - - if (tokens.length == 1) { - // Workaround for simple, non-generic types. - return `{${jsoned}: {}}`; - } - - return `{${jsoned}}`; + private doParse(expression: string): Type { + const typeFormula = this.backingTypeFormulaParser.parseExpression(expression); + const type = this.typeFormulaToType(typeFormula); + return type; } - private nodeToType(name: string, node: any): Type { - if (name.charAt(name.length - 1) === "1") { name = name.slice(0, -1); } - let typeParameters = Object.keys(node).map((key) => this.nodeToType(key, node[key])); - return new Type(name, typeParameters); + private typeFormulaToType(typeFormula: TypeFormula): Type { + const typeParameters = typeFormula.typeParameters.map((typeFormula) => this.typeFormulaToType(typeFormula)); + return new Type(typeFormula.name, typeParameters); } } From 7cabc3a2baad318509b59eeafbfa451d72f4bd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 14:25:29 +0200 Subject: [PATCH 138/275] Adjust package lock. --- package-lock.json | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 37071db97..f4fa10620 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.4", + "version": "13.0.0-beta.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.4", + "version": "13.0.0-beta.5", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -14,7 +14,6 @@ "blake2b": "2.1.3", "buffer": "6.0.3", "json-bigint": "1.0.0", - "json-duplicate-key-handle": "1.0.0", "keccak": "3.0.2", "protobufjs": "7.2.4" }, @@ -1489,11 +1488,6 @@ "babylon": "bin/babylon.js" } }, - "node_modules/backslash": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/backslash/-/backslash-0.2.0.tgz", - "integrity": "sha512-Avs+8FUZ1HF/VFP4YWwHQZSGzRPm37ukU1JQYQWijuHhtXdOuAzcZ8PcAzfIw898a8PyBzdn+RtnKA6MzW0X2A==" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3700,14 +3694,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/json-duplicate-key-handle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-duplicate-key-handle/-/json-duplicate-key-handle-1.0.0.tgz", - "integrity": "sha512-OLIxL+UpfwUsqcLX3i6Z51ChTou/Vje+6bSeGUSubj96dF/SfjObDprLy++ZXYH07KITuEzsXS7PX7e/BGf4jw==", - "dependencies": { - "backslash": "^0.2.0" - } - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6765,11 +6751,6 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, - "backslash": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/backslash/-/backslash-0.2.0.tgz", - "integrity": "sha512-Avs+8FUZ1HF/VFP4YWwHQZSGzRPm37ukU1JQYQWijuHhtXdOuAzcZ8PcAzfIw898a8PyBzdn+RtnKA6MzW0X2A==" - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -8488,14 +8469,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "json-duplicate-key-handle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-duplicate-key-handle/-/json-duplicate-key-handle-1.0.0.tgz", - "integrity": "sha512-OLIxL+UpfwUsqcLX3i6Z51ChTou/Vje+6bSeGUSubj96dF/SfjObDprLy++ZXYH07KITuEzsXS7PX7e/BGf4jw==", - "requires": { - "backslash": "^0.2.0" - } - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", From df7c920aa3b73ac581c16806f4c0712a4f509b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 14:34:14 +0200 Subject: [PATCH 139/275] Fix after self-review. --- src/abi/typeFormulaParser.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 0399ab5f6..4dbb1bcf9 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -83,9 +83,7 @@ export class TypeFormulaParser { const tokens: string[] = []; let currentToken = ""; - for (let i = 0; i < expression.length; i++) { - const character = expression[i]; - + for (const character of expression) { if (!TypeFormulaParser.PUNCTUATION.includes(character)) { // Non-punctuation character currentToken += character; From a5275439a9c2a35e822eb734c261004d58b7606b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 14:39:47 +0200 Subject: [PATCH 140/275] Add extra comments. --- src/abi/typeFormulaParser.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 4dbb1bcf9..caeb7fd2a 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -22,16 +22,18 @@ export class TypeFormulaParser { if (token === TypeFormulaParser.END_TYPE_PARAMETERS) { const type_parameters: TypeFormula[] = []; + // Parse type parameters while (true) { if (stack.length === 0) { throw new Error("Badly specified type parameters."); } + // If top of stack is "<", we're done with type parameters. if (stack[stack.length - 1] === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { break; } - let item = stack.pop(); + const item = stack.pop(); let type_formula: TypeFormula; if (item instanceof TypeFormula) { @@ -89,7 +91,9 @@ export class TypeFormulaParser { currentToken += character; } else { if (currentToken) { + // Retain current token tokens.push(currentToken.trim()); + // Reset current token currentToken = ""; } @@ -99,6 +103,7 @@ export class TypeFormulaParser { } if (currentToken) { + // Retain the last token (if any) tokens.push(currentToken.trim()); } From 32c3d599f2843722c6a5242c920d079ee786c10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 18:21:46 +0200 Subject: [PATCH 141/275] Refactor (extract method). --- src/abi/typeFormulaParser.ts | 53 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index caeb7fd2a..19b6290c0 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -20,30 +20,7 @@ export class TypeFormulaParser { for (const token of tokens) { if (TypeFormulaParser.PUNCTUATION.includes(token)) { if (token === TypeFormulaParser.END_TYPE_PARAMETERS) { - const type_parameters: TypeFormula[] = []; - - // Parse type parameters - while (true) { - if (stack.length === 0) { - throw new Error("Badly specified type parameters."); - } - - // If top of stack is "<", we're done with type parameters. - if (stack[stack.length - 1] === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { - break; - } - - const item = stack.pop(); - let type_formula: TypeFormula; - - if (item instanceof TypeFormula) { - type_formula = item; - } else { - type_formula = new TypeFormula(item, []); - } - - type_parameters.push(type_formula); - } + const type_parameters = this.acquireTypeParameters(stack); stack.pop(); // pop "<" symbol const type_name = stack.pop(); @@ -109,4 +86,32 @@ export class TypeFormulaParser { return tokens; } + + private acquireTypeParameters(stack: any[]): TypeFormula[] { + const type_parameters: TypeFormula[] = []; + + while (true) { + if (stack.length === 0) { + throw new Error("Badly specified type parameters."); + } + + // If top of stack is "<", we're done with type parameters. + if (stack[stack.length - 1] === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { + break; + } + + const item = stack.pop(); + let type_formula: TypeFormula; + + if (item instanceof TypeFormula) { + type_formula = item; + } else { + type_formula = new TypeFormula(item, []); + } + + type_parameters.push(type_formula); + } + + return type_parameters; + } } From 372135a3d0797ca273242ba68153eed06b7e8d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 18:37:37 +0200 Subject: [PATCH 142/275] Refactoring. --- src/abi/typeFormulaParser.ts | 48 +++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 19b6290c0..96938c57a 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -14,19 +14,14 @@ export class TypeFormulaParser { expression = expression.trim(); const tokens = this.tokenizeExpression(expression).filter((token) => token !== TypeFormulaParser.COMMA); - const stack: any[] = []; for (const token of tokens) { - if (TypeFormulaParser.PUNCTUATION.includes(token)) { - if (token === TypeFormulaParser.END_TYPE_PARAMETERS) { - const type_parameters = this.acquireTypeParameters(stack); - - stack.pop(); // pop "<" symbol - const type_name = stack.pop(); - const type_formula = new TypeFormula(type_name, type_parameters.reverse()); + if (this.isPunctuation(token)) { + if (this.isEndOfTypeParameters(token)) { + const type_formula = this.acquireTypeWithParameters(stack); stack.push(type_formula); - } else if (token === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { + } else if (this.isBeginningOfTypeParameters(token)) { // The symbol is pushed as a simple string, // as it will never be interpreted, anyway. stack.push(token); @@ -63,7 +58,7 @@ export class TypeFormulaParser { let currentToken = ""; for (const character of expression) { - if (!TypeFormulaParser.PUNCTUATION.includes(character)) { + if (!this.isPunctuation(character)) { // Non-punctuation character currentToken += character; } else { @@ -87,6 +82,13 @@ export class TypeFormulaParser { return tokens; } + private acquireTypeWithParameters(stack: any[]): TypeFormula { + const type_parameters = this.acquireTypeParameters(stack); + const type_name = stack.pop(); + const type_formula = new TypeFormula(type_name, type_parameters.reverse()); + return type_formula; + } + private acquireTypeParameters(stack: any[]): TypeFormula[] { const type_parameters: TypeFormula[] = []; @@ -95,23 +97,35 @@ export class TypeFormulaParser { throw new Error("Badly specified type parameters."); } - // If top of stack is "<", we're done with type parameters. - if (stack[stack.length - 1] === TypeFormulaParser.BEGIN_TYPE_PARAMETERS) { + const topOfStack = stack[stack.length - 1]; + if (this.isBeginningOfTypeParameters(topOfStack)) { + stack.pop(); break; } const item = stack.pop(); - let type_formula: TypeFormula; if (item instanceof TypeFormula) { - type_formula = item; + type_parameters.push(item); + } else if (typeof item === "string") { + type_parameters.push(new TypeFormula(item, [])); } else { - type_formula = new TypeFormula(item, []); + throw new Error(`Unexpected type parameter object in stack: ${item}`); } - - type_parameters.push(type_formula); } return type_parameters; } + + private isPunctuation(token: string): boolean { + return TypeFormulaParser.PUNCTUATION.includes(token); + } + + private isEndOfTypeParameters(token: string): boolean { + return token === TypeFormulaParser.END_TYPE_PARAMETERS; + } + + private isBeginningOfTypeParameters(token: string): boolean { + return token === TypeFormulaParser.BEGIN_TYPE_PARAMETERS; + } } From adf72efacbfd8b2f81d6b2535491ffab656e8f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 18:44:43 +0200 Subject: [PATCH 143/275] Refactoring. --- src/abi/typeFormulaParser.ts | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 96938c57a..560743bbd 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -19,8 +19,8 @@ export class TypeFormulaParser { for (const token of tokens) { if (this.isPunctuation(token)) { if (this.isEndOfTypeParameters(token)) { - const type_formula = this.acquireTypeWithParameters(stack); - stack.push(type_formula); + const typeFormula = this.acquireTypeWithParameters(stack); + stack.push(typeFormula); } else if (this.isBeginningOfTypeParameters(token)) { // The symbol is pushed as a simple string, // as it will never be interpreted, anyway. @@ -83,38 +83,39 @@ export class TypeFormulaParser { } private acquireTypeWithParameters(stack: any[]): TypeFormula { - const type_parameters = this.acquireTypeParameters(stack); - const type_name = stack.pop(); - const type_formula = new TypeFormula(type_name, type_parameters.reverse()); - return type_formula; + const typeParameters = this.acquireTypeParameters(stack); + const typeName = stack.pop(); + const typeFormula = new TypeFormula(typeName, typeParameters.reverse()); + return typeFormula; } private acquireTypeParameters(stack: any[]): TypeFormula[] { - const type_parameters: TypeFormula[] = []; + const typeParameters: TypeFormula[] = []; while (true) { - if (stack.length === 0) { - throw new Error("Badly specified type parameters."); + const item = stack.pop(); + + if (item === undefined) { + throw new Error("Badly specified type parameters"); } - const topOfStack = stack[stack.length - 1]; - if (this.isBeginningOfTypeParameters(topOfStack)) { - stack.pop(); + if (this.isBeginningOfTypeParameters(item)) { + // We've acquired all type parameters break; } - const item = stack.pop(); - if (item instanceof TypeFormula) { - type_parameters.push(item); + // Type parameter is a previously-acquired type + typeParameters.push(item); } else if (typeof item === "string") { - type_parameters.push(new TypeFormula(item, [])); + // Type parameter is a simple, non-generic type + typeParameters.push(new TypeFormula(item, [])); } else { throw new Error(`Unexpected type parameter object in stack: ${item}`); } } - return type_parameters; + return typeParameters; } private isPunctuation(token: string): boolean { From 531281f2a535c79474882b418cda4377e4644a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 12 Mar 2024 19:13:34 +0200 Subject: [PATCH 144/275] Refactoring. --- src/abi/typeFormulaParser.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 560743bbd..8d720f058 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -22,8 +22,7 @@ export class TypeFormulaParser { const typeFormula = this.acquireTypeWithParameters(stack); stack.push(typeFormula); } else if (this.isBeginningOfTypeParameters(token)) { - // The symbol is pushed as a simple string, - // as it will never be interpreted, anyway. + // This symbol is pushed as a simple string. stack.push(token); } else { throw new Error(`Unexpected token (punctuation): ${token}`); @@ -43,11 +42,11 @@ export class TypeFormulaParser { const item = stack[0]; - if (typeof item === "string") { - // Expression contained a simple, non-generic type - return new TypeFormula(item, []); - } else if (item instanceof TypeFormula) { + if (item instanceof TypeFormula) { return item; + } else if (typeof item === "string") { + // Expression contained a simple, non-generic type. + return new TypeFormula(item, []); } else { throw new Error(`Unexpected item on stack: ${item}`); } @@ -75,7 +74,7 @@ export class TypeFormulaParser { } if (currentToken) { - // Retain the last token (if any) + // Retain the last token (if any). tokens.push(currentToken.trim()); } @@ -100,15 +99,15 @@ export class TypeFormulaParser { } if (this.isBeginningOfTypeParameters(item)) { - // We've acquired all type parameters + // We've acquired all type parameters. break; } if (item instanceof TypeFormula) { - // Type parameter is a previously-acquired type + // Type parameter is a previously-acquired type. typeParameters.push(item); } else if (typeof item === "string") { - // Type parameter is a simple, non-generic type + // Type parameter is a simple, non-generic type. typeParameters.push(new TypeFormula(item, [])); } else { throw new Error(`Unexpected type parameter object in stack: ${item}`); From 4039cb44528e184b2621f30bf196f32569072f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 12:37:08 +0200 Subject: [PATCH 145/275] Minor refactoring. --- src/abi/typeFormulaParser.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/abi/typeFormulaParser.ts b/src/abi/typeFormulaParser.ts index 8d720f058..02e7b9612 100644 --- a/src/abi/typeFormulaParser.ts +++ b/src/abi/typeFormulaParser.ts @@ -57,10 +57,7 @@ export class TypeFormulaParser { let currentToken = ""; for (const character of expression) { - if (!this.isPunctuation(character)) { - // Non-punctuation character - currentToken += character; - } else { + if (this.isPunctuation(character)) { if (currentToken) { // Retain current token tokens.push(currentToken.trim()); @@ -70,6 +67,8 @@ export class TypeFormulaParser { // Punctuation character tokens.push(character); + } else { + currentToken += character; } } From c47cb8ef4fda347585e121b0d26251cb37958855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 15:06:23 +0200 Subject: [PATCH 146/275] Fix after review (partial). --- src/smartcontracts/smartContract.ts | 12 ++++++------ src/transaction.ts | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 0217c5f7f..a43c60042 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -118,7 +118,7 @@ export class SmartContract implements ISmartContract { Compatibility.guardAddressIsSetAndNonZero(deployer, "'deployer' of SmartContract.deploy()", "pass the actual address to deploy()"); const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); - const scNextTransactionFactory = new SmartContractTransactionsFactory({ + const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -127,7 +127,7 @@ export class SmartContract implements ISmartContract { const bytecode = Buffer.from(code.toString(), 'hex'); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const transaction = scNextTransactionFactory.createTransactionForDeploy({ + const transaction = factory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: BigInt(gasLimit.valueOf()), @@ -177,7 +177,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); - const scNextTransactionFactory = new SmartContractTransactionsFactory({ + const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -186,7 +186,7 @@ export class SmartContract implements ISmartContract { const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); - const transaction = scNextTransactionFactory.createTransactionForUpgrade({ + const transaction = factory.createTransactionForUpgrade({ sender: caller, contract: this.getAddress(), bytecode: bytecode, @@ -214,7 +214,7 @@ export class SmartContract implements ISmartContract { this.ensureHasAddress(); const config = new TransactionsFactoryConfig({ chainID: chainID.valueOf() }); - const scNextTransactionFactory = new SmartContractTransactionsFactory({ + const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, tokenComputer: new TokenComputer() @@ -223,7 +223,7 @@ export class SmartContract implements ISmartContract { args = args || []; value = value || 0; - const transaction = scNextTransactionFactory.createTransactionForExecute({ + const transaction = factory.createTransactionForExecute({ sender: caller, contract: receiver ? receiver : this.getAddress(), functionName: func.toString(), diff --git a/src/transaction.ts b/src/transaction.ts index b6fa42d8a..6125e0f96 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -42,12 +42,12 @@ export class Transaction { public value: bigint; /** - * The address of the sender. + * The address of the sender, in bech32 format. */ public sender: string; /** - * The address of the receiver. + * The address of the receiver, in bech32 format. */ public receiver: string; @@ -92,7 +92,7 @@ export class Transaction { public options: number; /** - * The address of the guardian. + * The address of the guardian, in bech32 format. */ public guardian: string; From 82f088c20922e532f606b76705ad6701f4439a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 16:47:30 +0200 Subject: [PATCH 147/275] Fix after review (partial). --- src/transaction.ts | 56 ++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 6125e0f96..6a4d39c96 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -114,23 +114,7 @@ export class Transaction { /** * Creates a new Transaction object. */ - public constructor({ - nonce, - value, - sender, - receiver, - senderUsername, - receiverUsername, - gasPrice, - gasLimit, - data, - chainID, - version, - options, - guardian, - signature, - guardianSignature, - }: { + public constructor(options: { nonce?: INonce | bigint; value?: ITransactionValue | bigint; sender?: IAddress | string; @@ -147,35 +131,39 @@ export class Transaction { signature?: Uint8Array; guardianSignature?: Uint8Array; }) { - this.nonce = BigInt(nonce?.valueOf() || 0n); + this.nonce = BigInt(options.nonce?.valueOf() || 0n); // We still rely on "bigNumber" for value, because client code might be passing a BigNumber object as a legacy "ITransactionValue", // and we want to keep compatibility. - this.value = value ? BigInt(new BigNumber(value.toString()).toFixed(0)) : 0n; - this.sender = sender ? (typeof sender === "string" ? sender : sender.bech32()) : ""; - this.receiver = receiver ? (typeof receiver === "string" ? receiver : receiver.bech32()) : ""; - this.senderUsername = senderUsername || ""; - this.receiverUsername = receiverUsername || ""; - this.gasPrice = BigInt(gasPrice?.valueOf() || TRANSACTION_MIN_GAS_PRICE); - this.gasLimit = BigInt(gasLimit?.valueOf() || 0n); - this.data = data?.valueOf() || new Uint8Array(); - this.chainID = chainID?.valueOf() || ""; - this.version = version?.valueOf() || TRANSACTION_VERSION_DEFAULT; - this.options = options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; - this.guardian = guardian ? (typeof guardian === "string" ? guardian : guardian.bech32()) : ""; + this.value = options.value ? BigInt(new BigNumber(options.value.toString()).toFixed(0)) : 0n; + this.sender = options.sender ? this.addressAsBech32(options.sender) : ""; + this.receiver = options.receiver ? this.addressAsBech32(options.receiver) : ""; + this.senderUsername = options.senderUsername || ""; + this.receiverUsername = options.receiverUsername || ""; + this.gasPrice = BigInt(options.gasPrice?.valueOf() || TRANSACTION_MIN_GAS_PRICE); + this.gasLimit = BigInt(options.gasLimit?.valueOf() || 0n); + this.data = options.data?.valueOf() || new Uint8Array(); + this.chainID = options.chainID?.valueOf() || ""; + this.version = options.version?.valueOf() || TRANSACTION_VERSION_DEFAULT; + this.options = options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; + this.guardian = options.guardian ? this.addressAsBech32(options.guardian) : ""; this.signature = Buffer.from([]); this.guardianSignature = Buffer.from([]); this.hash = TransactionHash.empty(); // Legacy logic, will be kept for some time, to avoid breaking changes in behavior. - if (signature?.length) { - this.applySignature(signature); + if (options.signature?.length) { + this.applySignature(options.signature); } - if (guardianSignature?.length) { - this.applyGuardianSignature(guardianSignature); + if (options.guardianSignature?.length) { + this.applyGuardianSignature(options.guardianSignature); } } + private addressAsBech32(address: IAddress | string): string { + return typeof address === "string" ? address : address.bech32(); + } + /** * Legacy method, use the "nonce" property instead. */ From a1d4abd8494647d2306a942e103330049c2585ac Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 13 Mar 2024 16:59:04 +0200 Subject: [PATCH 148/275] fix token managent transactions parser according to specs --- ...anagementTransactionsOutcomeParser.spec.ts | 137 +++++--- ...okenManagementTransactionsOutcomeParser.ts | 331 +++++++++--------- 2 files changed, 258 insertions(+), 210 deletions(-) diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index a95813f81..cecccfaf0 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -44,7 +44,8 @@ describe("test token management transactions outcome parser", () => { const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse issue non fungible", () => { @@ -77,7 +78,8 @@ describe("test token management transactions outcome parser", () => { const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueNonFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse issue semi fungible", () => { @@ -98,7 +100,8 @@ describe("test token management transactions outcome parser", () => { const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseIssueSemiFungible(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse register meta esdt", () => { @@ -119,34 +122,51 @@ describe("test token management transactions outcome parser", () => { const txOutcome = new TransactionOutcome({ transactionLogs: logs }); const outcome = parser.parseRegisterMetaEsdt(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse register and set all roles", () => { - const identifier = "LMAO-d9f892"; - const base64Identifier = Buffer.from(identifier).toString("base64"); + const firstIdentifier = "LMAO-d9f892"; + const firstBase64Identifier = Buffer.from(firstIdentifier).toString("base64"); + + const secondIdentifier = "TST-123456"; + const secondBase64Identifier = Buffer.from(secondIdentifier).toString("base64"); + const roles = ["ESDTRoleLocalMint", "ESDTRoleLocalBurn"]; - const event = new TransactionEvent({ + const firstEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "registerAndSetAllRoles", - topics: [base64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], + topics: [firstBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], + }); + + const secondEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "registerAndSetAllRoles", + topics: [secondBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], }); const transactionLogs = new TransactionLogs({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", - events: [event], + events: [firstEvent, secondEvent], }); - const resultEvent = new TransactionEvent({ + const firstResultEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTSetRole", topics: ["TE1BTy1kOWY4OTI=", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="], }); + const secondResultEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "ESDTSetRole", + topics: ["VFNULTEyMzQ1Ng==", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="], + }); + const resultLogs = new TransactionLogs({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", - events: [resultEvent], + events: [firstResultEvent, secondResultEvent], }); const scResult = new SmartContractResult({ @@ -165,8 +185,13 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseRegisterAndSetAllRoles(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); - assert.deepEqual(outcome.roles, roles); + assert.lengthOf(outcome, 2); + + assert.equal(outcome[0].tokenIdentifier, firstIdentifier); + assert.deepEqual(outcome[0].roles, roles); + + assert.equal(outcome[1].tokenIdentifier, secondIdentifier); + assert.deepEqual(outcome[1].roles, roles); }); it("should test parse register set special role", () => { @@ -197,9 +222,10 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseSetSpecialRole(txOutcome); - assert.equal(outcome.userAddress, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); - assert.equal(outcome.tokenIdentifier, identifier); - assert.deepEqual(outcome.roles, roles); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.deepEqual(outcome[0].roles, roles); }); it("should test parse nft create", () => { @@ -229,9 +255,10 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseNftCreate(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.initialQuantity, initialQuantity); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].initialQuantity, initialQuantity); }); it("should test parse local mint", () => { @@ -256,10 +283,11 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseLocalMint(txOutcome); - assert.equal(outcome.userAddress, event.address); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.mintedSupply, mintedSupply); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, event.address); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].mintedSupply, mintedSupply); }); it("should test parse local burn", () => { @@ -284,10 +312,11 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseLocalBurn(txOutcome); - assert.equal(outcome.userAddress, event.address); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.burntSupply, burntSupply); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, event.address); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].burntSupply, burntSupply); }); it("should test parse pause", () => { @@ -310,7 +339,8 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parsePause(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse unpause", () => { @@ -333,7 +363,8 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseUnpause(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); }); it("should test parse freeze", () => { @@ -366,10 +397,11 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseFreeze(txOutcome); - assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.balance, balance); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, address); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].balance, balance); }); it("should test parse unfreeze", () => { @@ -402,10 +434,11 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseUnfreeze(txOutcome); - assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.balance, balance); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, address); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].balance, balance); }); it("should test parse wipe", () => { @@ -438,10 +471,11 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseWipe(txOutcome); - assert.equal(outcome.userAddress, address); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.balance, balance); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].userAddress, address); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].balance, balance); }); it("should test parse update attributes", () => { @@ -467,9 +501,10 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseUpdateAttributes(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(Buffer.from(outcome.attributes).toString(), attributes); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(Buffer.from(outcome[0].attributes).toString(), attributes); }); it("should test parse add quantity", () => { @@ -494,9 +529,10 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseAddQuantity(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.addedQuantity, addedQuantity); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].addedQuantity, addedQuantity); }); it("should test parse burn quantity", () => { @@ -521,8 +557,9 @@ describe("test token management transactions outcome parser", () => { }); const outcome = parser.parseBurnQuantity(txOutcome); - assert.equal(outcome.tokenIdentifier, identifier); - assert.equal(outcome.nonce, nonce); - assert.equal(outcome.burntQuantity, burntQuantity); + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].tokenIdentifier, identifier); + assert.equal(outcome[0].nonce, nonce); + assert.equal(outcome[0].burntQuantity, burntQuantity); }); }); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index f9b389ebc..b0cb15aa9 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -6,57 +6,53 @@ import { bufferToBigInt } from "../smartcontracts/codec/utils"; export class TokenManagementTransactionsOutcomeParser { constructor() {} - parseIssueFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parseIssueFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "issue"); - const identifier = this.extractTokenIdentifier(event); - - return { tokenIdentifier: identifier }; + const events = this.findEventsByIdentifier(transactionOutcome, "issue"); + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } - parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "issueNonFungible"); - const identifier = this.extractTokenIdentifier(event); - - return { tokenIdentifier: identifier }; + const events = this.findEventsByIdentifier(transactionOutcome, "issueNonFungible"); + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } - parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "issueSemiFungible"); - const identifier = this.extractTokenIdentifier(event); - - return { tokenIdentifier: identifier }; + const events = this.findEventsByIdentifier(transactionOutcome, "issueSemiFungible"); + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } - parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "registerMetaESDT"); - const identifier = this.extractTokenIdentifier(event); - - return { tokenIdentifier: identifier }; + const events = this.findEventsByIdentifier(transactionOutcome, "registerMetaESDT"); + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } - parseRegisterAndSetAllRoles(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; roles: string[] } { + parseRegisterAndSetAllRoles( + transactionOutcome: TransactionOutcome, + ): { tokenIdentifier: string; roles: string[] }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); + const registerEvents = this.findEventsByIdentifier(transactionOutcome, "registerAndSetAllRoles"); + const setRoleEvents = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); - const registerEvent = this.findSingleEventByIdentifier(transactionOutcome, "registerAndSetAllRoles"); - const tokenIdentifier = this.extractTokenIdentifier(registerEvent); - - const setRoleEvent = this.findSingleEventByIdentifier(transactionOutcome, "ESDTSetRole"); - const encodedRoles = setRoleEvent.topics.slice(3); - - let roles: string[] = []; - for (const role of encodedRoles) { - roles = roles.concat(this.decodeTopicAsString(role)); + if (registerEvents.length !== setRoleEvents.length) { + throw new ErrParseTransactionOutcome( + "Register Events and Set Role events mismatch. Should have the same number of events.", + ); } - return { tokenIdentifier: tokenIdentifier, roles: roles }; + return registerEvents.map((registerEvent, index) => { + const tokenIdentifier = this.extractTokenIdentifier(registerEvent); + const encodedRoles = setRoleEvents[index].topics.slice(3); + const roles = encodedRoles.map((role) => this.decodeTopicAsString(role)); + return { tokenIdentifier, roles }; + }); } parseSetBurnRoleGlobally(transactionOutcome: TransactionOutcome) { @@ -71,36 +67,37 @@ export class TokenManagementTransactionsOutcomeParser { userAddress: string; tokenIdentifier: string; roles: string[]; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTSetRole"); - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - - const encodedRoles = event.topics.slice(3); + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); - let roles: string[] = []; - for (const role of encodedRoles) { - roles = roles.concat(this.decodeTopicAsString(role)); - } + return events.map((event) => { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const encodedRoles = event.topics.slice(3); + const roles = encodedRoles.map((role) => this.decodeTopicAsString(role)); - return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; + return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; + }); } parseNftCreate(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; nonce: bigint; initialQuantity: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTCreate"); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const amount = this.extractAmount(event); + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTCreate"); + + return events.map((event) => { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const amount = this.extractAmount(event); - return { tokenIdentifier: tokenIdentifier, nonce: nonce, initialQuantity: amount }; + return { tokenIdentifier: tokenIdentifier, nonce: nonce, initialQuantity: amount }; + }); } parseLocalMint(transactionOutcome: TransactionOutcome): { @@ -108,21 +105,24 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; nonce: bigint; mintedSupply: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTLocalMint"); - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const mintedSupply = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - mintedSupply: mintedSupply, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalMint"); + + return events.map((event) => { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const mintedSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + mintedSupply: mintedSupply, + }; + }); } parseLocalBurn(transactionOutcome: TransactionOutcome): { @@ -130,39 +130,39 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; nonce: bigint; burntSupply: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTLocalBurn"); - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const burntSupply = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - burntSupply: burntSupply, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalBurn"); + + return events.map((event) => { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntSupply: burntSupply, + }; + }); } - parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTPause"); - const tokenIdentifier = this.extractTokenIdentifier(event); + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTPause"); - return { tokenIdentifier: tokenIdentifier }; + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } - parseUnpause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string } { + parseUnpause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTUnPause"); - const tokenIdentifier = this.extractTokenIdentifier(event); - - return { tokenIdentifier: tokenIdentifier }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnPause"); + return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseFreeze(transactionOutcome: TransactionOutcome): { @@ -170,21 +170,24 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; nonce: bigint; balance: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTFreeze"); - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTFreeze"); + + return events.map((event) => { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + }); } parseUnfreeze(transactionOutcome: TransactionOutcome): { @@ -192,21 +195,24 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; nonce: bigint; balance: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTUnFreeze"); - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnFreeze"); + + return events.map((event) => { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + }); } parseWipe(transactionOutcome: TransactionOutcome): { @@ -214,78 +220,86 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; nonce: bigint; balance: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTWipe"); - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTWipe"); + return events.map((event) => { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; + }); } parseUpdateAttributes(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; nonce: bigint; attributes: Uint8Array; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - attributes: attributes, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); + return events.map((event) => { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + attributes: attributes, + }; + }); } parseAddQuantity(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; nonce: bigint; addedQuantity: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const addedQuantity = this.extractAmount(event); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - addedQuantity: addedQuantity, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); + return events.map((event) => { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const addedQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + addedQuantity: addedQuantity, + }; + }); } parseBurnQuantity(transactionOutcome: TransactionOutcome): { tokenIdentifier: string; nonce: bigint; burntQuantity: bigint; - } { + }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const event = this.findSingleEventByIdentifier(transactionOutcome, "ESDTNFTBurn"); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const burntQuantity = this.extractAmount(event); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - burntQuantity: burntQuantity, - }; + const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTBurn"); + return events.map((event) => { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntQuantity: burntQuantity, + }; + }); } private ensureNoError(transactionEvents: TransactionEvent[]) { @@ -301,17 +315,14 @@ export class TokenManagementTransactionsOutcomeParser { } } - private findSingleEventByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent { + private findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { const events = this.gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); if (events.length == 0) { throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); } - if (events.length > 1) { - throw new ErrParseTransactionOutcome(`more than one event of type ${identifier}`); - } - return events[0]; + return events; } private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { From 6ddacc432d864fe028be31314d21e2681c1a04a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 17:06:28 +0200 Subject: [PATCH 149/275] Fix after review. --- src/transaction.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 6a4d39c96..70f7a719a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -117,14 +117,14 @@ export class Transaction { public constructor(options: { nonce?: INonce | bigint; value?: ITransactionValue | bigint; - sender?: IAddress | string; - receiver?: IAddress | string; + sender: IAddress | string; + receiver: IAddress | string; senderUsername?: string; receiverUsername?: string; gasPrice?: IGasPrice | bigint; - gasLimit?: IGasLimit | bigint; + gasLimit: IGasLimit | bigint; data?: ITransactionPayload | Uint8Array; - chainID?: IChainID | string; + chainID: IChainID | string; version?: ITransactionVersion | number; options?: ITransactionOptions | number; guardian?: IAddress | string; @@ -135,14 +135,14 @@ export class Transaction { // We still rely on "bigNumber" for value, because client code might be passing a BigNumber object as a legacy "ITransactionValue", // and we want to keep compatibility. this.value = options.value ? BigInt(new BigNumber(options.value.toString()).toFixed(0)) : 0n; - this.sender = options.sender ? this.addressAsBech32(options.sender) : ""; - this.receiver = options.receiver ? this.addressAsBech32(options.receiver) : ""; + this.sender = this.addressAsBech32(options.sender); + this.receiver = this.addressAsBech32(options.receiver); this.senderUsername = options.senderUsername || ""; this.receiverUsername = options.receiverUsername || ""; this.gasPrice = BigInt(options.gasPrice?.valueOf() || TRANSACTION_MIN_GAS_PRICE); - this.gasLimit = BigInt(options.gasLimit?.valueOf() || 0n); + this.gasLimit = BigInt(options.gasLimit.valueOf()); this.data = options.data?.valueOf() || new Uint8Array(); - this.chainID = options.chainID?.valueOf() || ""; + this.chainID = options.chainID.valueOf(); this.version = options.version?.valueOf() || TRANSACTION_VERSION_DEFAULT; this.options = options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; this.guardian = options.guardian ? this.addressAsBech32(options.guardian) : ""; From 023ffa4774046ee75c5565c86f688c03febccf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 17:15:25 +0200 Subject: [PATCH 150/275] SerializeForSigning() now calls TransactionComputer. --- src/transaction.ts | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 70f7a719a..8a238fe0f 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -358,28 +358,14 @@ export class Transaction { } /** + * Legacy method, use "TransactionComputer.computeBytesForSigning()" instead. * Serializes a transaction to a sequence of bytes, ready to be signed. * This function is called internally by signers. */ serializeForSigning(): Buffer { - // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash - let plain = this.toPlainObject(); - // Make sure we never sign the transaction with another signature set up (useful when using the same method for verification) - if (plain.signature) { - delete plain.signature; - } - - if (plain.guardianSignature) { - delete plain.guardianSignature; - } - - if (!plain.guardian) { - delete plain.guardian; - } - - let serialized = JSON.stringify(plain); - - return Buffer.from(serialized); + const computer = new TransactionComputer(); + const bytes = computer.computeBytesForSigning(this); + return Buffer.from(bytes); } /** @@ -553,6 +539,7 @@ export class TransactionComputer { computeBytesForSigning(transaction: ITransaction): Uint8Array { // TODO: do some checks for the transaction e.g. sender, chain ID etc. + // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash const plainTransaction = this.toPlainObject(transaction); From c16e60e19425885891356ec023c769024a19722c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 17:22:12 +0200 Subject: [PATCH 151/275] Refactor getHash(), mark it as legacy. --- src/transaction.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 8a238fe0f..bc599e84a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -22,7 +22,6 @@ import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; import { Signature, interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; -import { guardNotEmpty } from "./utils"; const createTransactionHasher = require("blake2b"); const TRANSACTION_HASH_LENGTH = 32; @@ -106,11 +105,6 @@ export class Transaction { */ public guardianSignature: Uint8Array; - /** - * The transaction hash, also used as a transaction identifier. - */ - private hash: TransactionHash; - /** * Creates a new Transaction object. */ @@ -149,7 +143,6 @@ export class Transaction { this.signature = Buffer.from([]); this.guardianSignature = Buffer.from([]); - this.hash = TransactionHash.empty(); // Legacy logic, will be kept for some time, to avoid breaking changes in behavior. if (options.signature?.length) { @@ -353,8 +346,7 @@ export class Transaction { * Legacy method, use "TransactionComputer.computeTransactionHash()" instead. */ getHash(): TransactionHash { - guardNotEmpty(this.hash, "hash"); - return this.hash; + return TransactionHash.compute(this); } /** @@ -452,7 +444,6 @@ export class Transaction { */ applySignature(signature: ISignature | Uint8Array) { this.signature = interpretSignatureAsBuffer(signature); - this.hash = TransactionHash.compute(this); } /** @@ -462,7 +453,6 @@ export class Transaction { */ applyGuardianSignature(guardianSignature: ISignature | Uint8Array) { this.guardianSignature = interpretSignatureAsBuffer(guardianSignature); - this.hash = TransactionHash.compute(this); } /** @@ -487,6 +477,7 @@ export class Transaction { } /** + * Legacy class, use "TransactionComputer.computeTransactionHash()" instead. * An abstraction for handling and computing transaction hashes. */ export class TransactionHash extends Hash { @@ -495,13 +486,13 @@ export class TransactionHash extends Hash { } /** + * Legacy method, use "TransactionComputer.computeTransactionHash()" instead. * Computes the hash of a transaction. */ static compute(transaction: Transaction): TransactionHash { - let serializer = new ProtoSerializer(); - let buffer = serializer.serializeTransaction(transaction); - let hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); - return new TransactionHash(hash); + const computer = new TransactionComputer(); + const hash = computer.computeTransactionHash(transaction); + return new TransactionHash(Buffer.from(hash).toString("hex")); } } From 20def8a30cf5383274ba322319f59be0fae1eab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 18:07:14 +0200 Subject: [PATCH 152/275] Simplify toPlainObject() for signing. --- src/transaction.ts | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index bc599e84a..53b56b168 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -532,22 +532,8 @@ export class TransactionComputer { // TODO: do some checks for the transaction e.g. sender, chain ID etc. // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash - const plainTransaction = this.toPlainObject(transaction); - - if (plainTransaction.signature) { - delete plainTransaction.signature; - } - - if (plainTransaction.guardianSignature) { - delete plainTransaction.guardianSignature; - } - - if (!plainTransaction.guardian) { - delete plainTransaction.guardian; - } - + const plainTransaction = this.toPlainObjectForSigning(transaction); const serialized = JSON.stringify(plainTransaction); - return new Uint8Array(Buffer.from(serialized)); } @@ -560,7 +546,7 @@ export class TransactionComputer { return Buffer.from(hash, "hex"); } - private toPlainObject(transaction: ITransaction) { + private toPlainObjectForSigning(transaction: ITransaction) { return { nonce: Number(transaction.nonce), value: transaction.value.toString(), @@ -582,14 +568,8 @@ export class TransactionComputer { version: transaction.version, options: transaction.options ? transaction.options : undefined, guardian: transaction.guardian ? transaction.guardian : undefined, - signature: - transaction.signature.length == 0 ? undefined : Buffer.from(transaction.signature).toString("hex"), - guardianSignature: - transaction.guardianSignature.length == 0 - ? undefined - : Buffer.from(transaction.guardianSignature).toString("hex"), }; } - // TODO: missing functions from specs, with setting options etc.? + // TODO: add missing functions wrt. specs } From d19f4b0081781c6d755bc231b17fbd3fc9bb6390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 18:20:52 +0200 Subject: [PATCH 153/275] Minor refactoring. --- src/transaction.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index 53b56b168..8405343f2 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -538,8 +538,7 @@ export class TransactionComputer { } computeTransactionHash(transaction: ITransaction): Uint8Array { - let serializer = new ProtoSerializer(); - + const serializer = new ProtoSerializer(); const buffer = serializer.serializeTransaction(new Transaction(transaction)); const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); @@ -552,18 +551,11 @@ export class TransactionComputer { value: transaction.value.toString(), receiver: transaction.receiver, sender: transaction.sender, - senderUsername: transaction.senderUsername - ? Buffer.from(transaction.senderUsername).toString("base64") - : undefined, - receiverUsername: transaction.receiverUsername - ? Buffer.from(transaction.receiverUsername).toString("base64") - : undefined, + senderUsername: this.toBase64OrUndefined(transaction.senderUsername), + receiverUsername: this.toBase64OrUndefined(transaction.receiverUsername), gasPrice: Number(transaction.gasPrice), gasLimit: Number(transaction.gasLimit), - data: - transaction.data && transaction.data.length === 0 - ? undefined - : Buffer.from(transaction.data).toString("base64"), + data: this.toBase64OrUndefined(transaction.data), chainID: transaction.chainID, version: transaction.version, options: transaction.options ? transaction.options : undefined, @@ -571,5 +563,9 @@ export class TransactionComputer { }; } + private toBase64OrUndefined(value?: string | Uint8Array) { + return value && value.length ? Buffer.from(value).toString("base64") : undefined; + } + // TODO: add missing functions wrt. specs } From 6a6a8105f2fbbb4f0c15619b3a603defb290ed19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 13 Mar 2024 19:48:36 +0200 Subject: [PATCH 154/275] Move conversion logic to converters package. --- src/converters/index.ts | 1 + src/converters/transactionsConverter.ts | 64 ++++++++++++++++++++ src/transaction.ts | 77 +++++-------------------- 3 files changed, 79 insertions(+), 63 deletions(-) create mode 100644 src/converters/index.ts create mode 100644 src/converters/transactionsConverter.ts diff --git a/src/converters/index.ts b/src/converters/index.ts new file mode 100644 index 000000000..f0f6ba906 --- /dev/null +++ b/src/converters/index.ts @@ -0,0 +1 @@ +export { TransactionsConverter } from "./transactionsConverter"; diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts new file mode 100644 index 000000000..bcaea6649 --- /dev/null +++ b/src/converters/transactionsConverter.ts @@ -0,0 +1,64 @@ +import { IPlainTransactionObject, ITransaction } from "../interface"; +import { Transaction } from "../transaction"; + +export class TransactionsConverter { + transactionToPlainObject(transaction: ITransaction): IPlainTransactionObject { + const plainObject = { + nonce: Number(transaction.nonce), + value: transaction.value.toString(), + receiver: transaction.receiver, + sender: transaction.sender, + senderUsername: this.toBase64OrUndefined(transaction.senderUsername), + receiverUsername: this.toBase64OrUndefined(transaction.receiverUsername), + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), + data: this.toBase64OrUndefined(transaction.data), + chainID: transaction.chainID.valueOf(), + version: transaction.version, + options: transaction.options == 0 ? undefined : transaction.options, + guardian: transaction.guardian ? transaction.guardian : undefined, + signature: this.toHexOrUndefined(transaction.signature), + guardianSignature: this.toHexOrUndefined(transaction.guardianSignature), + }; + + return plainObject; + } + + private toBase64OrUndefined(value?: string | Uint8Array) { + return value && value.length ? Buffer.from(value).toString("base64") : undefined; + } + + private toHexOrUndefined(value?: Uint8Array) { + return value && value.length ? Buffer.from(value).toString("hex") : undefined; + } + + public plainObjectToTransaction(object: IPlainTransactionObject): Transaction { + const transaction = new Transaction({ + nonce: Number(object.nonce), + value: BigInt(object.value || ""), + receiver: object.receiver, + receiverUsername: this.bufferFromBase64(object.receiverUsername).toString(), + sender: object.sender, + senderUsername: this.bufferFromBase64(object.senderUsername).toString(), + guardian: object.guardian, + gasPrice: Number(object.gasPrice), + gasLimit: Number(object.gasLimit), + data: this.bufferFromBase64(object.data), + chainID: String(object.chainID), + version: object.version, + options: object.options, + signature: this.bufferFromHex(object.signature), + guardianSignature: this.bufferFromHex(object.guardianSignature), + }); + + return transaction; + } + + private bufferFromBase64(value?: string) { + return Buffer.from(value || "", "base64"); + } + + private bufferFromHex(value?: string) { + return Buffer.from(value || "", "hex"); + } +} diff --git a/src/transaction.ts b/src/transaction.ts index 8405343f2..f65c1c0ae 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,6 +1,7 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; +import { TransactionsConverter } from "./converters/transactionsConverter"; import * as errors from "./errors"; import { Hash } from "./hash"; import { @@ -20,7 +21,7 @@ import { import { INetworkConfig } from "./interfaceOfNetwork"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; -import { Signature, interpretSignatureAsBuffer } from "./signature"; +import { interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; const createTransactionHasher = require("blake2b"); @@ -141,16 +142,8 @@ export class Transaction { this.options = options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; this.guardian = options.guardian ? this.addressAsBech32(options.guardian) : ""; - this.signature = Buffer.from([]); - this.guardianSignature = Buffer.from([]); - - // Legacy logic, will be kept for some time, to avoid breaking changes in behavior. - if (options.signature?.length) { - this.applySignature(options.signature); - } - if (options.guardianSignature?.length) { - this.applyGuardianSignature(options.guardianSignature); - } + this.signature = options.signature || Buffer.from([]); + this.guardianSignature = options.guardianSignature || Buffer.from([]); } private addressAsBech32(address: IAddress | string): string { @@ -370,74 +363,31 @@ export class Transaction { } /** - * Legacy method, use the "converters" package instead. + * Legacy method, use "TransactionsConverter.transactionToPlainObject()" instead. * * Converts the transaction object into a ready-to-serialize, plain JavaScript object. * This function is called internally within the signing procedure. */ toPlainObject(): IPlainTransactionObject { - const plainObject = { - nonce: Number(this.nonce), - value: this.value.toString(), - receiver: this.receiver, - sender: this.sender, - senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined, - receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined, - gasPrice: Number(this.gasPrice), - gasLimit: Number(this.gasLimit), - data: this.data.length == 0 ? undefined : Buffer.from(this.data).toString("base64"), - chainID: this.chainID.valueOf(), - version: this.getVersion().valueOf(), - options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(), - guardian: this.guardian ? this.guardian : undefined, - signature: this.signature.length ? this.getSignature().toString("hex") : undefined, - guardianSignature: this.guardianSignature.length ? this.getGuardianSignature().toString("hex") : undefined, - }; - - return plainObject; + // Ideally, "converters" package should be outside of "core", and not referenced here. + const converter = new TransactionsConverter(); + return converter.transactionToPlainObject(this); } /** + * Legacy method, use "TransactionsConverter.plainObjectToTransaction()" instead. * Converts a plain object transaction into a Transaction Object. * * @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject() */ static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction { - const tx = new Transaction({ - nonce: Number(plainObjectTransaction.nonce), - value: new BigNumber(plainObjectTransaction.value).toFixed(0), - receiver: plainObjectTransaction.receiver, - receiverUsername: plainObjectTransaction.receiverUsername - ? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString() - : undefined, - sender: plainObjectTransaction.sender, - senderUsername: plainObjectTransaction.senderUsername - ? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString() - : undefined, - guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined, - gasPrice: Number(plainObjectTransaction.gasPrice), - gasLimit: Number(plainObjectTransaction.gasLimit), - data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")), - chainID: String(plainObjectTransaction.chainID), - version: plainObjectTransaction.version, - options: - plainObjectTransaction.options != null - ? new TransactionOptions(plainObjectTransaction.options) - : undefined, - }); - - if (plainObjectTransaction.signature) { - tx.applySignature(new Signature(plainObjectTransaction.signature)); - } - - if (plainObjectTransaction.guardianSignature) { - tx.applyGuardianSignature(new Signature(plainObjectTransaction.guardianSignature)); - } - - return tx; + // Ideally, "converters" package should be outside of "core", and not referenced here. + const converter = new TransactionsConverter(); + return converter.plainObjectToTransaction(plainObjectTransaction); } /** + * Legacy method, use the "signature" property instead. * Applies the signature on the transaction. * * @param signature The signature, as computed by a signer. @@ -447,6 +397,7 @@ export class Transaction { } /** + * Legacy method, use the "guardianSignature" property instead. * Applies the guardian signature on the transaction. * * @param guardianSignature The signature, as computed by a signer. From 313a452662738cd888be59b7b1496689d2af6245 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 12:39:51 +0200 Subject: [PATCH 155/275] delegation transactions outcome parser --- ...elegationTransactionsOutcomeParser.spec.ts | 61 ++++++++++++++++++ .../delegationTransactionsOutcomeParser.ts | 62 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts create mode 100644 src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts new file mode 100644 index 000000000..6fa578a0b --- /dev/null +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts @@ -0,0 +1,61 @@ +import { assert } from "chai"; +import { DelegationTransactionsOutcomeParser } from "./delegationTransactionsOutcomeParser"; +import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; +import { Address } from "../address"; + +describe("test token management transactions outcome parser", () => { + const parser = new DelegationTransactionsOutcomeParser(); + + it("should test parseCreateNewDelegationContract ", () => { + const contractAddress = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqpf0llllsccsy0c"); + const contractAddressB64 = Buffer.from(contractAddress.toBech32()).toString("base64"); + + const delegateEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "delegate", + topics: [ + "Q8M8GTdWSAAA", + "Q8M8GTdWSAAA", + "AQ==", + "Q8M8GTdWSAAA", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", + ], + }); + + const scDeployEvent = new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqy8lllls62y8s5", + identifier: "SCDeploy", + topics: [contractAddressB64, "PDXX6ssamaSgzKpTfvDMCuEJ9B9sK0AiA+Yzv7sHH1w="], + }); + + const logs = new TransactionLogs({ events: [delegateEvent, scDeployEvent] }); + + const scResultEvent = new TransactionEvent({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + identifier: "completedTxEvent", + topics: ["b2g6sUl6beG17FCUIkFwCOTGJjoJJi5SjkP2077e6xA="], + }); + + const scResultLog = new TransactionLogs({ + address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + events: [scResultEvent], + }); + + const scResult = new SmartContractResult({ + sender: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6", + receiver: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", + data: Buffer.from( + "QDZmNmJAMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMGZmZmZmZg==", + "base64", + ), + logs: scResultLog, + }); + + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + + const outcome = parser.parseCreateNewDelegationContract(txOutcome); + + assert.lengthOf(outcome, 1); + assert.equal(outcome[0].contractAddress, contractAddress.toBech32()); + }); +}); diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts new file mode 100644 index 000000000..7786fc037 --- /dev/null +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -0,0 +1,62 @@ +import { ErrParseTransactionOutcome } from "../errors"; +import { TransactionEvent, TransactionOutcome } from "./resources"; +import { Address } from "../address"; + +export class DelegationTransactionsOutcomeParser { + constructor() {} + + parseCreateNewDelegationContract(transactionOutcome: TransactionOutcome): { contractAddress: string }[] { + this.ensureNoError(transactionOutcome.transactionLogs.events); + + const events = this.findEventsByIdentifier(transactionOutcome, "SCDeploy"); + + return events.map((event) => ({ contractAddress: this.extractContractAddress(event) })); + } + + private ensureNoError(transactionEvents: TransactionEvent[]) { + for (const event of transactionEvents) { + if (event.identifier == "signalError") { + const data = Buffer.from(event.data.toString().slice(1)).toString(); + const message = this.decodeTopicAsString(event.topics[1]); + + throw new ErrParseTransactionOutcome( + `encountered signalError: ${message} (${Buffer.from(data, "hex").toString()})`, + ); + } + } + } + + private findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { + const events = this.gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); + + if (events.length == 0) { + throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); + } + + return events; + } + + private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { + const allEvents = []; + + allEvents.push(...transactionOutcome.transactionLogs.events); + + for (const item of transactionOutcome.smartContractResults) { + allEvents.push(...item.logs.events); + } + + return allEvents; + } + + private extractContractAddress(event: TransactionEvent): string { + if (!event.topics[0]) { + return ""; + } + const address = Buffer.from(event.topics[0], "base64"); + return Address.fromBech32(address.toString()).bech32(); + } + + private decodeTopicAsString(topic: string): string { + return Buffer.from(topic, "base64").toString(); + } +} From 4985058979ca166c10602000e2ed210ee1a6a231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 14 Mar 2024 14:07:56 +0200 Subject: [PATCH 156/275] Add test. --- src/converters/transactionsConverters.spec.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/converters/transactionsConverters.spec.ts diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts new file mode 100644 index 000000000..0cd0a4e39 --- /dev/null +++ b/src/converters/transactionsConverters.spec.ts @@ -0,0 +1,23 @@ +import { assert } from "chai"; +import { Transaction } from "../transaction"; + +describe("test transactions converter", async () => { + it("converts transaction to plain object and back", () => { + const transaction = new Transaction({ + nonce: 90, + value: BigInt("123456789000000000000000000000"), + sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + senderUsername: "alice", + receiverUsername: "bob", + gasPrice: 1000000000, + gasLimit: 80000, + data: Buffer.from("hello"), + chainID: "localnet", + }); + + const plainObject = transaction.toPlainObject(); + const restoredTransaction = Transaction.fromPlainObject(plainObject); + assert.deepEqual(restoredTransaction, transaction); + }); +}); From 7c1b80b88a80cf03cc3bf899a1327f768740920a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 14:13:15 +0200 Subject: [PATCH 157/275] fix address extraction --- .../delegationTransactionsOutcomeParser.spec.ts | 5 ++--- .../delegationTransactionsOutcomeParser.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts index 6fa578a0b..f94887951 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts @@ -7,8 +7,7 @@ describe("test token management transactions outcome parser", () => { const parser = new DelegationTransactionsOutcomeParser(); it("should test parseCreateNewDelegationContract ", () => { - const contractAddress = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqpf0llllsccsy0c"); - const contractAddressB64 = Buffer.from(contractAddress.toBech32()).toString("base64"); + const contractAddress = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqy8lllls62y8s5"); const delegateEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", @@ -25,7 +24,7 @@ describe("test token management transactions outcome parser", () => { const scDeployEvent = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqy8lllls62y8s5", identifier: "SCDeploy", - topics: [contractAddressB64, "PDXX6ssamaSgzKpTfvDMCuEJ9B9sK0AiA+Yzv7sHH1w="], + topics: ["AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", "PDXX6ssamaSgzKpTfvDMCuEJ9B9sK0AiA+Yzv7sHH1w="], }); const logs = new TransactionLogs({ events: [delegateEvent, scDeployEvent] }); diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index 7786fc037..036706ee2 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -53,7 +53,7 @@ export class DelegationTransactionsOutcomeParser { return ""; } const address = Buffer.from(event.topics[0], "base64"); - return Address.fromBech32(address.toString()).bech32(); + return Address.fromBuffer(address).bech32(); } private decodeTopicAsString(topic: string): string { From dc1c193dd0cc3d7c2ce6f16c509794bedc67d614 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 14:14:26 +0200 Subject: [PATCH 158/275] export delegation transactions outcome parser --- src/transactionsOutcomeParsers/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/transactionsOutcomeParsers/index.ts b/src/transactionsOutcomeParsers/index.ts index 55d945b5b..e95e9836b 100644 --- a/src/transactionsOutcomeParsers/index.ts +++ b/src/transactionsOutcomeParsers/index.ts @@ -1,2 +1,3 @@ export * from "./resources"; export * from "./tokenManagementTransactionsOutcomeParser"; +export * from "./delegationTransactionsOutcomeParser"; From 4dc94e3317c3289368d7cc3ecfa897f7ec50fa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 14 Mar 2024 14:56:31 +0200 Subject: [PATCH 159/275] Fix after review. --- src/converters/transactionsConverter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index bcaea6649..8cd166fd0 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -2,7 +2,7 @@ import { IPlainTransactionObject, ITransaction } from "../interface"; import { Transaction } from "../transaction"; export class TransactionsConverter { - transactionToPlainObject(transaction: ITransaction): IPlainTransactionObject { + public transactionToPlainObject(transaction: ITransaction): IPlainTransactionObject { const plainObject = { nonce: Number(transaction.nonce), value: transaction.value.toString(), From afad158adbaa9d784d566f3ce0a5302f38535246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 14 Mar 2024 15:31:17 +0200 Subject: [PATCH 160/275] Fix after review. --- src/converters/transactionsConverter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index 8cd166fd0..c45c3de64 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -34,15 +34,15 @@ export class TransactionsConverter { public plainObjectToTransaction(object: IPlainTransactionObject): Transaction { const transaction = new Transaction({ - nonce: Number(object.nonce), + nonce: BigInt(object.nonce), value: BigInt(object.value || ""), receiver: object.receiver, receiverUsername: this.bufferFromBase64(object.receiverUsername).toString(), sender: object.sender, senderUsername: this.bufferFromBase64(object.senderUsername).toString(), guardian: object.guardian, - gasPrice: Number(object.gasPrice), - gasLimit: Number(object.gasLimit), + gasPrice: BigInt(object.gasPrice), + gasLimit: BigInt(object.gasLimit), data: this.bufferFromBase64(object.data), chainID: String(object.chainID), version: object.version, From 3bcf6201d4bea67a84b974828b72519e51d5fd91 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 15:36:46 +0200 Subject: [PATCH 161/275] refactoring --- ...okenManagementTransactionsOutcomeParser.ts | 282 +++++++++++------- 1 file changed, 170 insertions(+), 112 deletions(-) diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index b0cb15aa9..5cbd89b20 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -71,15 +71,20 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); + return events.map((event) => this.getOutputForSetSpecialRoleEvent(event)); + } - return events.map((event) => { - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - const encodedRoles = event.topics.slice(3); - const roles = encodedRoles.map((role) => this.decodeTopicAsString(role)); + private getOutputForSetSpecialRoleEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + roles: string[]; + } { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const encodedRoles = event.topics.slice(3); + const roles = encodedRoles.map((role) => this.decodeTopicAsString(role)); - return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; - }); + return { userAddress: userAddress, tokenIdentifier: tokenIdentifier, roles: roles }; } parseNftCreate(transactionOutcome: TransactionOutcome): { @@ -90,14 +95,19 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTCreate"); + return events.map((event) => this.getOutputForNftCreateEvent(event)); + } - return events.map((event) => { - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const amount = this.extractAmount(event); + private getOutputForNftCreateEvent(event: TransactionEvent): { + tokenIdentifier: string; + nonce: bigint; + initialQuantity: bigint; + } { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const amount = this.extractAmount(event); - return { tokenIdentifier: tokenIdentifier, nonce: nonce, initialQuantity: amount }; - }); + return { tokenIdentifier: tokenIdentifier, nonce: nonce, initialQuantity: amount }; } parseLocalMint(transactionOutcome: TransactionOutcome): { @@ -109,20 +119,26 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalMint"); + return events.map((event) => this.getOutputForLocalMintEvent(event)); + } - return events.map((event) => { - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const mintedSupply = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - mintedSupply: mintedSupply, - }; - }); + private getOutputForLocalMintEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + mintedSupply: bigint; + } { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const mintedSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + mintedSupply: mintedSupply, + }; } parseLocalBurn(transactionOutcome: TransactionOutcome): { @@ -134,27 +150,32 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalBurn"); + return events.map((event) => this.getOutputForLocalBurnEvent(event)); + } - return events.map((event) => { - const userAddress = event.address; - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const burntSupply = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - burntSupply: burntSupply, - }; - }); + private getOutputForLocalBurnEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + burntSupply: bigint; + } { + const userAddress = event.address; + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntSupply = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntSupply: burntSupply, + }; } parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTPause"); - return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } @@ -174,20 +195,26 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTFreeze"); + return events.map((event) => this.getOutputForFreezeEvent(event)); + } - return events.map((event) => { - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; - }); + private getOutputForFreezeEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; } parseUnfreeze(transactionOutcome: TransactionOutcome): { @@ -199,20 +226,26 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnFreeze"); + return events.map((event) => this.getOutputForUnfreezeEvent(event)); + } - return events.map((event) => { - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; - }); + private getOutputForUnfreezeEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; } parseWipe(transactionOutcome: TransactionOutcome): { @@ -224,19 +257,26 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTWipe"); - return events.map((event) => { - const userAddress = this.extractAddress(event); - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const balance = this.extractAmount(event); - - return { - userAddress: userAddress, - tokenIdentifier: tokenIdentifier, - nonce: nonce, - balance: balance, - }; - }); + return events.map((event) => this.getOutputForWipeEvent(event)); + } + + private getOutputForWipeEvent(event: TransactionEvent): { + userAddress: string; + tokenIdentifier: string; + nonce: bigint; + balance: bigint; + } { + const userAddress = this.extractAddress(event); + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const balance = this.extractAmount(event); + + return { + userAddress: userAddress, + tokenIdentifier: tokenIdentifier, + nonce: nonce, + balance: balance, + }; } parseUpdateAttributes(transactionOutcome: TransactionOutcome): { @@ -247,17 +287,23 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); - return events.map((event) => { - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - attributes: attributes, - }; - }); + return events.map((event) => this.getOutputForUpdateAttributesEvent(event)); + } + + private getOutputForUpdateAttributesEvent(event: TransactionEvent): { + tokenIdentifier: string; + nonce: bigint; + attributes: Uint8Array; + } { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + attributes: attributes, + }; } parseAddQuantity(transactionOutcome: TransactionOutcome): { @@ -268,17 +314,23 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); - return events.map((event) => { - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const addedQuantity = this.extractAmount(event); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - addedQuantity: addedQuantity, - }; - }); + return events.map((event) => this.getOutputForAddQuantityEvent(event)); + } + + private getOutputForAddQuantityEvent(event: TransactionEvent): { + tokenIdentifier: string; + nonce: bigint; + addedQuantity: bigint; + } { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const addedQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + addedQuantity: addedQuantity, + }; } parseBurnQuantity(transactionOutcome: TransactionOutcome): { @@ -289,17 +341,23 @@ export class TokenManagementTransactionsOutcomeParser { this.ensureNoError(transactionOutcome.transactionLogs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTBurn"); - return events.map((event) => { - const tokenIdentifier = this.extractTokenIdentifier(event); - const nonce = this.extractNonce(event); - const burntQuantity = this.extractAmount(event); - - return { - tokenIdentifier: tokenIdentifier, - nonce: nonce, - burntQuantity: burntQuantity, - }; - }); + return events.map((event) => this.getOutputForBurnQuantityEvent(event)); + } + + private getOutputForBurnQuantityEvent(event: TransactionEvent): { + tokenIdentifier: string; + nonce: bigint; + burntQuantity: bigint; + } { + const tokenIdentifier = this.extractTokenIdentifier(event); + const nonce = this.extractNonce(event); + const burntQuantity = this.extractAmount(event); + + return { + tokenIdentifier: tokenIdentifier, + nonce: nonce, + burntQuantity: burntQuantity, + }; } private ensureNoError(transactionEvents: TransactionEvent[]) { From f9834c299baf6d02e9c61ade93844b0cfb26915d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 16:52:53 +0200 Subject: [PATCH 162/275] constructor refactor for transaction factories --- src/index.ts | 1 + .../smartContract.local.net.spec.ts | 2 +- src/transaction.local.net.spec.ts | 5 +- src/transaction.spec.ts | 3 +- src/transaction.ts | 81 +----------------- src/transactionComputer.ts | 83 +++++++++++++++++++ .../delegationTransactionsFactory.spec.ts | 2 +- .../delegationTransactionsFactory.ts | 4 +- .../relayedTransactionsFactory.spec.ts | 5 +- .../relayedTransactionsFactory.ts | 9 +- .../smartContractTransactionsFactory.ts | 8 +- ...anagementTransactionIntentsFactory.spec.ts | 2 +- .../tokenManagementTransactionsFactory.ts | 26 ++---- .../transferTransactionsFactory.spec.ts | 5 +- .../transferTransactionsFactory.ts | 6 +- 15 files changed, 118 insertions(+), 124 deletions(-) create mode 100644 src/transactionComputer.ts diff --git a/src/index.ts b/src/index.ts index 9063e99ad..39dbc2dc8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,3 +21,4 @@ export * from "./transactionPayload"; export * from "./transactionWatcher"; export * from "./transferTransactionsFactory"; export * from "./utils"; +export * from "./transactionComputer"; diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index e0a637474..2951df137 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -14,7 +14,7 @@ import { TransactionsFactoryConfig } from "../transactionsFactories/transactions import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TokenComputer } from "../tokens"; import { promises } from "fs"; -import { TransactionComputer } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; describe("test on local testnet", function () { let alice: TestWallet, bob: TestWallet, carol: TestWallet; diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index c00bbaa13..94ebefd2a 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -4,12 +4,13 @@ import { Logger } from "./logger"; import { loadTestWallets, TestWallet } from "./testutils"; import { createLocalnetProvider } from "./testutils/networkProviders"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction, TransactionComputer } from "./transaction"; +import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { TransactionWatcher } from "./transactionWatcher"; import { TransactionsFactoryConfig } from "./transactionsFactories/transactionsFactoryConfig"; import { NextTransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; import { TokenComputer } from "./tokens"; +import { TransactionComputer } from "./transactionComputer"; describe("test transaction", function () { let alice: TestWallet, bob: TestWallet; @@ -152,7 +153,7 @@ describe("test transaction", function () { const network = await provider.getNetworkConfig(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new NextTransferTransactionsFactory(config, new TokenComputer()); + const factory = new NextTransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); await alice.sync(provider); await bob.sync(provider); diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index ba5044657..257248ade 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -5,8 +5,9 @@ import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; -import { Transaction, TransactionComputer } from "./transaction"; +import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; +import { TransactionComputer } from "./transactionComputer"; describe("test transaction", async () => { let wallets: Record; diff --git a/src/transaction.ts b/src/transaction.ts index f65c1c0ae..a4417e661 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -2,7 +2,6 @@ import { BigNumber } from "bignumber.js"; import { Address } from "./address"; import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants"; import { TransactionsConverter } from "./converters/transactionsConverter"; -import * as errors from "./errors"; import { Hash } from "./hash"; import { IAddress, @@ -12,7 +11,6 @@ import { INonce, IPlainTransactionObject, ISignature, - ITransaction, ITransactionOptions, ITransactionPayload, ITransactionValue, @@ -20,12 +18,9 @@ import { } from "./interface"; import { INetworkConfig } from "./interfaceOfNetwork"; import { TransactionOptions, TransactionVersion } from "./networkParams"; -import { ProtoSerializer } from "./proto"; import { interpretSignatureAsBuffer } from "./signature"; import { TransactionPayload } from "./transactionPayload"; - -const createTransactionHasher = require("blake2b"); -const TRANSACTION_HASH_LENGTH = 32; +import { TransactionComputer } from "./transactionComputer"; /** * An abstraction for creating, signing and broadcasting transactions. @@ -446,77 +441,3 @@ export class TransactionHash extends Hash { return new TransactionHash(Buffer.from(hash).toString("hex")); } } - -/** - * An utilitary class meant to work together with the {@link Transaction} class. - */ -export class TransactionComputer { - constructor() {} - - computeTransactionFee( - transaction: { gasPrice: bigint; gasLimit: bigint; data: Uint8Array }, - networkConfig: INetworkConfig, - ): bigint { - const moveBalanceGas = BigInt( - networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, - ); - if (moveBalanceGas > transaction.gasLimit) { - throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); - } - - const gasPrice = transaction.gasPrice; - const feeForMove = moveBalanceGas * gasPrice; - if (moveBalanceGas === transaction.gasLimit) { - return feeForMove; - } - - const diff = transaction.gasLimit - moveBalanceGas; - const modifiedGasPrice = BigInt( - new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), - ); - const processingFee = diff * modifiedGasPrice; - - return feeForMove + processingFee; - } - - computeBytesForSigning(transaction: ITransaction): Uint8Array { - // TODO: do some checks for the transaction e.g. sender, chain ID etc. - // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash - - const plainTransaction = this.toPlainObjectForSigning(transaction); - const serialized = JSON.stringify(plainTransaction); - return new Uint8Array(Buffer.from(serialized)); - } - - computeTransactionHash(transaction: ITransaction): Uint8Array { - const serializer = new ProtoSerializer(); - const buffer = serializer.serializeTransaction(new Transaction(transaction)); - const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); - - return Buffer.from(hash, "hex"); - } - - private toPlainObjectForSigning(transaction: ITransaction) { - return { - nonce: Number(transaction.nonce), - value: transaction.value.toString(), - receiver: transaction.receiver, - sender: transaction.sender, - senderUsername: this.toBase64OrUndefined(transaction.senderUsername), - receiverUsername: this.toBase64OrUndefined(transaction.receiverUsername), - gasPrice: Number(transaction.gasPrice), - gasLimit: Number(transaction.gasLimit), - data: this.toBase64OrUndefined(transaction.data), - chainID: transaction.chainID, - version: transaction.version, - options: transaction.options ? transaction.options : undefined, - guardian: transaction.guardian ? transaction.guardian : undefined, - }; - } - - private toBase64OrUndefined(value?: string | Uint8Array) { - return value && value.length ? Buffer.from(value).toString("base64") : undefined; - } - - // TODO: add missing functions wrt. specs -} diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts new file mode 100644 index 000000000..0628205b0 --- /dev/null +++ b/src/transactionComputer.ts @@ -0,0 +1,83 @@ +import { INetworkConfig } from "./interfaceOfNetwork"; +import * as errors from "./errors"; +import BigNumber from "bignumber.js"; +import { ITransaction } from "./interface"; +import { ProtoSerializer } from "./proto"; +import { Transaction } from "./transaction"; + +const createTransactionHasher = require("blake2b"); +const TRANSACTION_HASH_LENGTH = 32; + +/** + * An utilitary class meant to work together with the {@link Transaction} class. + */ +export class TransactionComputer { + constructor() {} + + computeTransactionFee( + transaction: { gasPrice: bigint; gasLimit: bigint; data: Uint8Array }, + networkConfig: INetworkConfig, + ): bigint { + const moveBalanceGas = BigInt( + networkConfig.MinGasLimit + transaction.data.length * networkConfig.GasPerDataByte, + ); + if (moveBalanceGas > transaction.gasLimit) { + throw new errors.ErrNotEnoughGas(parseInt(transaction.gasLimit.toString(), 10)); + } + + const gasPrice = transaction.gasPrice; + const feeForMove = moveBalanceGas * gasPrice; + if (moveBalanceGas === transaction.gasLimit) { + return feeForMove; + } + + const diff = transaction.gasLimit - moveBalanceGas; + const modifiedGasPrice = BigInt( + new BigNumber(gasPrice.toString()).multipliedBy(new BigNumber(networkConfig.GasPriceModifier)).toFixed(0), + ); + const processingFee = diff * modifiedGasPrice; + + return feeForMove + processingFee; + } + + computeBytesForSigning(transaction: ITransaction): Uint8Array { + // TODO: do some checks for the transaction e.g. sender, chain ID etc. + // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash + + const plainTransaction = this.toPlainObjectForSigning(transaction); + const serialized = JSON.stringify(plainTransaction); + return new Uint8Array(Buffer.from(serialized)); + } + + computeTransactionHash(transaction: ITransaction): Uint8Array { + const serializer = new ProtoSerializer(); + const buffer = serializer.serializeTransaction(new Transaction(transaction)); + const hash = createTransactionHasher(TRANSACTION_HASH_LENGTH).update(buffer).digest("hex"); + + return Buffer.from(hash, "hex"); + } + + private toPlainObjectForSigning(transaction: ITransaction) { + return { + nonce: Number(transaction.nonce), + value: transaction.value.toString(), + receiver: transaction.receiver, + sender: transaction.sender, + senderUsername: this.toBase64OrUndefined(transaction.senderUsername), + receiverUsername: this.toBase64OrUndefined(transaction.receiverUsername), + gasPrice: Number(transaction.gasPrice), + gasLimit: Number(transaction.gasLimit), + data: this.toBase64OrUndefined(transaction.data), + chainID: transaction.chainID, + version: transaction.version, + options: transaction.options ? transaction.options : undefined, + guardian: transaction.guardian ? transaction.guardian : undefined, + }; + } + + private toBase64OrUndefined(value?: string | Uint8Array) { + return value && value.length ? Buffer.from(value).toString("base64") : undefined; + } + + // TODO: add missing functions wrt. specs +} diff --git a/src/transactionsFactories/delegationTransactionsFactory.spec.ts b/src/transactionsFactories/delegationTransactionsFactory.spec.ts index 09a671fc2..c76d1917c 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.spec.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.spec.ts @@ -7,7 +7,7 @@ import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test delegation transactions factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); - const delegationFactory = new DelegationTransactionsFactory(config); + const delegationFactory = new DelegationTransactionsFactory({ config: config }); it("should create 'Transaction' for new delegation contract", async function () { const sender = Address.fromBech32("erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2"); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index d2bbe3619..da902ee32 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -29,8 +29,8 @@ interface IValidatorPublicKey { export class DelegationTransactionsFactory { private readonly config: Config; - constructor(config: Config) { - this.config = config; + constructor(options: { config: Config }) { + this.config = options.config; } createTransactionForNewDelegationContract(options: { diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index 32b80864c..ca06cd8de 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -1,12 +1,13 @@ import { assert } from "chai"; import { TestWallet, loadTestWallets } from "../testutils"; -import { Transaction, TransactionComputer } from "../transaction"; +import { Transaction } from "../transaction"; import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; +import { TransactionComputer } from "../transactionComputer"; describe("test relayed v1 transaction builder", function () { const config = new TransactionsFactoryConfig({ chainID: "T" }); - const factory = new RelayedTransactionsFactory(config); + const factory = new RelayedTransactionsFactory({ config: config }); const transactionComputer = new TransactionComputer(); let alice: TestWallet, bob: TestWallet, carol: TestWallet, grace: TestWallet, frank: TestWallet; diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/transactionsFactories/relayedTransactionsFactory.ts index 5a4ef5c78..fdf12be61 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.ts @@ -19,14 +19,11 @@ interface IConfig { export class RelayedTransactionsFactory { private readonly config: IConfig; - constructor(config: IConfig) { - this.config = config; + constructor(options: { config: IConfig }) { + this.config = options.config; } - createRelayedV1Transaction(options: { - innerTransaction: ITransaction; - relayerAddress: IAddress; - }): Transaction { + createRelayedV1Transaction(options: { innerTransaction: ITransaction; relayerAddress: IAddress }): Transaction { if (!options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit is not set for the inner transaction"); } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index ba190f81b..c2e4efbd7 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -35,10 +35,10 @@ export class SmartContractTransactionsFactory { private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - constructor({ config, abi, tokenComputer }: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { - this.config = config; - this.abi = abi; - this.tokenComputer = tokenComputer; + constructor(options: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { + this.config = options.config; + this.abi = options.abi; + this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index f626d452a..678faee41 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -12,7 +12,7 @@ describe("test token management transactions factory", () => { before(async function () { ({ frank, grace } = await loadTestWallets()); config = new TransactionsFactoryConfig({ chainID: "T" }); - tokenManagementFactory = new TokenManagementTransactionsFactory(config); + tokenManagementFactory = new TokenManagementTransactionsFactory({ config: config }); }); it("should create 'Transaction' for registering and setting roles", () => { diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index c7acb2e6e..4460e2872 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -36,8 +36,8 @@ export class TokenManagementTransactionsFactory { private readonly trueAsHex: string; private readonly falseAsHex: string; - constructor(config: Config) { - this.config = config; + constructor(options: { config: Config }) { + this.config = options.config; this.trueAsHex = utf8ToHex("true"); this.falseAsHex = utf8ToHex("false"); } @@ -253,10 +253,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForSettingBurnRoleGlobally(options: { - sender: IAddress; - tokenIdentifier: string; - }): Transaction { + createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; return new TransactionBuilder({ @@ -269,10 +266,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForUnsettingBurnRoleGlobally(options: { - sender: IAddress; - tokenIdentifier: string; - }): Transaction { + createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; return new TransactionBuilder({ @@ -443,11 +437,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForFreezing(options: { - sender: IAddress; - user: IAddress; - tokenIdentifier: string; - }): Transaction { + createTransactionForFreezing(options: { sender: IAddress; user: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; return new TransactionBuilder({ @@ -477,11 +467,7 @@ export class TokenManagementTransactionsFactory { }).build(); } - createTransactionForWiping(options: { - sender: IAddress; - user: IAddress; - tokenIdentifier: string; - }): Transaction { + createTransactionForWiping(options: { sender: IAddress; user: IAddress; tokenIdentifier: string }): Transaction { const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; return new TransactionBuilder({ diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 301360a4d..eb3fa0282 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -7,7 +7,10 @@ import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); - const nextTransferFactory = new NextTransferTransactionsFactory(config, new TokenComputer()); + const nextTransferFactory = new NextTransferTransactionsFactory({ + config: config, + tokenComputer: new TokenComputer(), + }); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const bob = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 2ca3ccdff..002fa0396 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -30,9 +30,9 @@ export class NextTransferTransactionsFactory { private readonly dataArgsBuilder: TokenTransfersDataBuilder; private readonly tokenComputer: TokenComputer; - constructor(config: IConfig, tokenComputer: TokenComputer) { - this.config = config; - this.tokenComputer = tokenComputer; + constructor(options: { config: IConfig; tokenComputer: TokenComputer }) { + this.config = options.config; + this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); } From 6df2983d8a3babc14c279a15bb92fad06d8753d7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 14 Mar 2024 17:07:16 +0200 Subject: [PATCH 163/275] bump version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4fa10620..3a94e1324 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.5", + "version": "13.0.0-beta.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.5", + "version": "13.0.0-beta.6", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index a8e6852b6..dc0477ae1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.5", + "version": "13.0.0-beta.6", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 7e4f7f50d2387bdaeefcf9dbf273b6534362f3b9 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Thu, 14 Mar 2024 18:05:54 +0200 Subject: [PATCH 164/275] Sketch SC outcome parser. --- src/interfaceOfNetwork.ts | 1 + src/transactionsOutcomeParsers/resources.ts | 2 ++ .../smartContractTransactionsOutcomeParser.ts | 34 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts diff --git a/src/interfaceOfNetwork.ts b/src/interfaceOfNetwork.ts index 84b284fca..35acd76f4 100644 --- a/src/interfaceOfNetwork.ts +++ b/src/interfaceOfNetwork.ts @@ -20,6 +20,7 @@ export interface ITransactionOnNetwork { value: string; receiver: IAddress; sender: IAddress; + function?: string; data: Buffer; status: ITransactionStatus; receipt: ITransactionReceipt; diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 4fd7249ad..19bdea09b 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -43,10 +43,12 @@ export class SmartContractResult { } export class TransactionOutcome { + function: string; smartContractResults: SmartContractResult[]; transactionLogs: TransactionLogs; constructor(init: Partial) { + this.function = ""; this.smartContractResults = []; this.transactionLogs = new TransactionLogs({}); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts new file mode 100644 index 000000000..212ce6c48 --- /dev/null +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -0,0 +1,34 @@ +import { EndpointDefinition, ResultsParser } from "../smartcontracts"; +import { TransactionOutcome } from "./resources"; + +interface Abi { + getEndpoint(name: string): EndpointDefinition; +} + +export class SmartContractTransactionsOutcomeParser { + private readonly abi?: Abi; + private readonly legacyResultsParser: ResultsParser; + + constructor(options: { abi?: Abi }) { + this.abi = options.abi; + this.legacyResultsParser = new ResultsParser(); + } + + parseExecute(options: { outcome: TransactionOutcome; function?: string }): { + values: any[]; + returnCode: string; + returnMessage: string; + } { + const functionName = options.function || options.outcome.function; + + if (this.abi) { + const endpoint = this.abi.getEndpoint(functionName); + } + + return { + values: [], + returnCode: "", + returnMessage: "", + }; + } +} From c089a05fb621b2197ea25f9ab2929a7e5463cddf Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 15 Mar 2024 17:01:52 +0200 Subject: [PATCH 165/275] fix tests --- src/smartcontracts/interaction.local.net.spec.ts | 3 ++- .../smartContractResults.local.net.spec.ts | 2 +- src/testutils/contractController.ts | 13 +++++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 6650e9075..292814b40 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -3,7 +3,8 @@ import { assert } from "chai"; import { loadAbiRegistry, loadTestWallets, prepareDeployment, TestWallet } from "../testutils"; import { ContractController } from "../testutils/contractController"; import { createLocalnetProvider } from "../testutils/networkProviders"; -import { Transaction, TransactionComputer } from "../transaction"; +import { Transaction } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; import { Interaction } from "./interaction"; import { ReturnCode } from "./returnCode"; import { SmartContract } from "./smartContract"; diff --git a/src/smartcontracts/smartContractResults.local.net.spec.ts b/src/smartcontracts/smartContractResults.local.net.spec.ts index f465fc7c7..731c0b185 100644 --- a/src/smartcontracts/smartContractResults.local.net.spec.ts +++ b/src/smartcontracts/smartContractResults.local.net.spec.ts @@ -9,7 +9,7 @@ import { TransactionsFactoryConfig } from "../transactionsFactories/transactions import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TokenComputer } from "../tokens"; import { promises } from "fs"; -import { TransactionComputer } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; describe("fetch transactions from local testnet", function () { let alice: TestWallet; diff --git a/src/testutils/contractController.ts b/src/testutils/contractController.ts index 0e1bcd071..8df126fb5 100644 --- a/src/testutils/contractController.ts +++ b/src/testutils/contractController.ts @@ -3,7 +3,8 @@ import { Logger } from "../logger"; import { Interaction } from "../smartcontracts/interaction"; import { TypedOutcomeBundle, UntypedOutcomeBundle } from "../smartcontracts/interface"; import { ResultsParser } from "../smartcontracts/resultsParser"; -import { Transaction, TransactionComputer, TransactionNext } from "../transaction"; +import { Transaction } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; import { TransactionWatcher } from "../transactionWatcher"; import { INetworkProvider } from "./networkProviders"; @@ -20,7 +21,7 @@ export class ContractController { }); } - async deploy(transaction: Transaction | TransactionNext): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: UntypedOutcomeBundle }> { + async deploy(transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: UntypedOutcomeBundle }> { const txHash = this.getTransactionHash(transaction); Logger.info(`ContractController.deploy [begin]: transaction = ${txHash}`); @@ -32,7 +33,7 @@ export class ContractController { return { transactionOnNetwork, bundle }; } - async execute(interaction: Interaction, transaction: Transaction | TransactionNext): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: TypedOutcomeBundle }> { + async execute(interaction: Interaction, transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: TypedOutcomeBundle }> { const txHash = this.getTransactionHash(transaction); Logger.info(`ContractController.execute [begin]: function = ${interaction.getFunction()}, transaction = ${txHash}`); @@ -58,11 +59,7 @@ export class ContractController { return bundle; } - private getTransactionHash(transaction: Transaction | TransactionNext): string { - if ("toSendable" in transaction){ - return transaction.getHash().hex(); - } - + private getTransactionHash(transaction: Transaction): string { const transactionComputer = new TransactionComputer(); const txHash = transactionComputer.computeTransactionHash(transaction); return Buffer.from(txHash).toString("hex"); From 91e81c75af7d8e3e882a95ffc4b2217ba50b02cb Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 18 Mar 2024 10:58:03 +0200 Subject: [PATCH 166/275] refactor tx watcher to accept either transaction or hash --- src/transactionWatcher.spec.ts | 25 +++++- src/transactionWatcher.ts | 136 ++++++++++++++++++++------------- 2 files changed, 108 insertions(+), 53 deletions(-) diff --git a/src/transactionWatcher.spec.ts b/src/transactionWatcher.spec.ts index 7f329970c..93790a2dd 100644 --- a/src/transactionWatcher.spec.ts +++ b/src/transactionWatcher.spec.ts @@ -6,7 +6,7 @@ import { TransactionWatcher } from "./transactionWatcher"; describe("test transactionWatcher", () => { - it("should await status == executed", async () => { + it("should await status == executed using hash", async () => { let hash = new TransactionHash("abba"); let provider = new MockNetworkProvider(); let watcher = new TransactionWatcher(provider, { @@ -28,4 +28,27 @@ describe("test transactionWatcher", () => { assert.isTrue((await provider.getTransactionStatus(hash.hex())).isExecuted()); }); + + it("should await status == executed using transction", async () => { + let hash = new TransactionHash("mockTransactionHash"); + let provider = new MockNetworkProvider(); + let watcher = new TransactionWatcher(provider, { + pollingIntervalMilliseconds: 42, + timeoutMilliseconds: 42 * 42 + }); + let dummyTransaction = { + getHash: () => hash + } + + provider.mockPutTransaction(hash, new TransactionOnNetwork({ + status: new TransactionStatus("unknown") + })); + + await Promise.all([ + provider.mockTransactionTimelineByHash(hash, [new Wait(40), new TransactionStatus("pending"), new Wait(40), new TransactionStatus("executed"), new MarkCompleted()]), + watcher.awaitCompleted(dummyTransaction) + ]); + + assert.isTrue((await provider.getTransactionStatus(hash.hex())).isExecuted()); + }); }); diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index bd518d4e1..a69a388a2 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -1,11 +1,23 @@ import { AsyncTimer } from "./asyncTimer"; -import { Err, ErrExpectedTransactionEventsNotFound, ErrExpectedTransactionStatusNotReached, ErrIsCompletedFieldIsMissingOnTransaction } from "./errors"; +import { + Err, + ErrExpectedTransactionEventsNotFound, + ErrExpectedTransactionStatusNotReached, + ErrIsCompletedFieldIsMissingOnTransaction, +} from "./errors"; import { ITransactionFetcher } from "./interface"; import { ITransactionEvent, ITransactionOnNetwork, ITransactionStatus } from "./interfaceOfNetwork"; import { Logger } from "./logger"; export type PredicateIsAwaitedStatus = (status: ITransactionStatus) => boolean; +/** + * Internal interface: a transaction, as seen from the perspective of a {@link TransactionWatcher}. + */ +interface ITransaction { + getHash(): { hex(): string }; +} + /** * TransactionWatcher allows one to continuously watch (monitor), by means of polling, the status of a given transaction. */ @@ -14,7 +26,7 @@ export class TransactionWatcher { static DefaultTimeout: number = TransactionWatcher.DefaultPollingInterval * 15; static DefaultPatience: number = 0; - static NoopOnStatusReceived = (_: ITransactionStatus) => { }; + static NoopOnStatusReceived = (_: ITransactionStatus) => {}; protected readonly fetcher: ITransactionFetcher; protected readonly pollingIntervalMilliseconds: number; @@ -23,7 +35,7 @@ export class TransactionWatcher { /** * A transaction watcher (awaiter). - * + * * @param fetcher The transaction fetcher * @param options The options * @param options.pollingIntervalMilliseconds The polling interval, in milliseconds @@ -33,12 +45,14 @@ export class TransactionWatcher { constructor( fetcher: ITransactionFetcher, options: { - pollingIntervalMilliseconds?: number, - timeoutMilliseconds?: number, - patienceMilliseconds?: number - } = {}) { + pollingIntervalMilliseconds?: number; + timeoutMilliseconds?: number; + patienceMilliseconds?: number; + } = {}, + ) { this.fetcher = new TransactionFetcherWithTracing(fetcher); - this.pollingIntervalMilliseconds = options.pollingIntervalMilliseconds || TransactionWatcher.DefaultPollingInterval; + this.pollingIntervalMilliseconds = + options.pollingIntervalMilliseconds || TransactionWatcher.DefaultPollingInterval; this.timeoutMilliseconds = options.timeoutMilliseconds || TransactionWatcher.DefaultTimeout; this.patienceMilliseconds = options.patienceMilliseconds || TransactionWatcher.DefaultPatience; } @@ -47,89 +61,107 @@ export class TransactionWatcher { * Waits until the transaction reaches the "pending" status. * @param txHash The hex-encoded transaction hash */ - public async awaitPending(txHash: string): Promise { + public async awaitPending(transactionOrTxHash: ITransaction | string): Promise { const isPending = (transaction: ITransactionOnNetwork) => transaction.status.isPending(); - const doFetch = async () => await this.fetcher.getTransaction(txHash); + const doFetch = async () => { + if (typeof transactionOrTxHash === "string") { + return await this.fetcher.getTransaction(transactionOrTxHash); + } + return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); - return this.awaitConditionally( - isPending, - doFetch, - errorProvider - ); + return this.awaitConditionally(isPending, doFetch, errorProvider); } /** - * Waits until the transaction is completely processed. - * @param txHash The hex-encoded transaction hash - */ - public async awaitCompleted(txHash: string): Promise { + * Waits until the transaction is completely processed. + * @param txHash The hex-encoded transaction hash + */ + public async awaitCompleted(transactionOrTxHash: ITransaction | string): Promise { const isCompleted = (transactionOnNetwork: ITransactionOnNetwork) => { if (transactionOnNetwork.isCompleted === undefined) { throw new ErrIsCompletedFieldIsMissingOnTransaction(); } - return transactionOnNetwork.isCompleted + return transactionOnNetwork.isCompleted; }; - const doFetch = async () => await this.fetcher.getTransaction(txHash); + const doFetch = async () => { + if (typeof transactionOrTxHash === "string") { + return await this.fetcher.getTransaction(transactionOrTxHash); + } + return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); - return this.awaitConditionally( - isCompleted, - doFetch, - errorProvider - ); + return this.awaitConditionally(isCompleted, doFetch, errorProvider); } - public async awaitAllEvents(txHash: string, events: string[]): Promise { + public async awaitAllEvents( + transactionOrTxHash: ITransaction | string, + events: string[], + ): Promise { const foundAllEvents = (transactionOnNetwork: ITransactionOnNetwork) => { - const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map(event => event.identifier); - const allAreFound = events.every(event => allEventIdentifiers.includes(event)); + const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map( + (event) => event.identifier, + ); + const allAreFound = events.every((event) => allEventIdentifiers.includes(event)); return allAreFound; }; - const doFetch = async () => await this.fetcher.getTransaction(txHash); + const doFetch = async () => { + if (typeof transactionOrTxHash === "string") { + return await this.fetcher.getTransaction(transactionOrTxHash); + } + return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); - return this.awaitConditionally( - foundAllEvents, - doFetch, - errorProvider - ); + return this.awaitConditionally(foundAllEvents, doFetch, errorProvider); } - public async awaitAnyEvent(txHash: string, events: string[]): Promise { + public async awaitAnyEvent( + transactionOrTxHash: ITransaction | string, + events: string[], + ): Promise { const foundAnyEvent = (transactionOnNetwork: ITransactionOnNetwork) => { - const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map(event => event.identifier); - const anyIsFound = events.find(event => allEventIdentifiers.includes(event)) != undefined; + const allEventIdentifiers = this.getAllTransactionEvents(transactionOnNetwork).map( + (event) => event.identifier, + ); + const anyIsFound = events.find((event) => allEventIdentifiers.includes(event)) != undefined; return anyIsFound; }; - const doFetch = async () => await this.fetcher.getTransaction(txHash); + const doFetch = async () => { + if (typeof transactionOrTxHash === "string") { + return await this.fetcher.getTransaction(transactionOrTxHash); + } + return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); - return this.awaitConditionally( - foundAnyEvent, - doFetch, - errorProvider - ); + return this.awaitConditionally(foundAnyEvent, doFetch, errorProvider); } - public async awaitOnCondition(txHash: string, condition: (data: ITransactionOnNetwork) => boolean): Promise { - const doFetch = async () => await this.fetcher.getTransaction(txHash); + public async awaitOnCondition( + transactionOrTxHash: ITransaction | string, + condition: (data: ITransactionOnNetwork) => boolean, + ): Promise { + const doFetch = async () => { + if (typeof transactionOrTxHash === "string") { + return await this.fetcher.getTransaction(transactionOrTxHash); + } + return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); - return this.awaitConditionally( - condition, - doFetch, - errorProvider - ); + return this.awaitConditionally(condition, doFetch, errorProvider); } protected async awaitConditionally( isSatisfied: (data: TData) => boolean, doFetch: () => Promise, - createError: () => Err + createError: () => Err, ): Promise { const periodicTimer = new AsyncTimer("watcher:periodic"); const patienceTimer = new AsyncTimer("watcher:patience"); From a3e71f59eff09d1443de5ccc2c58327b6d18953a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 18 Mar 2024 11:08:56 +0200 Subject: [PATCH 167/275] small refactoring --- src/transactionWatcher.ts | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index a69a388a2..6c3fb615d 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -64,10 +64,8 @@ export class TransactionWatcher { public async awaitPending(transactionOrTxHash: ITransaction | string): Promise { const isPending = (transaction: ITransactionOnNetwork) => transaction.status.isPending(); const doFetch = async () => { - if (typeof transactionOrTxHash === "string") { - return await this.fetcher.getTransaction(transactionOrTxHash); - } - return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); @@ -87,10 +85,8 @@ export class TransactionWatcher { }; const doFetch = async () => { - if (typeof transactionOrTxHash === "string") { - return await this.fetcher.getTransaction(transactionOrTxHash); - } - return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); @@ -110,10 +106,8 @@ export class TransactionWatcher { }; const doFetch = async () => { - if (typeof transactionOrTxHash === "string") { - return await this.fetcher.getTransaction(transactionOrTxHash); - } - return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); @@ -133,10 +127,8 @@ export class TransactionWatcher { }; const doFetch = async () => { - if (typeof transactionOrTxHash === "string") { - return await this.fetcher.getTransaction(transactionOrTxHash); - } - return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); @@ -148,10 +140,8 @@ export class TransactionWatcher { condition: (data: ITransactionOnNetwork) => boolean, ): Promise { const doFetch = async () => { - if (typeof transactionOrTxHash === "string") { - return await this.fetcher.getTransaction(transactionOrTxHash); - } - return await this.fetcher.getTransaction(transactionOrTxHash.getHash().hex()); + const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); From d5a847f013e72f0744cb38b956287727062f9080 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Mar 2024 13:09:56 +0200 Subject: [PATCH 168/275] move hash extraction to a private method --- src/transactionWatcher.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index 6c3fb615d..69b50329d 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -64,7 +64,7 @@ export class TransactionWatcher { public async awaitPending(transactionOrTxHash: ITransaction | string): Promise { const isPending = (transaction: ITransactionOnNetwork) => transaction.status.isPending(); const doFetch = async () => { - const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = this.transactionOrTxHashToTxHash(transactionOrTxHash); return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); @@ -85,7 +85,7 @@ export class TransactionWatcher { }; const doFetch = async () => { - const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = this.transactionOrTxHashToTxHash(transactionOrTxHash); return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); @@ -106,7 +106,7 @@ export class TransactionWatcher { }; const doFetch = async () => { - const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = this.transactionOrTxHashToTxHash(transactionOrTxHash); return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); @@ -127,7 +127,7 @@ export class TransactionWatcher { }; const doFetch = async () => { - const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = this.transactionOrTxHashToTxHash(transactionOrTxHash); return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionEventsNotFound(); @@ -140,7 +140,7 @@ export class TransactionWatcher { condition: (data: ITransactionOnNetwork) => boolean, ): Promise { const doFetch = async () => { - const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = this.transactionOrTxHashToTxHash(transactionOrTxHash); return await this.fetcher.getTransaction(hash); }; const errorProvider = () => new ErrExpectedTransactionStatusNotReached(); @@ -148,6 +148,10 @@ export class TransactionWatcher { return this.awaitConditionally(condition, doFetch, errorProvider); } + private transactionOrTxHashToTxHash(transactionOrTxHash: ITransaction | string): string { + return typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + } + protected async awaitConditionally( isSatisfied: (data: TData) => boolean, doFetch: () => Promise, From f823244d5315d370d36622991d6d054d30e368ac Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Mar 2024 13:45:52 +0200 Subject: [PATCH 169/275] check if transaction hash length is correct --- src/constants.ts | 1 + src/transactionWatcher.spec.ts | 6 +++--- src/transactionWatcher.ts | 10 +++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 63784a2fd..2ad2fb8d0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,3 +16,4 @@ export const DEFAULT_HRP = "erd"; export const ESDT_CONTRACT_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; export const DEFAULT_MESSAGE_VERSION = 1; export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; +export const DEFALT_HEX_HASH_LENGTH = 64; diff --git a/src/transactionWatcher.spec.ts b/src/transactionWatcher.spec.ts index 93790a2dd..7d9574200 100644 --- a/src/transactionWatcher.spec.ts +++ b/src/transactionWatcher.spec.ts @@ -7,7 +7,7 @@ import { TransactionWatcher } from "./transactionWatcher"; describe("test transactionWatcher", () => { it("should await status == executed using hash", async () => { - let hash = new TransactionHash("abba"); + let hash = new TransactionHash("abbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba"); let provider = new MockNetworkProvider(); let watcher = new TransactionWatcher(provider, { pollingIntervalMilliseconds: 42, @@ -29,8 +29,8 @@ describe("test transactionWatcher", () => { assert.isTrue((await provider.getTransactionStatus(hash.hex())).isExecuted()); }); - it("should await status == executed using transction", async () => { - let hash = new TransactionHash("mockTransactionHash"); + it("should await status == executed using transaction", async () => { + let hash = new TransactionHash("abbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba"); let provider = new MockNetworkProvider(); let watcher = new TransactionWatcher(provider, { pollingIntervalMilliseconds: 42, diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index 69b50329d..3172acb58 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -1,4 +1,5 @@ import { AsyncTimer } from "./asyncTimer"; +import { DEFALT_HEX_HASH_LENGTH } from "./constants"; import { Err, ErrExpectedTransactionEventsNotFound, @@ -149,7 +150,14 @@ export class TransactionWatcher { } private transactionOrTxHashToTxHash(transactionOrTxHash: ITransaction | string): string { - return typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + const hash = + typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); + + if (hash.length !== DEFALT_HEX_HASH_LENGTH) { + throw new Err("Invalid transaction hash length. The length of a hex encoded hash should be 64."); + } + + return hash; } protected async awaitConditionally( From dad51f8783258d13e767eae6f3d3b09ea21df32b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Mar 2024 14:01:53 +0200 Subject: [PATCH 170/275] fix typo --- src/constants.ts | 2 +- src/transactionWatcher.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 2ad2fb8d0..21dfb69d0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,4 +16,4 @@ export const DEFAULT_HRP = "erd"; export const ESDT_CONTRACT_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; export const DEFAULT_MESSAGE_VERSION = 1; export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; -export const DEFALT_HEX_HASH_LENGTH = 64; +export const DEFAULT_HEX_HASH_LENGTH = 64; diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index 3172acb58..3a43b9237 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -1,5 +1,5 @@ import { AsyncTimer } from "./asyncTimer"; -import { DEFALT_HEX_HASH_LENGTH } from "./constants"; +import { DEFAULT_HEX_HASH_LENGTH } from "./constants"; import { Err, ErrExpectedTransactionEventsNotFound, @@ -153,7 +153,7 @@ export class TransactionWatcher { const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); - if (hash.length !== DEFALT_HEX_HASH_LENGTH) { + if (hash.length !== DEFAULT_HEX_HASH_LENGTH) { throw new Err("Invalid transaction hash length. The length of a hex encoded hash should be 64."); } From c1971bdb8554dca325659cd7e80e6e5afa60b794 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 19 Mar 2024 15:51:45 +0200 Subject: [PATCH 171/275] merge TransferTransactionsFactory in NextTransferTransactionsFactory --- src/index.ts | 1 - .../tokenOperationsFactory.test.net.spec.ts | 4 +- src/transaction.local.net.spec.ts | 4 +- .../transferTransactionsFactory.spec.ts | 16 +- .../transferTransactionsFactory.ts | 267 ++++++++++++++++-- src/transferTransactionsFactory.spec.ts | 2 +- src/transferTransactionsFactory.ts | 162 ----------- 7 files changed, 258 insertions(+), 198 deletions(-) delete mode 100644 src/transferTransactionsFactory.ts diff --git a/src/index.ts b/src/index.ts index 39dbc2dc8..3043ba6cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,5 @@ export * from "./tokens"; export * from "./transaction"; export * from "./transactionPayload"; export * from "./transactionWatcher"; -export * from "./transferTransactionsFactory"; export * from "./utils"; export * from "./transactionComputer"; diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts index 05a4dfc03..0e2e51135 100644 --- a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts +++ b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts @@ -6,7 +6,7 @@ import { INetworkProvider, createTestnetProvider } from "../testutils/networkPro import { TokenTransfer } from "../tokenTransfer"; import { Transaction } from "../transaction"; import { TransactionWatcher } from "../transactionWatcher"; -import { TransferTransactionsFactory } from "../transferTransactionsFactory"; +import { TransferTransactionsFactory } from "../transactionsFactories/transferTransactionsFactory"; import { TokenOperationsFactory } from "./tokenOperationsFactory"; import { TokenOperationsFactoryConfig } from "./tokenOperationsFactoryConfig"; import { TokenOperationsOutcomeParser } from "./tokenOperationsOutcomeParser"; @@ -675,7 +675,7 @@ describe("test factory on testnet", function () { async function processTransaction( wallet: TestWallet, transaction: Transaction, - tag: string + tag: string, ): Promise { wallet.account.incrementNonce(); transaction.applySignature(await wallet.signer.sign(transaction.serializeForSigning())); diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 94ebefd2a..9795bba72 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -8,7 +8,7 @@ import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { TransactionWatcher } from "./transactionWatcher"; import { TransactionsFactoryConfig } from "./transactionsFactories/transactionsFactoryConfig"; -import { NextTransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; +import { TransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; import { TokenComputer } from "./tokens"; import { TransactionComputer } from "./transactionComputer"; @@ -153,7 +153,7 @@ describe("test transaction", function () { const network = await provider.getNetworkConfig(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new NextTransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new TransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); await alice.sync(provider); await bob.sync(provider); diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index eb3fa0282..78af08903 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -3,11 +3,11 @@ import { Address } from "../address"; import { ErrBadUsage } from "../errors"; import { NextTokenTransfer, Token, TokenComputer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import { NextTransferTransactionsFactory } from "./transferTransactionsFactory"; +import { TransferTransactionsFactory } from "./transferTransactionsFactory"; describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); - const nextTransferFactory = new NextTransferTransactionsFactory({ + const transferFactory = new TransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer(), }); @@ -20,7 +20,7 @@ describe("test transfer transcations factory", function () { assert.throw( () => { - nextTransferFactory.createTransactionForESDTTokenTransfer({ + transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: transfers, @@ -32,7 +32,7 @@ describe("test transfer transcations factory", function () { }); it("should create 'Transaction' for native token transfer without data", async () => { - const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ + const transaction = transferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: 1000000000000000000n, @@ -46,7 +46,7 @@ describe("test transfer transcations factory", function () { }); it("should create 'Transaction' for native token transfer with data", async () => { - const transaction = nextTransferFactory.createTransactionForNativeTokenTransfer({ + const transaction = transferFactory.createTransactionForNativeTokenTransfer({ sender: alice, receiver: bob, nativeAmount: 1000000000000000000n, @@ -64,7 +64,7 @@ describe("test transfer transcations factory", function () { const fooToken = new Token("FOO-123456", 0n); const transfer = new NextTokenTransfer(fooToken, 1000000n); - const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ + const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], @@ -81,7 +81,7 @@ describe("test transfer transcations factory", function () { const nft = new Token("NFT-123456", 10n); const transfer = new NextTokenTransfer(nft, 1n); - const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ + const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [transfer], @@ -104,7 +104,7 @@ describe("test transfer transcations factory", function () { const secondNft = new Token("TEST-987654", 1n); const secondTransfer = new NextTokenTransfer(secondNft, 1n); - const transaction = nextTransferFactory.createTransactionForESDTTokenTransfer({ + const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, receiver: bob, tokenTransfers: [firstTransfer, secondTransfer], diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 002fa0396..e955d6035 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -1,7 +1,26 @@ -import { ErrBadUsage } from "../errors"; -import { IAddress } from "../interface"; +import { Err, ErrBadUsage } from "../errors"; +import { + IAddress, + IChainID, + IGasLimit, + IGasPrice, + INonce, + ITokenTransfer, + ITransactionPayload, + ITransactionValue, +} from "../interface"; +import { + AddressValue, + ArgSerializer, + BigUIntValue, + BytesValue, + TypedValue, + U16Value, + U64Value, +} from "../smartcontracts"; import { NextTokenTransfer, Token } from "../tokens"; import { Transaction } from "../transaction"; +import { TransactionPayload } from "../transactionPayload"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; import { TransactionBuilder } from "./transactionBuilder"; @@ -17,23 +36,66 @@ interface IConfig { gasLimitMultiESDTNFTTransfer: bigint; } -interface TokenComputer { +interface ITokenComputer { isFungible(token: Token): boolean; } +interface IGasEstimator { + forEGLDTransfer(dataLength: number): number; + forESDTTransfer(dataLength: number): number; + forESDTNFTTransfer(dataLength: number): number; + forMultiESDTNFTTransfer(dataLength: number, numTransfers: number): number; +} + /** * Use this class to create transactions for native token transfers (EGLD) or custom tokens transfers (ESDT/NTF/MetaESDT). * This name is only temporary, the class will be renamed to `TransferTransactionsFactory`. */ -export class NextTransferTransactionsFactory { - private readonly config: IConfig; - private readonly dataArgsBuilder: TokenTransfersDataBuilder; - private readonly tokenComputer: TokenComputer; - - constructor(options: { config: IConfig; tokenComputer: TokenComputer }) { - this.config = options.config; - this.tokenComputer = options.tokenComputer; - this.dataArgsBuilder = new TokenTransfersDataBuilder(); +export class TransferTransactionsFactory { + private readonly config?: IConfig; + private readonly dataArgsBuilder?: TokenTransfersDataBuilder; + private readonly tokenComputer?: ITokenComputer; + private readonly gasEstimator?: IGasEstimator; + + constructor(options: IGasEstimator | { config: IConfig; tokenComputer: ITokenComputer }) { + if (this.isGasEstimator(options)) { + this.gasEstimator = options; + } else { + this.config = options.config; + this.tokenComputer = options.tokenComputer; + this.dataArgsBuilder = new TokenTransfersDataBuilder(); + } + } + + private isGasEstimator(options: any): options is IGasEstimator { + return ( + typeof options === "object" && + typeof options.forEGLDTransfer === "function" && + typeof options.forESDTTransfer === "function" && + typeof options.forESDTNFTTransfer === "function" && + typeof options.forMultiESDTNFTTransfer === "function" + ); + } + + private isGasEstimatorDefined(): boolean { + if (this.gasEstimator === undefined) { + return false; + } + return this.isGasEstimator(this.gasEstimator); + } + + private ensureMembersAreDefined() { + if (this.config === undefined) { + throw new Err("'config' is not defined"); + } + + if (this.dataArgsBuilder === undefined) { + throw new Err("`dataArgsBuilder is not defined`"); + } + + if (this.tokenComputer === undefined) { + throw new Err("`tokenComputer is not defined`"); + } } createTransactionForNativeTokenTransfer(options: { @@ -42,10 +104,12 @@ export class NextTransferTransactionsFactory { nativeAmount: bigint; data?: string; }): Transaction { + this.ensureMembersAreDefined(); + const data = options.data || ""; return new TransactionBuilder({ - config: this.config, + config: this.config!, sender: options.sender, receiver: options.receiver, dataParts: [data], @@ -60,6 +124,8 @@ export class NextTransferTransactionsFactory { receiver: IAddress; tokenTransfers: NextTokenTransfer[]; }): Transaction { + this.ensureMembersAreDefined(); + const numberOfTransfers = options.tokenTransfers.length; if (numberOfTransfers === 0) { @@ -70,17 +136,17 @@ export class NextTransferTransactionsFactory { return this.createSingleESDTTransferDraft(options); } - const transferArgs = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer( + const transferArgs = this.dataArgsBuilder!.buildArgsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers, ); const extraGasForTransfer = - this.config.gasLimitMultiESDTNFTTransfer * BigInt(numberOfTransfers) + + this.config!.gasLimitMultiESDTNFTTransfer * BigInt(numberOfTransfers) + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); return new TransactionBuilder({ - config: this.config, + config: this.config!, sender: options.sender, receiver: options.sender, dataParts: transferArgs, @@ -89,27 +155,184 @@ export class NextTransferTransactionsFactory { }).build(); } + createEGLDTransfer(args: { + nonce?: INonce; + value: ITransactionValue; + receiver: IAddress; + sender: IAddress; + gasPrice?: IGasPrice; + gasLimit?: IGasLimit; + data?: ITransactionPayload; + chainID: IChainID; + }) { + if (!this.isGasEstimatorDefined()) { + throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + } + + const dataLength = args.data?.length() || 0; + const estimatedGasLimit = this.gasEstimator!.forEGLDTransfer(dataLength); + + return new Transaction({ + nonce: args.nonce, + value: args.value, + receiver: args.receiver, + sender: args.sender, + gasPrice: args.gasPrice, + gasLimit: args.gasLimit || estimatedGasLimit, + data: args.data, + chainID: args.chainID, + }); + } + + createESDTTransfer(args: { + tokenTransfer: ITokenTransfer; + nonce?: INonce; + receiver: IAddress; + sender: IAddress; + gasPrice?: IGasPrice; + gasLimit?: IGasLimit; + chainID: IChainID; + }) { + if (!this.isGasEstimatorDefined()) { + throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + } + + const { argumentsString } = new ArgSerializer().valuesToString([ + // The token identifier + BytesValue.fromUTF8(args.tokenTransfer.tokenIdentifier), + // The transfered amount + new BigUIntValue(args.tokenTransfer.valueOf()), + ]); + + const data = `ESDTTransfer@${argumentsString}`; + const transactionPayload = new TransactionPayload(data); + const dataLength = transactionPayload.length() || 0; + const estimatedGasLimit = this.gasEstimator!.forESDTTransfer(dataLength); + + return new Transaction({ + nonce: args.nonce, + receiver: args.receiver, + sender: args.sender, + gasPrice: args.gasPrice, + gasLimit: args.gasLimit || estimatedGasLimit, + data: transactionPayload, + chainID: args.chainID, + }); + } + + createESDTNFTTransfer(args: { + tokenTransfer: ITokenTransfer; + nonce?: INonce; + destination: IAddress; + sender: IAddress; + gasPrice?: IGasPrice; + gasLimit?: IGasLimit; + chainID: IChainID; + }) { + if (!this.isGasEstimatorDefined()) { + throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + } + + const { argumentsString } = new ArgSerializer().valuesToString([ + // The token identifier + BytesValue.fromUTF8(args.tokenTransfer.tokenIdentifier), + // The nonce of the token + new U64Value(args.tokenTransfer.nonce), + // The transferred quantity + new BigUIntValue(args.tokenTransfer.valueOf()), + // The destination address + new AddressValue(args.destination), + ]); + + const data = `ESDTNFTTransfer@${argumentsString}`; + const transactionPayload = new TransactionPayload(data); + const dataLength = transactionPayload.length() || 0; + const estimatedGasLimit = this.gasEstimator!.forESDTNFTTransfer(dataLength); + + return new Transaction({ + nonce: args.nonce, + receiver: args.sender, + sender: args.sender, + gasPrice: args.gasPrice, + gasLimit: args.gasLimit || estimatedGasLimit, + data: transactionPayload, + chainID: args.chainID, + }); + } + + createMultiESDTNFTTransfer(args: { + tokenTransfers: ITokenTransfer[]; + nonce?: INonce; + destination: IAddress; + sender: IAddress; + gasPrice?: IGasPrice; + gasLimit?: IGasLimit; + chainID: IChainID; + }) { + if (!this.isGasEstimatorDefined()) { + throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + } + + const parts: TypedValue[] = [ + // The destination address + new AddressValue(args.destination), + // Number of tokens + new U16Value(args.tokenTransfers.length), + ]; + + for (const payment of args.tokenTransfers) { + parts.push( + ...[ + // The token identifier + BytesValue.fromUTF8(payment.tokenIdentifier), + // The nonce of the token + new U64Value(payment.nonce), + // The transfered quantity + new BigUIntValue(payment.valueOf()), + ], + ); + } + + const { argumentsString } = new ArgSerializer().valuesToString(parts); + const data = `MultiESDTNFTTransfer@${argumentsString}`; + const transactionPayload = new TransactionPayload(data); + const dataLength = transactionPayload.length() || 0; + const estimatedGasLimit = this.gasEstimator!.forMultiESDTNFTTransfer(dataLength, args.tokenTransfers.length); + + return new Transaction({ + nonce: args.nonce, + receiver: args.sender, + sender: args.sender, + gasPrice: args.gasPrice, + gasLimit: args.gasLimit || estimatedGasLimit, + data: transactionPayload, + chainID: args.chainID, + }); + } + private createSingleESDTTransferDraft(options: { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; }): Transaction { + this.ensureMembersAreDefined(); + let transferArgs: string[] = []; const transfer = options.tokenTransfers[0]; let extraGasForTransfer = 0n; let receiver = options.receiver; - if (this.tokenComputer.isFungible(transfer.token)) { - transferArgs = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); - extraGasForTransfer = this.config.gasLimitESDTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_TRANSFER); + if (this.tokenComputer!.isFungible(transfer.token)) { + transferArgs = this.dataArgsBuilder!.buildArgsForESDTTransfer(transfer); + extraGasForTransfer = this.config!.gasLimitESDTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_TRANSFER); } else { - transferArgs = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); - extraGasForTransfer = this.config.gasLimitESDTNFTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); + transferArgs = this.dataArgsBuilder!.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + extraGasForTransfer = this.config!.gasLimitESDTNFTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); receiver = options.sender; } return new TransactionBuilder({ - config: this.config, + config: this.config!, sender: options.sender, receiver: receiver, dataParts: transferArgs, diff --git a/src/transferTransactionsFactory.spec.ts b/src/transferTransactionsFactory.spec.ts index 93638a384..abc64867e 100644 --- a/src/transferTransactionsFactory.spec.ts +++ b/src/transferTransactionsFactory.spec.ts @@ -3,7 +3,7 @@ import { Address } from "./address"; import { GasEstimator } from "./gasEstimator"; import { TokenTransfer } from "./tokenTransfer"; import { TransactionPayload } from "./transactionPayload"; -import { TransferTransactionsFactory } from "./transferTransactionsFactory"; +import { TransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; describe("test transaction factory", () => { const factory = new TransferTransactionsFactory(new GasEstimator()); diff --git a/src/transferTransactionsFactory.ts b/src/transferTransactionsFactory.ts deleted file mode 100644 index 3e312df95..000000000 --- a/src/transferTransactionsFactory.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, ITokenTransfer, ITransactionPayload, ITransactionValue } from "./interface"; -import { ArgSerializer } from "./smartcontracts/argSerializer"; -import { AddressValue, BigUIntValue, BytesValue, TypedValue, U16Value, U64Value } from "./smartcontracts/typesystem"; -import { Transaction } from "./transaction"; -import { TransactionPayload } from "./transactionPayload"; - -interface IGasEstimator { - forEGLDTransfer(dataLength: number): number; - forESDTTransfer(dataLength: number): number; - forESDTNFTTransfer(dataLength: number): number; - forMultiESDTNFTTransfer(dataLength: number, numTransfers: number): number; -} - -/** - * @deprecated Use {@link NextTransferTransactionsFactory} instead. - */ -export class TransferTransactionsFactory { - private readonly gasEstimator; - - constructor(gasEstimator: IGasEstimator) { - this.gasEstimator = gasEstimator; - } - - createEGLDTransfer(args: { - nonce?: INonce; - value: ITransactionValue; - receiver: IAddress; - sender: IAddress; - gasPrice?: IGasPrice; - gasLimit?: IGasLimit; - data?: ITransactionPayload; - chainID: IChainID; - }) { - const dataLength = args.data?.length() || 0; - const estimatedGasLimit = this.gasEstimator.forEGLDTransfer(dataLength); - - return new Transaction({ - nonce: args.nonce, - value: args.value, - receiver: args.receiver, - sender: args.sender, - gasPrice: args.gasPrice, - gasLimit: args.gasLimit || estimatedGasLimit, - data: args.data, - chainID: args.chainID, - }); - } - - createESDTTransfer(args: { - tokenTransfer: ITokenTransfer; - nonce?: INonce; - receiver: IAddress; - sender: IAddress; - gasPrice?: IGasPrice; - gasLimit?: IGasLimit; - chainID: IChainID; - }) { - const { argumentsString } = new ArgSerializer().valuesToString([ - // The token identifier - BytesValue.fromUTF8(args.tokenTransfer.tokenIdentifier), - // The transfered amount - new BigUIntValue(args.tokenTransfer.valueOf()), - ]); - - const data = `ESDTTransfer@${argumentsString}`; - const transactionPayload = new TransactionPayload(data); - const dataLength = transactionPayload.length() || 0; - const estimatedGasLimit = this.gasEstimator.forESDTTransfer(dataLength); - - return new Transaction({ - nonce: args.nonce, - receiver: args.receiver, - sender: args.sender, - gasPrice: args.gasPrice, - gasLimit: args.gasLimit || estimatedGasLimit, - data: transactionPayload, - chainID: args.chainID, - }); - } - - createESDTNFTTransfer(args: { - tokenTransfer: ITokenTransfer; - nonce?: INonce; - destination: IAddress; - sender: IAddress; - gasPrice?: IGasPrice; - gasLimit?: IGasLimit; - chainID: IChainID; - }) { - const { argumentsString } = new ArgSerializer().valuesToString([ - // The token identifier - BytesValue.fromUTF8(args.tokenTransfer.tokenIdentifier), - // The nonce of the token - new U64Value(args.tokenTransfer.nonce), - // The transferred quantity - new BigUIntValue(args.tokenTransfer.valueOf()), - // The destination address - new AddressValue(args.destination), - ]); - - const data = `ESDTNFTTransfer@${argumentsString}`; - const transactionPayload = new TransactionPayload(data); - const dataLength = transactionPayload.length() || 0; - const estimatedGasLimit = this.gasEstimator.forESDTNFTTransfer(dataLength); - - return new Transaction({ - nonce: args.nonce, - receiver: args.sender, - sender: args.sender, - gasPrice: args.gasPrice, - gasLimit: args.gasLimit || estimatedGasLimit, - data: transactionPayload, - chainID: args.chainID, - }); - } - - createMultiESDTNFTTransfer(args: { - tokenTransfers: ITokenTransfer[]; - nonce?: INonce; - destination: IAddress; - sender: IAddress; - gasPrice?: IGasPrice; - gasLimit?: IGasLimit; - chainID: IChainID; - }) { - const parts: TypedValue[] = [ - // The destination address - new AddressValue(args.destination), - // Number of tokens - new U16Value(args.tokenTransfers.length), - ]; - - for (const payment of args.tokenTransfers) { - parts.push( - ...[ - // The token identifier - BytesValue.fromUTF8(payment.tokenIdentifier), - // The nonce of the token - new U64Value(payment.nonce), - // The transfered quantity - new BigUIntValue(payment.valueOf()), - ] - ); - } - - const { argumentsString } = new ArgSerializer().valuesToString(parts); - const data = `MultiESDTNFTTransfer@${argumentsString}`; - const transactionPayload = new TransactionPayload(data); - const dataLength = transactionPayload.length() || 0; - const estimatedGasLimit = this.gasEstimator.forMultiESDTNFTTransfer(dataLength, args.tokenTransfers.length); - - return new Transaction({ - nonce: args.nonce, - receiver: args.sender, - sender: args.sender, - gasPrice: args.gasPrice, - gasLimit: args.gasLimit || estimatedGasLimit, - data: transactionPayload, - chainID: args.chainID, - }); - } -} From 42337c9c05ddc8f5cac18d78f11d7d2f7bc9eb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 11:54:04 +0200 Subject: [PATCH 172/275] TransactionOutcome: renaming, plus new field for direct contract outcome. --- .../delegationTransactionsOutcomeParser.ts | 6 +-- src/transactionsOutcomeParsers/resources.ts | 24 ++++++++-- ...okenManagementTransactionsOutcomeParser.ts | 44 +++++++++---------- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index 036706ee2..da3883681 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -1,12 +1,12 @@ +import { Address } from "../address"; import { ErrParseTransactionOutcome } from "../errors"; import { TransactionEvent, TransactionOutcome } from "./resources"; -import { Address } from "../address"; export class DelegationTransactionsOutcomeParser { constructor() {} parseCreateNewDelegationContract(transactionOutcome: TransactionOutcome): { contractAddress: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "SCDeploy"); @@ -39,7 +39,7 @@ export class DelegationTransactionsOutcomeParser { private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { const allEvents = []; - allEvents.push(...transactionOutcome.transactionLogs.events); + allEvents.push(...transactionOutcome.logs.events); for (const item of transactionOutcome.smartContractResults) { allEvents.push(...item.logs.events); diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 19bdea09b..395d51f74 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -43,14 +43,30 @@ export class SmartContractResult { } export class TransactionOutcome { - function: string; + directSmartContractCallOutcome: SmartContractCallOutcome; smartContractResults: SmartContractResult[]; - transactionLogs: TransactionLogs; + logs: TransactionLogs; constructor(init: Partial) { - this.function = ""; + this.directSmartContractCallOutcome = new SmartContractCallOutcome({}); this.smartContractResults = []; - this.transactionLogs = new TransactionLogs({}); + this.logs = new TransactionLogs({}); + + Object.assign(this, init); + } +} + +export class SmartContractCallOutcome { + function: string; + returnDataParts: Uint8Array[]; + returnMessage: string; + returnCode: string; + + constructor(init: Partial) { + this.function = ""; + this.returnDataParts = []; + this.returnMessage = ""; + this.returnCode = ""; Object.assign(this, init); } diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index 5cbd89b20..f33ff249c 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -1,34 +1,34 @@ -import { TransactionEvent, TransactionOutcome } from "./resources"; -import { ErrParseTransactionOutcome } from "../errors"; import { Address } from "../address"; +import { ErrParseTransactionOutcome } from "../errors"; import { bufferToBigInt } from "../smartcontracts/codec/utils"; +import { TransactionEvent, TransactionOutcome } from "./resources"; export class TokenManagementTransactionsOutcomeParser { constructor() {} parseIssueFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "issue"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "issueNonFungible"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "issueSemiFungible"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "registerMetaESDT"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); @@ -37,7 +37,7 @@ export class TokenManagementTransactionsOutcomeParser { parseRegisterAndSetAllRoles( transactionOutcome: TransactionOutcome, ): { tokenIdentifier: string; roles: string[] }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const registerEvents = this.findEventsByIdentifier(transactionOutcome, "registerAndSetAllRoles"); const setRoleEvents = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); @@ -56,11 +56,11 @@ export class TokenManagementTransactionsOutcomeParser { } parseSetBurnRoleGlobally(transactionOutcome: TransactionOutcome) { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); } parseUnsetBurnRoleGlobally(transactionOutcome: TransactionOutcome) { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); } parseSetSpecialRole(transactionOutcome: TransactionOutcome): { @@ -68,7 +68,7 @@ export class TokenManagementTransactionsOutcomeParser { tokenIdentifier: string; roles: string[]; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); return events.map((event) => this.getOutputForSetSpecialRoleEvent(event)); @@ -92,7 +92,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; initialQuantity: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTCreate"); return events.map((event) => this.getOutputForNftCreateEvent(event)); @@ -116,7 +116,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; mintedSupply: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalMint"); return events.map((event) => this.getOutputForLocalMintEvent(event)); @@ -147,7 +147,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; burntSupply: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalBurn"); return events.map((event) => this.getOutputForLocalBurnEvent(event)); @@ -173,14 +173,14 @@ export class TokenManagementTransactionsOutcomeParser { } parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTPause"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseUnpause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnPause"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); @@ -192,7 +192,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; balance: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTFreeze"); return events.map((event) => this.getOutputForFreezeEvent(event)); @@ -223,7 +223,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; balance: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnFreeze"); return events.map((event) => this.getOutputForUnfreezeEvent(event)); @@ -254,7 +254,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; balance: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTWipe"); return events.map((event) => this.getOutputForWipeEvent(event)); @@ -284,7 +284,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; attributes: Uint8Array; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); return events.map((event) => this.getOutputForUpdateAttributesEvent(event)); @@ -311,7 +311,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; addedQuantity: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); return events.map((event) => this.getOutputForAddQuantityEvent(event)); @@ -338,7 +338,7 @@ export class TokenManagementTransactionsOutcomeParser { nonce: bigint; burntQuantity: bigint; }[] { - this.ensureNoError(transactionOutcome.transactionLogs.events); + this.ensureNoError(transactionOutcome.logs.events); const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTBurn"); return events.map((event) => this.getOutputForBurnQuantityEvent(event)); @@ -386,7 +386,7 @@ export class TokenManagementTransactionsOutcomeParser { private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { const allEvents = []; - allEvents.push(...transactionOutcome.transactionLogs.events); + allEvents.push(...transactionOutcome.logs.events); for (const item of transactionOutcome.smartContractResults) { allEvents.push(...item.logs.events); From c6ac6c89f0e4abaa05202278f6e6ec255e799d12 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 12:47:27 +0200 Subject: [PATCH 173/275] transaction signing by hash --- src/constants.ts | 3 +- src/smartcontracts/interaction.spec.ts | 35 ++++++++++++++++++--- src/smartcontracts/resultsParser.ts | 2 +- src/transaction.spec.ts | 39 +++++++++++++++++++++++ src/transactionComputer.ts | 43 ++++++++++++++++++++++++-- src/transactionWatcher.ts | 4 +-- 6 files changed, 114 insertions(+), 12 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 21dfb69d0..42dd256d0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,4 +16,5 @@ export const DEFAULT_HRP = "erd"; export const ESDT_CONTRACT_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; export const DEFAULT_MESSAGE_VERSION = 1; export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; -export const DEFAULT_HEX_HASH_LENGTH = 64; +export const HEX_TRANSACTION_HASH_LENGTH = 64; +export const BECH32_ADDRESS_LENGTH = 62; diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 4b0f9f7bc..fbad250e2 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -237,7 +237,12 @@ describe("test smart contract interactor", function () { assert.deepEqual(counterValue!.valueOf(), new BigNumber(7)); - let incrementTransaction = incrementInteraction.withSender(alice.address).withNonce(14).buildTransaction(); + let incrementTransaction = incrementInteraction + .withSender(alice.address) + .withNonce(14) + .withChainID("mock") + .buildTransaction(); + incrementTransaction.applySignature(await alice.signer.sign(incrementTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@08"); let { bundle: { firstValue: valueAfterIncrement } } = await controller.execute(incrementInteraction, incrementTransaction); @@ -245,7 +250,12 @@ describe("test smart contract interactor", function () { // Decrement three times (simulate three parallel broadcasts). Wait for execution of the latter (third transaction). Return fake "5". // Decrement #1 - let decrementTransaction = decrementInteraction.withSender(alice.address).withNonce(15).buildTransaction(); + let decrementTransaction = decrementInteraction + .withSender(alice.address) + .withNonce(15) + .withChainID("mock") + .buildTransaction(); + decrementTransaction.applySignature(await alice.signer.sign(decrementTransaction.serializeForSigning())); await provider.sendTransaction(decrementTransaction); // Decrement #2 @@ -294,7 +304,12 @@ describe("test smart contract interactor", function () { ); // start() - let startTransaction = startInteraction.withSender(alice.address).withNonce(14).buildTransaction(); + let startTransaction = startInteraction + .withSender(alice.address) + .withNonce(14) + .withChainID("mock") + .buildTransaction(); + startTransaction.applySignature(await alice.signer.sign(startTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b"); let { bundle: { returnCode: startReturnCode, values: startReturnValues } } = await controller.execute(startInteraction, startTransaction); @@ -304,7 +319,12 @@ describe("test smart contract interactor", function () { assert.lengthOf(startReturnValues, 0); // status() (this is a view function, but for the sake of the test, we'll execute it) - let statusTransaction = statusInteraction.withSender(alice.address).withNonce(15).buildTransaction(); + let statusTransaction = statusInteraction + .withSender(alice.address) + .withNonce(15) + .withChainID("mock") + .buildTransaction(); + statusTransaction.applySignature(await alice.signer.sign(statusTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@01"); let { bundle: { returnCode: statusReturnCode, values: statusReturnValues, firstValue: statusFirstValue } } = await controller.execute(statusInteraction, statusTransaction); @@ -315,7 +335,12 @@ describe("test smart contract interactor", function () { assert.deepEqual(statusFirstValue!.valueOf(), { name: "Running", fields: [] }); // lotteryInfo() (this is a view function, but for the sake of the test, we'll execute it) - let getLotteryInfoTransaction = getLotteryInfoInteraction.withSender(alice.address).withNonce(15).buildTransaction(); + let getLotteryInfoTransaction = getLotteryInfoInteraction + .withSender(alice.address) + .withNonce(15) + .withChainID("mock") + .buildTransaction(); + getLotteryInfoTransaction.applySignature(await alice.signer.sign(getLotteryInfoTransaction.serializeForSigning())); provider.mockGetTransactionWithAnyHashAsNotarizedWithOneResult("@6f6b@0000000b6c75636b792d746f6b656e000000010100000000000000005fc2b9dbffffffff00000001640000000a140ec80fa7ee88000000"); let { bundle: { returnCode: infoReturnCode, values: infoReturnValues, firstValue: infoFirstValue } } = await controller.execute(getLotteryInfoInteraction, getLotteryInfoTransaction); diff --git a/src/smartcontracts/resultsParser.ts b/src/smartcontracts/resultsParser.ts index 6186e8e6c..4138914a8 100644 --- a/src/smartcontracts/resultsParser.ts +++ b/src/smartcontracts/resultsParser.ts @@ -308,7 +308,7 @@ export class ResultsParser { return null; } - private sliceDataFieldInParts(data: string): { returnCode: ReturnCode, returnDataParts: Buffer[] } { + protected sliceDataFieldInParts(data: string): { returnCode: ReturnCode, returnDataParts: Buffer[] } { // By default, skip the first part, which is usually empty (e.g. "[empty]@6f6b") let startingIndex = 1; diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 257248ade..ea0131bc3 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -614,4 +614,43 @@ describe("test transaction", async () => { transaction.applyGuardianSignature(transaction.getSignature()); assert.isTrue(transaction.isGuardedTransaction()); }); + + it("test sign using hash", async () => { + let transaction = new Transaction({ + nonce: 89n, + value: 0n, + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "integration tests chain ID", + version: 2, + options: 1, + }); + + transaction.signature = await wallets.alice.signer.sign( + Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + ); + + assert.equal( + "f0c81f2393b1ec5972c813f817bae8daa00ade91c6f75ea604ab6a4d2797aca4378d783023ff98f1a02717fe4f24240cdfba0b674ee9abb18042203d713bc70a", + Buffer.from(transaction.signature).toString("hex"), + ); + }); + + it("should apply guardian", async () => { + let transaction = new Transaction({ + nonce: 89n, + value: 0n, + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "localnet", + }); + + transactionComputer.applyGuardian(transaction, wallets.carol.address.toBech32()); + + assert.equal(transaction.version, 2); + assert.equal(transaction.options, 2); + assert.equal(transaction.guardian, wallets.carol.address.toBech32()); + }); }); diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 0628205b0..36c0c0bf8 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -4,8 +4,10 @@ import BigNumber from "bignumber.js"; import { ITransaction } from "./interface"; import { ProtoSerializer } from "./proto"; import { Transaction } from "./transaction"; +import { BECH32_ADDRESS_LENGTH, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN } from "./constants"; const createTransactionHasher = require("blake2b"); +const createKeccakHash = require("keccak"); const TRANSACTION_HASH_LENGTH = 32; /** @@ -41,14 +43,23 @@ export class TransactionComputer { } computeBytesForSigning(transaction: ITransaction): Uint8Array { - // TODO: do some checks for the transaction e.g. sender, chain ID etc. - // TODO: for appropriate tx.version, interpret tx.options accordingly and sign using the content / data hash + this.ensureFields(transaction); + + if (transaction.version >= 2 && this.hasOptionsSetForHashSigning(transaction)) { + return this.computeHashForSigning(transaction); + } const plainTransaction = this.toPlainObjectForSigning(transaction); const serialized = JSON.stringify(plainTransaction); return new Uint8Array(Buffer.from(serialized)); } + computeHashForSigning(transaction: ITransaction): Uint8Array { + const plainTransaction = this.toPlainObjectForSigning(transaction); + const signable = Buffer.from(JSON.stringify(plainTransaction)); + return createKeccakHash("keccak256").update(signable).digest(); + } + computeTransactionHash(transaction: ITransaction): Uint8Array { const serializer = new ProtoSerializer(); const buffer = serializer.serializeTransaction(new Transaction(transaction)); @@ -57,6 +68,20 @@ export class TransactionComputer { return Buffer.from(hash, "hex"); } + hasOptionsSetForGuardedTransaction(transaction: ITransaction): boolean { + return (transaction.options & TRANSACTION_OPTIONS_TX_GUARDED) == TRANSACTION_OPTIONS_TX_GUARDED; + } + + hasOptionsSetForHashSigning(transaction: ITransaction): boolean { + return (transaction.options & TRANSACTION_OPTIONS_TX_HASH_SIGN) == TRANSACTION_OPTIONS_TX_HASH_SIGN; + } + + applyGuardian(transaction: ITransaction, guardian: string) { + transaction.version = 2; + transaction.options = transaction.options | TRANSACTION_OPTIONS_TX_GUARDED; + transaction.guardian = guardian; + } + private toPlainObjectForSigning(transaction: ITransaction) { return { nonce: Number(transaction.nonce), @@ -79,5 +104,17 @@ export class TransactionComputer { return value && value.length ? Buffer.from(value).toString("base64") : undefined; } - // TODO: add missing functions wrt. specs + private ensureFields(transaction: ITransaction) { + if (transaction.sender.length !== BECH32_ADDRESS_LENGTH) { + throw new errors.ErrBadUsage("The `sender` field is not set"); + } + + if (transaction.receiver.length !== BECH32_ADDRESS_LENGTH) { + throw new errors.ErrBadUsage("The `receiver` field is not set"); + } + + if (!transaction.chainID.length) { + throw new errors.ErrBadUsage("The `chainID` field is not set"); + } + } } diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index 3a43b9237..7acd56a3f 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -1,5 +1,5 @@ import { AsyncTimer } from "./asyncTimer"; -import { DEFAULT_HEX_HASH_LENGTH } from "./constants"; +import { HEX_TRANSACTION_HASH_LENGTH } from "./constants"; import { Err, ErrExpectedTransactionEventsNotFound, @@ -153,7 +153,7 @@ export class TransactionWatcher { const hash = typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); - if (hash.length !== DEFAULT_HEX_HASH_LENGTH) { + if (hash.length !== HEX_TRANSACTION_HASH_LENGTH) { throw new Err("Invalid transaction hash length. The length of a hex encoded hash should be 64."); } From 35d9efbd0488bd816d732ff7ccdf0eabe45b48b2 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 13:01:56 +0200 Subject: [PATCH 174/275] explicitly add gas price on test transaction --- src/transaction.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index ea0131bc3..3b6c74162 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -622,6 +622,7 @@ describe("test transaction", async () => { sender: wallets.alice.address.toBech32(), receiver: wallets.bob.address.toBech32(), gasLimit: 50000n, + gasPrice: 1000000000n, chainID: "integration tests chain ID", version: 2, options: 1, From b1d7896c8129bacc9137d37837deabcf245a5511 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 13:26:02 +0200 Subject: [PATCH 175/275] change error message for invalid sender or receiver --- src/transactionComputer.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 36c0c0bf8..479879971 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -106,11 +106,15 @@ export class TransactionComputer { private ensureFields(transaction: ITransaction) { if (transaction.sender.length !== BECH32_ADDRESS_LENGTH) { - throw new errors.ErrBadUsage("The `sender` field is not set"); + throw new errors.ErrBadUsage( + "The `sender` field is invalid. Should be set to the bech32 address of the sender.", + ); } if (transaction.receiver.length !== BECH32_ADDRESS_LENGTH) { - throw new errors.ErrBadUsage("The `receiver` field is not set"); + throw new errors.ErrBadUsage( + "The `receiver` field is invalid. Should be set to the bech32 address of the receiver.", + ); } if (!transaction.chainID.length) { From 2ecacdff2a38c684a444c21b4ea24ccd9b17825d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 13:41:07 +0200 Subject: [PATCH 176/275] change error message --- src/transactionComputer.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 479879971..a5fc99843 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -106,15 +106,11 @@ export class TransactionComputer { private ensureFields(transaction: ITransaction) { if (transaction.sender.length !== BECH32_ADDRESS_LENGTH) { - throw new errors.ErrBadUsage( - "The `sender` field is invalid. Should be set to the bech32 address of the sender.", - ); + throw new errors.ErrBadUsage("Invalid `sender` field. Should be the bech32 address of the sender."); } if (transaction.receiver.length !== BECH32_ADDRESS_LENGTH) { - throw new errors.ErrBadUsage( - "The `receiver` field is invalid. Should be set to the bech32 address of the receiver.", - ); + throw new errors.ErrBadUsage("Invalid `receiver` field. Should be the bech32 address of the receiver."); } if (!transaction.chainID.length) { From e83494853a5e7536a480444c33eb6ca23b848e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 13:47:11 +0200 Subject: [PATCH 177/275] Renaming. --- src/converters/transactionsConverter.ts | 59 +++++++++++++++++++ ...elegationTransactionsOutcomeParser.spec.ts | 4 +- ...anagementTransactionsOutcomeParser.spec.ts | 32 +++++----- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index c45c3de64..eb5631b9d 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -1,5 +1,14 @@ import { IPlainTransactionObject, ITransaction } from "../interface"; +import { IContractResultItem, ITransactionEvent, ITransactionOnNetwork } from "../interfaceOfNetwork"; +import { ResultsParser } from "../smartcontracts"; import { Transaction } from "../transaction"; +import { + SmartContractCallOutcome, + SmartContractResult, + TransactionEvent, + TransactionLogs, + TransactionOutcome, +} from "../transactionsOutcomeParsers/resources"; export class TransactionsConverter { public transactionToPlainObject(transaction: ITransaction): IPlainTransactionObject { @@ -61,4 +70,54 @@ export class TransactionsConverter { private bufferFromHex(value?: string) { return Buffer.from(value || "", "hex"); } + + public transactionOnNetworkToOutcome(transactionOnNetwork: ITransactionOnNetwork): TransactionOutcome { + // In the future, this will not be needed because the transaction, as returned from the API, + // will hold the data corresponding to the direct smart contract call outcome (in case of smart contract calls). + const resultsParser = new ResultsParser(); + const callOutcomeBundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + const callOutcome = new SmartContractCallOutcome({ + returnCode: callOutcomeBundle.returnCode.toString(), + returnMessage: callOutcomeBundle.returnMessage, + returnDataParts: callOutcomeBundle.values, + }); + + const contractResults = transactionOnNetwork.contractResults.items.map((result) => + this.smartContractResultOnNetworkToSmartContractResult(result), + ); + + const logs = new TransactionLogs({ + events: transactionOnNetwork.logs.events.map((event) => this.eventOnNetworkToEvent(event)), + }); + + return new TransactionOutcome({ + logs: logs, + smartContractResults: contractResults, + directSmartContractCallOutcome: callOutcome, + }); + } + + private smartContractResultOnNetworkToSmartContractResult( + resultOnNetwork: IContractResultItem, + ): SmartContractResult { + return new SmartContractResult({ + sender: resultOnNetwork.sender.bech32(), + receiver: resultOnNetwork.receiver.bech32(), + data: Buffer.from(resultOnNetwork.data), + logs: new TransactionLogs({ + events: resultOnNetwork.logs.events.map((event) => this.eventOnNetworkToEvent(event)), + }), + }); + } + + private eventOnNetworkToEvent(eventOnNetwork: ITransactionEvent): TransactionEvent { + return new TransactionEvent({ + address: eventOnNetwork.address.bech32(), + identifier: eventOnNetwork.identifier, + // TODO: Fix this workaround. + topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex()).toString("base64")), + // TODO: Check if OK. + data: Buffer.from(eventOnNetwork.data), + }); + } } diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts index f94887951..f8b955f79 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; +import { Address } from "../address"; import { DelegationTransactionsOutcomeParser } from "./delegationTransactionsOutcomeParser"; import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; -import { Address } from "../address"; describe("test token management transactions outcome parser", () => { const parser = new DelegationTransactionsOutcomeParser(); @@ -50,7 +50,7 @@ describe("test token management transactions outcome parser", () => { logs: scResultLog, }); - const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], logs: logs }); const outcome = parser.parseCreateNewDelegationContract(txOutcome); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index cecccfaf0..7dce611cd 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { ErrParseTransactionOutcome } from "../errors"; -import { TokenManagementTransactionsOutcomeParser } from "./tokenManagementTransactionsOutcomeParser"; import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; +import { TokenManagementTransactionsOutcomeParser } from "./tokenManagementTransactionsOutcomeParser"; describe("test token management transactions outcome parser", () => { const parser = new TokenManagementTransactionsOutcomeParser(); @@ -15,7 +15,7 @@ describe("test token management transactions outcome parser", () => { }); const logs = new TransactionLogs({ events: [event] }); - const txOutcome = new TransactionOutcome({ transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ logs: logs }); assert.throws( () => { @@ -41,7 +41,7 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const txOutcome = new TransactionOutcome({ transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ logs: logs }); const outcome = parser.parseIssueFungible(txOutcome); assert.lengthOf(outcome, 1); @@ -75,7 +75,7 @@ describe("test token management transactions outcome parser", () => { events: [firstEvent, secondEvent, thirdEvent], }); - const txOutcome = new TransactionOutcome({ transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ logs: logs }); const outcome = parser.parseIssueNonFungible(txOutcome); assert.lengthOf(outcome, 1); @@ -97,7 +97,7 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const txOutcome = new TransactionOutcome({ transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ logs: logs }); const outcome = parser.parseIssueSemiFungible(txOutcome); assert.lengthOf(outcome, 1); @@ -119,7 +119,7 @@ describe("test token management transactions outcome parser", () => { events: [event], }); - const txOutcome = new TransactionOutcome({ transactionLogs: logs }); + const txOutcome = new TransactionOutcome({ logs: logs }); const outcome = parser.parseRegisterMetaEsdt(txOutcome); assert.lengthOf(outcome, 1); @@ -181,7 +181,7 @@ describe("test token management transactions outcome parser", () => { const txOutcome = new TransactionOutcome({ smartContractResults: [scResult], - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseRegisterAndSetAllRoles(txOutcome); @@ -218,7 +218,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseSetSpecialRole(txOutcome); @@ -251,7 +251,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseNftCreate(txOutcome); @@ -279,7 +279,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseLocalMint(txOutcome); @@ -308,7 +308,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseLocalBurn(txOutcome); @@ -335,7 +335,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parsePause(txOutcome); @@ -359,7 +359,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseUnpause(txOutcome); @@ -497,7 +497,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseUpdateAttributes(txOutcome); @@ -525,7 +525,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseAddQuantity(txOutcome); @@ -553,7 +553,7 @@ describe("test token management transactions outcome parser", () => { }); const txOutcome = new TransactionOutcome({ - transactionLogs: transactionLogs, + logs: transactionLogs, }); const outcome = parser.parseBurnQuantity(txOutcome); From 3e2147c9cc7598761f1e31e7d0dfa820c0050250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 13:53:40 +0200 Subject: [PATCH 178/275] Proto as optional dependency (experiment). --- package-lock.json | 80 ++++++++++++++++++++++++++++++++--------------- package.json | 6 ++-- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8973fb291..c16c0f8f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.19.1", + "version": "12.20.0-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.19.1", + "version": "12.20.0-beta.0", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -14,8 +14,7 @@ "blake2b": "2.1.3", "buffer": "6.0.3", "json-duplicate-key-handle": "1.0.0", - "keccak": "3.0.2", - "protobufjs": "7.2.4" + "keccak": "3.0.2" }, "devDependencies": { "@multiversx/sdk-network-providers": "2.2.0", @@ -35,6 +34,9 @@ "tslint": "6.1.3", "typescript": "4.1.2" }, + "optionalDependencies": { + "protobufjs": "7.2.4" + }, "peerDependencies": { "bignumber.js": "^9.0.1" } @@ -619,27 +621,32 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -648,27 +655,32 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true }, "node_modules/@types/assert": { "version": "1.4.6", @@ -691,7 +703,8 @@ "node_modules/@types/node": { "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", - "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" + "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", + "devOptional": true }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", @@ -2929,7 +2942,8 @@ "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true }, "node_modules/loose-envify": { "version": "1.4.0", @@ -3503,6 +3517,7 @@ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", "hasInstallScript": true, + "optional": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -4930,27 +4945,32 @@ "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true }, "@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true }, "@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true }, "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -4959,27 +4979,32 @@ "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true }, "@types/assert": { "version": "1.4.6", @@ -5002,7 +5027,8 @@ "@types/node": { "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", - "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" + "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", + "devOptional": true }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -6788,7 +6814,8 @@ "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true }, "loose-envify": { "version": "1.4.0", @@ -7234,6 +7261,7 @@ "version": "7.2.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", diff --git a/package.json b/package.json index 1175e6a7b..03d43a264 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.19.1", + "version": "12.20.0-beta.0", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -30,7 +30,9 @@ "blake2b": "2.1.3", "buffer": "6.0.3", "json-duplicate-key-handle": "1.0.0", - "keccak": "3.0.2", + "keccak": "3.0.2" + }, + "optionalDependencies": { "protobufjs": "7.2.4" }, "devDependencies": { From 625da3304af7ba5e6eed71e10bc64b116b1c6c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 14:04:37 +0200 Subject: [PATCH 179/275] Without protobuf. --- package-lock.json | 195 +--------------------------------------------- package.json | 5 +- 2 files changed, 5 insertions(+), 195 deletions(-) diff --git a/package-lock.json b/package-lock.json index c16c0f8f5..50d688c01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.0", + "version": "12.20.0-beta.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.0", + "version": "12.20.0-beta.1", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -34,9 +34,6 @@ "tslint": "6.1.3", "typescript": "4.1.2" }, - "optionalDependencies": { - "protobufjs": "7.2.4" - }, "peerDependencies": { "bignumber.js": "^9.0.1" } @@ -618,70 +615,6 @@ } ] }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "optional": true - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "optional": true - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "optional": true - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "optional": true - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "optional": true - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "optional": true - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "optional": true - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "optional": true - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "optional": true - }, "node_modules/@types/assert": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.4.6.tgz", @@ -704,7 +637,7 @@ "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", - "devOptional": true + "dev": true }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", @@ -2939,12 +2872,6 @@ "node": ">=8" } }, - "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", - "optional": true - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3512,30 +3439,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/protobufjs": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", - "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -4942,70 +4845,6 @@ "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "dev": true }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "optional": true - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "optional": true - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "optional": true - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "optional": true - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "optional": true, - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "optional": true - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "optional": true - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "optional": true - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "optional": true - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "optional": true - }, "@types/assert": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.4.6.tgz", @@ -5028,7 +4867,7 @@ "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", - "devOptional": true + "dev": true }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -6811,12 +6650,6 @@ } } }, - "long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", - "optional": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -7257,26 +7090,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "protobufjs": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", - "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", - "optional": true, - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - } - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index 03d43a264..174824459 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.0", + "version": "12.20.0-beta.1", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -32,9 +32,6 @@ "json-duplicate-key-handle": "1.0.0", "keccak": "3.0.2" }, - "optionalDependencies": { - "protobufjs": "7.2.4" - }, "devDependencies": { "@multiversx/sdk-network-providers": "2.2.0", "@multiversx/sdk-wallet": "3.0.0", From 290ddaa5296f00fcc38e5ad1d4bf9ca1449c6cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 14:08:04 +0200 Subject: [PATCH 180/275] Temporarily skip tests. --- .github/workflows/publish-not-main.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-not-main.yml b/.github/workflows/publish-not-main.yml index 9bae589f3..11d34113c 100644 --- a/.github/workflows/publish-not-main.yml +++ b/.github/workflows/publish-not-main.yml @@ -6,10 +6,10 @@ on: channel: type: choice description: NPM channel - options: - - alpha - - beta - - previous + options: + - alpha + - beta + - previous permissions: contents: write @@ -23,7 +23,7 @@ jobs: with: node-version: 16 registry-url: https://registry.npmjs.org/ - + - name: Create release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -31,9 +31,9 @@ jobs: RELEASE_TAG=v$(node -p "require('./package.json').version") gh release create --prerelease $RELEASE_TAG --target=$GITHUB_SHA --title="$RELEASE_TAG" --generate-notes - - run: npm ci - - run: npm test - + # - run: npm ci + # - run: npm test + - name: Publish to npmjs env: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} From bc43a5138123c41d15e67baee2274ac958879dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 14:10:59 +0200 Subject: [PATCH 181/275] Fix workflow. --- .github/workflows/publish-not-main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-not-main.yml b/.github/workflows/publish-not-main.yml index 11d34113c..3f8f0e69c 100644 --- a/.github/workflows/publish-not-main.yml +++ b/.github/workflows/publish-not-main.yml @@ -33,6 +33,7 @@ jobs: # - run: npm ci # - run: npm test + - run: npm install - name: Publish to npmjs env: From 5959080b10626038a463a204cf8ad69f994ded99 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 14:32:38 +0200 Subject: [PATCH 182/275] fixes after review --- .../transferTransactionsFactory.ts | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index e955d6035..135ae56e5 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -49,7 +49,6 @@ interface IGasEstimator { /** * Use this class to create transactions for native token transfers (EGLD) or custom tokens transfers (ESDT/NTF/MetaESDT). - * This name is only temporary, the class will be renamed to `TransferTransactionsFactory`. */ export class TransferTransactionsFactory { private readonly config?: IConfig; @@ -57,6 +56,12 @@ export class TransferTransactionsFactory { private readonly tokenComputer?: ITokenComputer; private readonly gasEstimator?: IGasEstimator; + /** + * Should be instantiated using `Config` and `TokenComputer`. + * Instantiating this class using GasEstimator represents the legacy version of this class. + * The legacy version contains methods like `createEGLDTransfer`, `createESDTTransfer`, `createESDTNFTTransfer` and `createMultiESDTNFTTransfer`. + */ + // this was done to minimize breaking changes in client code constructor(options: IGasEstimator | { config: IConfig; tokenComputer: ITokenComputer }) { if (this.isGasEstimator(options)) { this.gasEstimator = options; @@ -81,7 +86,7 @@ export class TransferTransactionsFactory { if (this.gasEstimator === undefined) { return false; } - return this.isGasEstimator(this.gasEstimator); + return true; } private ensureMembersAreDefined() { @@ -133,7 +138,7 @@ export class TransferTransactionsFactory { } if (numberOfTransfers === 1) { - return this.createSingleESDTTransferDraft(options); + return this.createSingleESDTTransferTransaction(options); } const transferArgs = this.dataArgsBuilder!.buildArgsForMultiESDTNFTTransfer( @@ -155,6 +160,10 @@ export class TransferTransactionsFactory { }).build(); } + /** + * This is a legacy method. Can only be used if the class was instantiated using `GasEstimator`. + * Use {@link createTransactionForNativeTokenTransfer} instead. + */ createEGLDTransfer(args: { nonce?: INonce; value: ITransactionValue; @@ -166,7 +175,9 @@ export class TransferTransactionsFactory { chainID: IChainID; }) { if (!this.isGasEstimatorDefined()) { - throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + throw new Err( + "You are calling a legacy function to create an EGLD transfer transaction. If this is your intent, then instantiate the class using a `GasEstimator`. Or, instead, use the new, recommended `createTransactionForNativeTokenTransfer` method.", + ); } const dataLength = args.data?.length() || 0; @@ -184,6 +195,10 @@ export class TransferTransactionsFactory { }); } + /** + * This is a legacy method. Can only be used if the class was instantiated using `GasEstimator`. + * Use {@link createTransactionForESDTTokenTransfer} instead. + */ createESDTTransfer(args: { tokenTransfer: ITokenTransfer; nonce?: INonce; @@ -194,7 +209,9 @@ export class TransferTransactionsFactory { chainID: IChainID; }) { if (!this.isGasEstimatorDefined()) { - throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + throw new Err( + "You are calling a legacy function to create an ESDT transfer transaction. If this is your intent, then instantiate the class using a `GasEstimator`. Or, instead, use the new, recommended `createTransactionForESDTTokenTransfer` method.", + ); } const { argumentsString } = new ArgSerializer().valuesToString([ @@ -220,6 +237,10 @@ export class TransferTransactionsFactory { }); } + /** + * This is a legacy method. Can only be used if the class was instantiated using `GasEstimator`. + * Use {@link createTransactionForESDTTokenTransfer} instead. + */ createESDTNFTTransfer(args: { tokenTransfer: ITokenTransfer; nonce?: INonce; @@ -230,7 +251,9 @@ export class TransferTransactionsFactory { chainID: IChainID; }) { if (!this.isGasEstimatorDefined()) { - throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + throw new Err( + "You are calling a legacy function to create an ESDTNFT transfer transaction. If this is your intent, then instantiate the class using a `GasEstimator`. Or, instead, use the new, recommended `createTransactionForESDTTokenTransfer` method.", + ); } const { argumentsString } = new ArgSerializer().valuesToString([ @@ -260,6 +283,10 @@ export class TransferTransactionsFactory { }); } + /** + * This is a legacy method. Can only be used if the class was instantiated using `GasEstimator`. + * Use {@link createTransactionForESDTTokenTransfer} instead. + */ createMultiESDTNFTTransfer(args: { tokenTransfers: ITokenTransfer[]; nonce?: INonce; @@ -270,7 +297,9 @@ export class TransferTransactionsFactory { chainID: IChainID; }) { if (!this.isGasEstimatorDefined()) { - throw new Err("`gasEstimator` is not defined. Instantiate the factory using the gasEstimator."); + throw new Err( + "You are calling a legacy function to create a MultiESDTNFT transfer transaction. If this is your intent, then instantiate the class using a `GasEstimator`. Or, instead, use the new, recommended `createTransactionForESDTTokenTransfer` method.", + ); } const parts: TypedValue[] = [ @@ -310,7 +339,7 @@ export class TransferTransactionsFactory { }); } - private createSingleESDTTransferDraft(options: { + private createSingleESDTTransferTransaction(options: { sender: IAddress; receiver: IAddress; tokenTransfers: NextTokenTransfer[]; From afa4f6f4029baaa0d1c7b6e23ad2f6d3b1d48d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 15:16:31 +0200 Subject: [PATCH 183/275] Simplifications. --- package-lock.json | 1217 +++++++++++++++++++++++++++++++- package.json | 8 +- src/proto/compiled.d.ts | 178 ----- src/proto/compiled.js | 1316 ++++++++++++++++++----------------- src/proto/transaction.proto | 35 +- 5 files changed, 1907 insertions(+), 847 deletions(-) delete mode 100644 src/proto/compiled.d.ts diff --git a/package-lock.json b/package-lock.json index 50d688c01..9e955cb2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.1", + "version": "12.20.0-beta.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.1", + "version": "12.20.0-beta.2", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -30,12 +30,14 @@ "chai": "4.2.0", "esmify": "2.1.1", "mocha": "9.2.2", + "protobufjs-cli": "1.1.2", "ts-node": "9.1.1", "tslint": "6.1.3", "typescript": "4.1.2" }, "peerDependencies": { - "bignumber.js": "^9.0.1" + "bignumber.js": "^9.0.1", + "protobufjs": "^7.2.6" } }, "@multiversx/sdk-wallet:4.0.0-beta.3": { @@ -477,6 +479,18 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", + "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@multiversx/sdk-bls-wasm": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@multiversx/sdk-bls-wasm/-/sdk-bls-wasm-0.3.5.tgz", @@ -615,6 +629,70 @@ } ] }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "peer": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "peer": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "peer": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "peer": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "peer": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "peer": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "peer": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "peer": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "peer": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "peer": true + }, "node_modules/@types/assert": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.4.6.tgz", @@ -627,6 +705,28 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "node_modules/@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -636,8 +736,7 @@ "node_modules/@types/node": { "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", - "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", - "dev": true + "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", @@ -657,6 +756,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -1071,6 +1179,12 @@ "nanoassert": "^1.0.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -1449,6 +1563,18 @@ } ] }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -1753,6 +1879,12 @@ "node": ">=0.12" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -1927,6 +2059,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es6-object-assign": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", @@ -1951,6 +2092,59 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esmify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/esmify/-/esmify-2.1.1.tgz", @@ -1969,6 +2163,35 @@ "through2": "^2.0.5" } }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -1982,6 +2205,15 @@ "node": ">=4" } }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -2010,6 +2242,12 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -2222,6 +2460,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -2656,6 +2900,65 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2749,6 +3052,15 @@ "node": ">= 6" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/labeled-stream-splicer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", @@ -2759,6 +3071,28 @@ "stream-splicer": "^2.0.0" } }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2872,6 +3206,12 @@ "node": ">=8" } }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "peer": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2899,6 +3239,44 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2910,6 +3288,12 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -3278,6 +3662,23 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -3424,6 +3825,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3439,6 +3849,201 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs-cli": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.2.tgz", + "integrity": "sha512-8ivXWxT39gZN4mm4ArQyJrRgnIwZqffBWoLDsE21TmMcKI3XwJMV4lEF2WU02C4JAtgYYc2SfJIltelD8to35g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/protobufjs-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/protobufjs-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/protobufjs-cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protobufjs-cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -3575,6 +4180,15 @@ "node": ">=0.10.0" } }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -3922,6 +4536,15 @@ "node": ">=0.6.0" } }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4079,6 +4702,18 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4107,6 +4742,24 @@ "node": ">=4.2.0" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", @@ -4132,6 +4785,12 @@ "undeclared-identifiers": "bin.js" } }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -4242,6 +4901,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", @@ -4304,6 +4972,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -4724,6 +5398,15 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@jsdoc/salty": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", + "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } + }, "@multiversx/sdk-bls-wasm": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@multiversx/sdk-bls-wasm/-/sdk-bls-wasm-0.3.5.tgz", @@ -4845,6 +5528,70 @@ "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "dev": true }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "peer": true + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "peer": true + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "peer": true + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "peer": true + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "peer": true, + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "peer": true + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "peer": true + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "peer": true + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "peer": true + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "peer": true + }, "@types/assert": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.4.6.tgz", @@ -4857,6 +5604,28 @@ "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", "dev": true }, + "@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, + "@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "requires": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "@types/mocha": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", @@ -4866,8 +5635,7 @@ "@types/node": { "version": "13.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", - "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==", - "dev": true + "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -4881,6 +5649,13 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -5237,6 +6012,12 @@ "nanoassert": "^1.0.0" } }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -5551,6 +6332,15 @@ "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", "dev": true }, + "catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -5809,6 +6599,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -5959,6 +6755,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, "es6-object-assign": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", @@ -5977,6 +6779,40 @@ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, "esmify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/esmify/-/esmify-2.1.1.tgz", @@ -5995,12 +6831,37 @@ "through2": "^2.0.5" } }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "dependencies": { + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6023,6 +6884,12 @@ "safe-buffer": "^5.1.1" } }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -6172,6 +7039,12 @@ "get-intrinsic": "^1.1.3" } }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -6491,6 +7364,52 @@ "argparse": "^2.0.1" } }, + "js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.4" + } + }, + "jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -6558,6 +7477,15 @@ } } }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, "labeled-stream-splicer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", @@ -6568,6 +7496,25 @@ "stream-splicer": "^2.0.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6650,6 +7597,12 @@ } } }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "peer": true + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6674,6 +7627,32 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "requires": {} + }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -6685,6 +7664,12 @@ "safe-buffer": "^5.1.2" } }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -6965,6 +7950,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -7078,6 +8077,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -7090,6 +8095,150 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "peer": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, + "protobufjs-cli": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.2.tgz", + "integrity": "sha512-8ivXWxT39gZN4mm4ArQyJrRgnIwZqffBWoLDsE21TmMcKI3XwJMV4lEF2WU02C4JAtgYYc2SfJIltelD8to35g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -7217,6 +8366,15 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, + "requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -7491,6 +8649,12 @@ "process": "~0.11.0" } }, + "tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7609,6 +8773,15 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -7627,6 +8800,18 @@ "integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true + }, "umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", @@ -7646,6 +8831,12 @@ "xtend": "^4.0.1" } }, + "underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, "update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -7727,6 +8918,12 @@ "is-typed-array": "^1.1.10" } }, + "word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true + }, "workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", @@ -7776,6 +8973,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 174824459..6cfcfbda0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "12.20.0-beta.1", + "version": "12.20.0-beta.2", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -16,7 +16,7 @@ "tests-testnet": "mocha $(find . -name '*.test.net.spec.ts')", "compile-browser": "tsc -p tsconfig.json && browserify out/index.js -o out-browser/sdk-core.js --standalone multiversxSdkCore -p esmify", "compile": "tsc -p tsconfig.json", - "compile-proto": "npx pbjs -t static-module -w commonjs -o src/proto/compiled.js src/proto/transaction.proto && npx pbts -o src/proto/compiled.d.ts src/proto/compiled.js", + "compile-proto": "npx pbjs -t static-module -w default -o src/proto/compiled.js src/proto/transaction.proto", "browser-tests": "make clean && make browser-tests && http-server --port=9876 -o browser-tests/index.html", "lint": "tslint --project .", "pretest": "npm run compile", @@ -46,11 +46,13 @@ "chai": "4.2.0", "esmify": "2.1.1", "mocha": "9.2.2", + "protobufjs-cli": "1.1.2", "ts-node": "9.1.1", "tslint": "6.1.3", "typescript": "4.1.2" }, "peerDependencies": { - "bignumber.js": "^9.0.1" + "bignumber.js": "^9.0.1", + "protobufjs": "^7.2.6" } } diff --git a/src/proto/compiled.d.ts b/src/proto/compiled.d.ts deleted file mode 100644 index ed08acfeb..000000000 --- a/src/proto/compiled.d.ts +++ /dev/null @@ -1,178 +0,0 @@ -import * as $protobuf from "protobufjs"; -/** Namespace proto. */ -export namespace proto { - - /** Properties of a Transaction. */ - interface ITransaction { - - /** Transaction Nonce */ - Nonce?: (number|Long|null); - - /** Transaction Value */ - Value?: (Uint8Array|null); - - /** Transaction RcvAddr */ - RcvAddr?: (Uint8Array|null); - - /** Transaction RcvUserName */ - RcvUserName?: (Uint8Array|null); - - /** Transaction SndAddr */ - SndAddr?: (Uint8Array|null); - - /** Transaction SndUserName */ - SndUserName?: (Uint8Array|null); - - /** Transaction GasPrice */ - GasPrice?: (number|Long|null); - - /** Transaction GasLimit */ - GasLimit?: (number|Long|null); - - /** Transaction Data */ - Data?: (Uint8Array|null); - - /** Transaction ChainID */ - ChainID?: (Uint8Array|null); - - /** Transaction Version */ - Version?: (number|null); - - /** Transaction Signature */ - Signature?: (Uint8Array|null); - - /** Transaction Options */ - Options?: (number|null); - - /** Transaction GuardAddr */ - GuardAddr?: (Uint8Array|null); - - /** Transaction GuardSignature */ - GuardSignature?: (Uint8Array|null); - } - - /** Represents a Transaction. */ - class Transaction implements ITransaction { - - /** - * Constructs a new Transaction. - * @param [properties] Properties to set - */ - constructor(properties?: proto.ITransaction); - - /** Transaction Nonce. */ - public Nonce: (number|Long); - - /** Transaction Value. */ - public Value: Uint8Array; - - /** Transaction RcvAddr. */ - public RcvAddr: Uint8Array; - - /** Transaction RcvUserName. */ - public RcvUserName: Uint8Array; - - /** Transaction SndAddr. */ - public SndAddr: Uint8Array; - - /** Transaction SndUserName. */ - public SndUserName: Uint8Array; - - /** Transaction GasPrice. */ - public GasPrice: (number|Long); - - /** Transaction GasLimit. */ - public GasLimit: (number|Long); - - /** Transaction Data. */ - public Data: Uint8Array; - - /** Transaction ChainID. */ - public ChainID: Uint8Array; - - /** Transaction Version. */ - public Version: number; - - /** Transaction Signature. */ - public Signature: Uint8Array; - - /** Transaction Options. */ - public Options: number; - - /** Transaction GuardAddr. */ - public GuardAddr: Uint8Array; - - /** Transaction GuardSignature. */ - public GuardSignature: Uint8Array; - - /** - * Creates a new Transaction instance using the specified properties. - * @param [properties] Properties to set - * @returns Transaction instance - */ - public static create(properties?: proto.ITransaction): proto.Transaction; - - /** - * Encodes the specified Transaction message. Does not implicitly {@link proto.Transaction.verify|verify} messages. - * @param message Transaction message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: proto.ITransaction, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified Transaction message, length delimited. Does not implicitly {@link proto.Transaction.verify|verify} messages. - * @param message Transaction message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: proto.ITransaction, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a Transaction message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns Transaction - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): proto.Transaction; - - /** - * Decodes a Transaction message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns Transaction - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): proto.Transaction; - - /** - * Verifies a Transaction message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a Transaction message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns Transaction - */ - public static fromObject(object: { [k: string]: any }): proto.Transaction; - - /** - * Creates a plain object from a Transaction message. Also converts values to other types if specified. - * @param message Transaction - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: proto.Transaction, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this Transaction to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - } -} diff --git a/src/proto/compiled.js b/src/proto/compiled.js index 7efef837c..feed796f9 100644 --- a/src/proto/compiled.js +++ b/src/proto/compiled.js @@ -1,652 +1,690 @@ /*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ -"use strict"; +(function(global, factory) { /* global define, require, module */ -var $protobuf = require("protobufjs/minimal"); + /* AMD */ if (typeof define === 'function' && define.amd) + define(["protobufjs/minimal"], factory); -// Common aliases -var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + /* CommonJS */ else if (typeof require === 'function' && typeof module === 'object' && module && module.exports) + module.exports = factory(require("protobufjs/minimal")); -// Exported root namespace -var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); - -$root.proto = (function() { - - /** - * Namespace proto. - * @exports proto - * @namespace - */ - var proto = {}; - - proto.Transaction = (function() { - - /** - * Properties of a Transaction. - * @memberof proto - * @interface ITransaction - * @property {number|Long|null} [Nonce] Transaction Nonce - * @property {Uint8Array|null} [Value] Transaction Value - * @property {Uint8Array|null} [RcvAddr] Transaction RcvAddr - * @property {Uint8Array|null} [RcvUserName] Transaction RcvUserName - * @property {Uint8Array|null} [SndAddr] Transaction SndAddr - * @property {Uint8Array|null} [SndUserName] Transaction SndUserName - * @property {number|Long|null} [GasPrice] Transaction GasPrice - * @property {number|Long|null} [GasLimit] Transaction GasLimit - * @property {Uint8Array|null} [Data] Transaction Data - * @property {Uint8Array|null} [ChainID] Transaction ChainID - * @property {number|null} [Version] Transaction Version - * @property {Uint8Array|null} [Signature] Transaction Signature - * @property {number|null} [Options] Transaction Options - * @property {Uint8Array|null} [GuardAddr] Transaction GuardAddr - * @property {Uint8Array|null} [GuardSignature] Transaction GuardSignature - */ - - /** - * Constructs a new Transaction. - * @memberof proto - * @classdesc Represents a Transaction. - * @implements ITransaction - * @constructor - * @param {proto.ITransaction=} [properties] Properties to set - */ - function Transaction(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Transaction Nonce. - * @member {number|Long} Nonce - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.Nonce = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - - /** - * Transaction Value. - * @member {Uint8Array} Value - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.Value = $util.newBuffer([]); - - /** - * Transaction RcvAddr. - * @member {Uint8Array} RcvAddr - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.RcvAddr = $util.newBuffer([]); - - /** - * Transaction RcvUserName. - * @member {Uint8Array} RcvUserName - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.RcvUserName = $util.newBuffer([]); - - /** - * Transaction SndAddr. - * @member {Uint8Array} SndAddr - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.SndAddr = $util.newBuffer([]); - - /** - * Transaction SndUserName. - * @member {Uint8Array} SndUserName - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.SndUserName = $util.newBuffer([]); - - /** - * Transaction GasPrice. - * @member {number|Long} GasPrice - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.GasPrice = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - - /** - * Transaction GasLimit. - * @member {number|Long} GasLimit - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.GasLimit = $util.Long ? $util.Long.fromBits(0,0,true) : 0; +})(this, function($protobuf) { + "use strict"; + // Common aliases + var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + + // Exported root namespace + var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + + $root.proto = (function() { + /** - * Transaction Data. - * @member {Uint8Array} Data - * @memberof proto.Transaction - * @instance + * Namespace proto. + * @exports proto + * @namespace */ - Transaction.prototype.Data = $util.newBuffer([]); - - /** - * Transaction ChainID. - * @member {Uint8Array} ChainID - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.ChainID = $util.newBuffer([]); - - /** - * Transaction Version. - * @member {number} Version - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.Version = 0; - - /** - * Transaction Signature. - * @member {Uint8Array} Signature - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.Signature = $util.newBuffer([]); - - /** - * Transaction Options. - * @member {number} Options - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.Options = 0; - - /** - * Transaction GuardAddr. - * @member {Uint8Array} GuardAddr - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.GuardAddr = $util.newBuffer([]); - - /** - * Transaction GuardSignature. - * @member {Uint8Array} GuardSignature - * @memberof proto.Transaction - * @instance - */ - Transaction.prototype.GuardSignature = $util.newBuffer([]); - - /** - * Creates a new Transaction instance using the specified properties. - * @function create - * @memberof proto.Transaction - * @static - * @param {proto.ITransaction=} [properties] Properties to set - * @returns {proto.Transaction} Transaction instance - */ - Transaction.create = function create(properties) { - return new Transaction(properties); - }; - - /** - * Encodes the specified Transaction message. Does not implicitly {@link proto.Transaction.verify|verify} messages. - * @function encode - * @memberof proto.Transaction - * @static - * @param {proto.ITransaction} message Transaction message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Transaction.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.Nonce != null && Object.hasOwnProperty.call(message, "Nonce")) - writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.Nonce); - if (message.Value != null && Object.hasOwnProperty.call(message, "Value")) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.Value); - if (message.RcvAddr != null && Object.hasOwnProperty.call(message, "RcvAddr")) - writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.RcvAddr); - if (message.RcvUserName != null && Object.hasOwnProperty.call(message, "RcvUserName")) - writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.RcvUserName); - if (message.SndAddr != null && Object.hasOwnProperty.call(message, "SndAddr")) - writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.SndAddr); - if (message.SndUserName != null && Object.hasOwnProperty.call(message, "SndUserName")) - writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.SndUserName); - if (message.GasPrice != null && Object.hasOwnProperty.call(message, "GasPrice")) - writer.uint32(/* id 7, wireType 0 =*/56).uint64(message.GasPrice); - if (message.GasLimit != null && Object.hasOwnProperty.call(message, "GasLimit")) - writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.GasLimit); - if (message.Data != null && Object.hasOwnProperty.call(message, "Data")) - writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.Data); - if (message.ChainID != null && Object.hasOwnProperty.call(message, "ChainID")) - writer.uint32(/* id 10, wireType 2 =*/82).bytes(message.ChainID); - if (message.Version != null && Object.hasOwnProperty.call(message, "Version")) - writer.uint32(/* id 11, wireType 0 =*/88).uint32(message.Version); - if (message.Signature != null && Object.hasOwnProperty.call(message, "Signature")) - writer.uint32(/* id 12, wireType 2 =*/98).bytes(message.Signature); - if (message.Options != null && Object.hasOwnProperty.call(message, "Options")) - writer.uint32(/* id 13, wireType 0 =*/104).uint32(message.Options); - if (message.GuardAddr != null && Object.hasOwnProperty.call(message, "GuardAddr")) - writer.uint32(/* id 14, wireType 2 =*/114).bytes(message.GuardAddr); - if (message.GuardSignature != null && Object.hasOwnProperty.call(message, "GuardSignature")) - writer.uint32(/* id 15, wireType 2 =*/122).bytes(message.GuardSignature); - return writer; - }; - - /** - * Encodes the specified Transaction message, length delimited. Does not implicitly {@link proto.Transaction.verify|verify} messages. - * @function encodeDelimited - * @memberof proto.Transaction - * @static - * @param {proto.ITransaction} message Transaction message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Transaction.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Transaction message from the specified reader or buffer. - * @function decode - * @memberof proto.Transaction - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {proto.Transaction} Transaction - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Transaction.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.proto.Transaction(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.Nonce = reader.uint64(); - break; - case 2: - message.Value = reader.bytes(); - break; - case 3: - message.RcvAddr = reader.bytes(); - break; - case 4: - message.RcvUserName = reader.bytes(); - break; - case 5: - message.SndAddr = reader.bytes(); - break; - case 6: - message.SndUserName = reader.bytes(); - break; - case 7: - message.GasPrice = reader.uint64(); - break; - case 8: - message.GasLimit = reader.uint64(); - break; - case 9: - message.Data = reader.bytes(); - break; - case 10: - message.ChainID = reader.bytes(); - break; - case 11: - message.Version = reader.uint32(); - break; - case 12: - message.Signature = reader.bytes(); - break; - case 13: - message.Options = reader.uint32(); - break; - case 14: - message.GuardAddr = reader.bytes(); - break; - case 15: - message.GuardSignature = reader.bytes(); - break; - default: - reader.skipType(tag & 7); - break; - } + var proto = {}; + + proto.Transaction = (function() { + + /** + * Properties of a Transaction. + * @memberof proto + * @interface ITransaction + * @property {number|Long|null} [Nonce] Transaction Nonce + * @property {Uint8Array|null} [Value] Transaction Value + * @property {Uint8Array|null} [RcvAddr] Transaction RcvAddr + * @property {Uint8Array|null} [RcvUserName] Transaction RcvUserName + * @property {Uint8Array|null} [SndAddr] Transaction SndAddr + * @property {Uint8Array|null} [SndUserName] Transaction SndUserName + * @property {number|Long|null} [GasPrice] Transaction GasPrice + * @property {number|Long|null} [GasLimit] Transaction GasLimit + * @property {Uint8Array|null} [Data] Transaction Data + * @property {Uint8Array|null} [ChainID] Transaction ChainID + * @property {number|null} [Version] Transaction Version + * @property {Uint8Array|null} [Signature] Transaction Signature + * @property {number|null} [Options] Transaction Options + * @property {Uint8Array|null} [GuardianAddr] Transaction GuardianAddr + * @property {Uint8Array|null} [GuardianSignature] Transaction GuardianSignature + */ + + /** + * Constructs a new Transaction. + * @memberof proto + * @classdesc Represents a Transaction. + * @implements ITransaction + * @constructor + * @param {proto.ITransaction=} [properties] Properties to set + */ + function Transaction(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; } - return message; - }; - - /** - * Decodes a Transaction message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof proto.Transaction - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {proto.Transaction} Transaction - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Transaction.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Transaction message. - * @function verify - * @memberof proto.Transaction - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Transaction.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.Nonce != null && message.hasOwnProperty("Nonce")) - if (!$util.isInteger(message.Nonce) && !(message.Nonce && $util.isInteger(message.Nonce.low) && $util.isInteger(message.Nonce.high))) - return "Nonce: integer|Long expected"; - if (message.Value != null && message.hasOwnProperty("Value")) - if (!(message.Value && typeof message.Value.length === "number" || $util.isString(message.Value))) - return "Value: buffer expected"; - if (message.RcvAddr != null && message.hasOwnProperty("RcvAddr")) - if (!(message.RcvAddr && typeof message.RcvAddr.length === "number" || $util.isString(message.RcvAddr))) - return "RcvAddr: buffer expected"; - if (message.RcvUserName != null && message.hasOwnProperty("RcvUserName")) - if (!(message.RcvUserName && typeof message.RcvUserName.length === "number" || $util.isString(message.RcvUserName))) - return "RcvUserName: buffer expected"; - if (message.SndAddr != null && message.hasOwnProperty("SndAddr")) - if (!(message.SndAddr && typeof message.SndAddr.length === "number" || $util.isString(message.SndAddr))) - return "SndAddr: buffer expected"; - if (message.SndUserName != null && message.hasOwnProperty("SndUserName")) - if (!(message.SndUserName && typeof message.SndUserName.length === "number" || $util.isString(message.SndUserName))) - return "SndUserName: buffer expected"; - if (message.GasPrice != null && message.hasOwnProperty("GasPrice")) - if (!$util.isInteger(message.GasPrice) && !(message.GasPrice && $util.isInteger(message.GasPrice.low) && $util.isInteger(message.GasPrice.high))) - return "GasPrice: integer|Long expected"; - if (message.GasLimit != null && message.hasOwnProperty("GasLimit")) - if (!$util.isInteger(message.GasLimit) && !(message.GasLimit && $util.isInteger(message.GasLimit.low) && $util.isInteger(message.GasLimit.high))) - return "GasLimit: integer|Long expected"; - if (message.Data != null && message.hasOwnProperty("Data")) - if (!(message.Data && typeof message.Data.length === "number" || $util.isString(message.Data))) - return "Data: buffer expected"; - if (message.ChainID != null && message.hasOwnProperty("ChainID")) - if (!(message.ChainID && typeof message.ChainID.length === "number" || $util.isString(message.ChainID))) - return "ChainID: buffer expected"; - if (message.Version != null && message.hasOwnProperty("Version")) - if (!$util.isInteger(message.Version)) - return "Version: integer expected"; - if (message.Signature != null && message.hasOwnProperty("Signature")) - if (!(message.Signature && typeof message.Signature.length === "number" || $util.isString(message.Signature))) - return "Signature: buffer expected"; - if (message.Options != null && message.hasOwnProperty("Options")) - if (!$util.isInteger(message.Options)) - return "Options: integer expected"; - if (message.GuardAddr != null && message.hasOwnProperty("GuardAddr")) - if (!(message.GuardAddr && typeof message.GuardAddr.length === "number" || $util.isString(message.GuardAddr))) - return "GuardAddr: buffer expected"; - if (message.GuardSignature != null && message.hasOwnProperty("GuardSignature")) - if (!(message.GuardSignature && typeof message.GuardSignature.length === "number" || $util.isString(message.GuardSignature))) - return "GuardSignature: buffer expected"; - return null; - }; - - /** - * Creates a Transaction message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof proto.Transaction - * @static - * @param {Object.} object Plain object - * @returns {proto.Transaction} Transaction - */ - Transaction.fromObject = function fromObject(object) { - if (object instanceof $root.proto.Transaction) - return object; - var message = new $root.proto.Transaction(); - if (object.Nonce != null) - if ($util.Long) - (message.Nonce = $util.Long.fromValue(object.Nonce)).unsigned = true; - else if (typeof object.Nonce === "string") - message.Nonce = parseInt(object.Nonce, 10); - else if (typeof object.Nonce === "number") - message.Nonce = object.Nonce; - else if (typeof object.Nonce === "object") - message.Nonce = new $util.LongBits(object.Nonce.low >>> 0, object.Nonce.high >>> 0).toNumber(true); - if (object.Value != null) - if (typeof object.Value === "string") - $util.base64.decode(object.Value, message.Value = $util.newBuffer($util.base64.length(object.Value)), 0); - else if (object.Value.length) - message.Value = object.Value; - if (object.RcvAddr != null) - if (typeof object.RcvAddr === "string") - $util.base64.decode(object.RcvAddr, message.RcvAddr = $util.newBuffer($util.base64.length(object.RcvAddr)), 0); - else if (object.RcvAddr.length) - message.RcvAddr = object.RcvAddr; - if (object.RcvUserName != null) - if (typeof object.RcvUserName === "string") - $util.base64.decode(object.RcvUserName, message.RcvUserName = $util.newBuffer($util.base64.length(object.RcvUserName)), 0); - else if (object.RcvUserName.length) - message.RcvUserName = object.RcvUserName; - if (object.SndAddr != null) - if (typeof object.SndAddr === "string") - $util.base64.decode(object.SndAddr, message.SndAddr = $util.newBuffer($util.base64.length(object.SndAddr)), 0); - else if (object.SndAddr.length) - message.SndAddr = object.SndAddr; - if (object.SndUserName != null) - if (typeof object.SndUserName === "string") - $util.base64.decode(object.SndUserName, message.SndUserName = $util.newBuffer($util.base64.length(object.SndUserName)), 0); - else if (object.SndUserName.length) - message.SndUserName = object.SndUserName; - if (object.GasPrice != null) - if ($util.Long) - (message.GasPrice = $util.Long.fromValue(object.GasPrice)).unsigned = true; - else if (typeof object.GasPrice === "string") - message.GasPrice = parseInt(object.GasPrice, 10); - else if (typeof object.GasPrice === "number") - message.GasPrice = object.GasPrice; - else if (typeof object.GasPrice === "object") - message.GasPrice = new $util.LongBits(object.GasPrice.low >>> 0, object.GasPrice.high >>> 0).toNumber(true); - if (object.GasLimit != null) - if ($util.Long) - (message.GasLimit = $util.Long.fromValue(object.GasLimit)).unsigned = true; - else if (typeof object.GasLimit === "string") - message.GasLimit = parseInt(object.GasLimit, 10); - else if (typeof object.GasLimit === "number") - message.GasLimit = object.GasLimit; - else if (typeof object.GasLimit === "object") - message.GasLimit = new $util.LongBits(object.GasLimit.low >>> 0, object.GasLimit.high >>> 0).toNumber(true); - if (object.Data != null) - if (typeof object.Data === "string") - $util.base64.decode(object.Data, message.Data = $util.newBuffer($util.base64.length(object.Data)), 0); - else if (object.Data.length) - message.Data = object.Data; - if (object.ChainID != null) - if (typeof object.ChainID === "string") - $util.base64.decode(object.ChainID, message.ChainID = $util.newBuffer($util.base64.length(object.ChainID)), 0); - else if (object.ChainID.length) - message.ChainID = object.ChainID; - if (object.Version != null) - message.Version = object.Version >>> 0; - if (object.Signature != null) - if (typeof object.Signature === "string") - $util.base64.decode(object.Signature, message.Signature = $util.newBuffer($util.base64.length(object.Signature)), 0); - else if (object.Signature.length) - message.Signature = object.Signature; - if (object.Options != null) - message.Options = object.Options >>> 0; - if (object.GuardAddr != null) - if (typeof object.GuardAddr === "string") - $util.base64.decode(object.GuardAddr, message.GuardAddr = $util.newBuffer($util.base64.length(object.GuardAddr)), 0); - else if (object.GuardAddr.length) - message.GuardAddr = object.GuardAddr; - if (object.GuardSignature != null) - if (typeof object.GuardSignature === "string") - $util.base64.decode(object.GuardSignature, message.GuardSignature = $util.newBuffer($util.base64.length(object.GuardSignature)), 0); - else if (object.GuardSignature.length) - message.GuardSignature = object.GuardSignature; - return message; - }; - - /** - * Creates a plain object from a Transaction message. Also converts values to other types if specified. - * @function toObject - * @memberof proto.Transaction - * @static - * @param {proto.Transaction} message Transaction - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Transaction.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.Nonce = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.Nonce = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.Value = ""; - else { - object.Value = []; - if (options.bytes !== Array) - object.Value = $util.newBuffer(object.Value); - } - if (options.bytes === String) - object.RcvAddr = ""; - else { - object.RcvAddr = []; - if (options.bytes !== Array) - object.RcvAddr = $util.newBuffer(object.RcvAddr); - } - if (options.bytes === String) - object.RcvUserName = ""; - else { - object.RcvUserName = []; - if (options.bytes !== Array) - object.RcvUserName = $util.newBuffer(object.RcvUserName); - } - if (options.bytes === String) - object.SndAddr = ""; - else { - object.SndAddr = []; - if (options.bytes !== Array) - object.SndAddr = $util.newBuffer(object.SndAddr); + + /** + * Transaction Nonce. + * @member {number|Long} Nonce + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Nonce = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Transaction Value. + * @member {Uint8Array} Value + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Value = $util.newBuffer([]); + + /** + * Transaction RcvAddr. + * @member {Uint8Array} RcvAddr + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.RcvAddr = $util.newBuffer([]); + + /** + * Transaction RcvUserName. + * @member {Uint8Array} RcvUserName + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.RcvUserName = $util.newBuffer([]); + + /** + * Transaction SndAddr. + * @member {Uint8Array} SndAddr + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.SndAddr = $util.newBuffer([]); + + /** + * Transaction SndUserName. + * @member {Uint8Array} SndUserName + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.SndUserName = $util.newBuffer([]); + + /** + * Transaction GasPrice. + * @member {number|Long} GasPrice + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.GasPrice = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Transaction GasLimit. + * @member {number|Long} GasLimit + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.GasLimit = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Transaction Data. + * @member {Uint8Array} Data + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Data = $util.newBuffer([]); + + /** + * Transaction ChainID. + * @member {Uint8Array} ChainID + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.ChainID = $util.newBuffer([]); + + /** + * Transaction Version. + * @member {number} Version + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Version = 0; + + /** + * Transaction Signature. + * @member {Uint8Array} Signature + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Signature = $util.newBuffer([]); + + /** + * Transaction Options. + * @member {number} Options + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.Options = 0; + + /** + * Transaction GuardianAddr. + * @member {Uint8Array} GuardianAddr + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.GuardianAddr = $util.newBuffer([]); + + /** + * Transaction GuardianSignature. + * @member {Uint8Array} GuardianSignature + * @memberof proto.Transaction + * @instance + */ + Transaction.prototype.GuardianSignature = $util.newBuffer([]); + + /** + * Creates a new Transaction instance using the specified properties. + * @function create + * @memberof proto.Transaction + * @static + * @param {proto.ITransaction=} [properties] Properties to set + * @returns {proto.Transaction} Transaction instance + */ + Transaction.create = function create(properties) { + return new Transaction(properties); + }; + + /** + * Encodes the specified Transaction message. Does not implicitly {@link proto.Transaction.verify|verify} messages. + * @function encode + * @memberof proto.Transaction + * @static + * @param {proto.ITransaction} message Transaction message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Transaction.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.Nonce != null && Object.hasOwnProperty.call(message, "Nonce")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.Nonce); + if (message.Value != null && Object.hasOwnProperty.call(message, "Value")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.Value); + if (message.RcvAddr != null && Object.hasOwnProperty.call(message, "RcvAddr")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.RcvAddr); + if (message.RcvUserName != null && Object.hasOwnProperty.call(message, "RcvUserName")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.RcvUserName); + if (message.SndAddr != null && Object.hasOwnProperty.call(message, "SndAddr")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.SndAddr); + if (message.SndUserName != null && Object.hasOwnProperty.call(message, "SndUserName")) + writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.SndUserName); + if (message.GasPrice != null && Object.hasOwnProperty.call(message, "GasPrice")) + writer.uint32(/* id 7, wireType 0 =*/56).uint64(message.GasPrice); + if (message.GasLimit != null && Object.hasOwnProperty.call(message, "GasLimit")) + writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.GasLimit); + if (message.Data != null && Object.hasOwnProperty.call(message, "Data")) + writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.Data); + if (message.ChainID != null && Object.hasOwnProperty.call(message, "ChainID")) + writer.uint32(/* id 10, wireType 2 =*/82).bytes(message.ChainID); + if (message.Version != null && Object.hasOwnProperty.call(message, "Version")) + writer.uint32(/* id 11, wireType 0 =*/88).uint32(message.Version); + if (message.Signature != null && Object.hasOwnProperty.call(message, "Signature")) + writer.uint32(/* id 12, wireType 2 =*/98).bytes(message.Signature); + if (message.Options != null && Object.hasOwnProperty.call(message, "Options")) + writer.uint32(/* id 13, wireType 0 =*/104).uint32(message.Options); + if (message.GuardianAddr != null && Object.hasOwnProperty.call(message, "GuardianAddr")) + writer.uint32(/* id 14, wireType 2 =*/114).bytes(message.GuardianAddr); + if (message.GuardianSignature != null && Object.hasOwnProperty.call(message, "GuardianSignature")) + writer.uint32(/* id 15, wireType 2 =*/122).bytes(message.GuardianSignature); + return writer; + }; + + /** + * Encodes the specified Transaction message, length delimited. Does not implicitly {@link proto.Transaction.verify|verify} messages. + * @function encodeDelimited + * @memberof proto.Transaction + * @static + * @param {proto.ITransaction} message Transaction message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Transaction.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Transaction message from the specified reader or buffer. + * @function decode + * @memberof proto.Transaction + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {proto.Transaction} Transaction + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Transaction.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.proto.Transaction(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.Nonce = reader.uint64(); + break; + } + case 2: { + message.Value = reader.bytes(); + break; + } + case 3: { + message.RcvAddr = reader.bytes(); + break; + } + case 4: { + message.RcvUserName = reader.bytes(); + break; + } + case 5: { + message.SndAddr = reader.bytes(); + break; + } + case 6: { + message.SndUserName = reader.bytes(); + break; + } + case 7: { + message.GasPrice = reader.uint64(); + break; + } + case 8: { + message.GasLimit = reader.uint64(); + break; + } + case 9: { + message.Data = reader.bytes(); + break; + } + case 10: { + message.ChainID = reader.bytes(); + break; + } + case 11: { + message.Version = reader.uint32(); + break; + } + case 12: { + message.Signature = reader.bytes(); + break; + } + case 13: { + message.Options = reader.uint32(); + break; + } + case 14: { + message.GuardianAddr = reader.bytes(); + break; + } + case 15: { + message.GuardianSignature = reader.bytes(); + break; + } + default: + reader.skipType(tag & 7); + break; + } } - if (options.bytes === String) - object.SndUserName = ""; - else { - object.SndUserName = []; - if (options.bytes !== Array) - object.SndUserName = $util.newBuffer(object.SndUserName); + return message; + }; + + /** + * Decodes a Transaction message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof proto.Transaction + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {proto.Transaction} Transaction + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Transaction.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Transaction message. + * @function verify + * @memberof proto.Transaction + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Transaction.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.Nonce != null && message.hasOwnProperty("Nonce")) + if (!$util.isInteger(message.Nonce) && !(message.Nonce && $util.isInteger(message.Nonce.low) && $util.isInteger(message.Nonce.high))) + return "Nonce: integer|Long expected"; + if (message.Value != null && message.hasOwnProperty("Value")) + if (!(message.Value && typeof message.Value.length === "number" || $util.isString(message.Value))) + return "Value: buffer expected"; + if (message.RcvAddr != null && message.hasOwnProperty("RcvAddr")) + if (!(message.RcvAddr && typeof message.RcvAddr.length === "number" || $util.isString(message.RcvAddr))) + return "RcvAddr: buffer expected"; + if (message.RcvUserName != null && message.hasOwnProperty("RcvUserName")) + if (!(message.RcvUserName && typeof message.RcvUserName.length === "number" || $util.isString(message.RcvUserName))) + return "RcvUserName: buffer expected"; + if (message.SndAddr != null && message.hasOwnProperty("SndAddr")) + if (!(message.SndAddr && typeof message.SndAddr.length === "number" || $util.isString(message.SndAddr))) + return "SndAddr: buffer expected"; + if (message.SndUserName != null && message.hasOwnProperty("SndUserName")) + if (!(message.SndUserName && typeof message.SndUserName.length === "number" || $util.isString(message.SndUserName))) + return "SndUserName: buffer expected"; + if (message.GasPrice != null && message.hasOwnProperty("GasPrice")) + if (!$util.isInteger(message.GasPrice) && !(message.GasPrice && $util.isInteger(message.GasPrice.low) && $util.isInteger(message.GasPrice.high))) + return "GasPrice: integer|Long expected"; + if (message.GasLimit != null && message.hasOwnProperty("GasLimit")) + if (!$util.isInteger(message.GasLimit) && !(message.GasLimit && $util.isInteger(message.GasLimit.low) && $util.isInteger(message.GasLimit.high))) + return "GasLimit: integer|Long expected"; + if (message.Data != null && message.hasOwnProperty("Data")) + if (!(message.Data && typeof message.Data.length === "number" || $util.isString(message.Data))) + return "Data: buffer expected"; + if (message.ChainID != null && message.hasOwnProperty("ChainID")) + if (!(message.ChainID && typeof message.ChainID.length === "number" || $util.isString(message.ChainID))) + return "ChainID: buffer expected"; + if (message.Version != null && message.hasOwnProperty("Version")) + if (!$util.isInteger(message.Version)) + return "Version: integer expected"; + if (message.Signature != null && message.hasOwnProperty("Signature")) + if (!(message.Signature && typeof message.Signature.length === "number" || $util.isString(message.Signature))) + return "Signature: buffer expected"; + if (message.Options != null && message.hasOwnProperty("Options")) + if (!$util.isInteger(message.Options)) + return "Options: integer expected"; + if (message.GuardianAddr != null && message.hasOwnProperty("GuardianAddr")) + if (!(message.GuardianAddr && typeof message.GuardianAddr.length === "number" || $util.isString(message.GuardianAddr))) + return "GuardianAddr: buffer expected"; + if (message.GuardianSignature != null && message.hasOwnProperty("GuardianSignature")) + if (!(message.GuardianSignature && typeof message.GuardianSignature.length === "number" || $util.isString(message.GuardianSignature))) + return "GuardianSignature: buffer expected"; + return null; + }; + + /** + * Creates a Transaction message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof proto.Transaction + * @static + * @param {Object.} object Plain object + * @returns {proto.Transaction} Transaction + */ + Transaction.fromObject = function fromObject(object) { + if (object instanceof $root.proto.Transaction) + return object; + var message = new $root.proto.Transaction(); + if (object.Nonce != null) + if ($util.Long) + (message.Nonce = $util.Long.fromValue(object.Nonce)).unsigned = true; + else if (typeof object.Nonce === "string") + message.Nonce = parseInt(object.Nonce, 10); + else if (typeof object.Nonce === "number") + message.Nonce = object.Nonce; + else if (typeof object.Nonce === "object") + message.Nonce = new $util.LongBits(object.Nonce.low >>> 0, object.Nonce.high >>> 0).toNumber(true); + if (object.Value != null) + if (typeof object.Value === "string") + $util.base64.decode(object.Value, message.Value = $util.newBuffer($util.base64.length(object.Value)), 0); + else if (object.Value.length >= 0) + message.Value = object.Value; + if (object.RcvAddr != null) + if (typeof object.RcvAddr === "string") + $util.base64.decode(object.RcvAddr, message.RcvAddr = $util.newBuffer($util.base64.length(object.RcvAddr)), 0); + else if (object.RcvAddr.length >= 0) + message.RcvAddr = object.RcvAddr; + if (object.RcvUserName != null) + if (typeof object.RcvUserName === "string") + $util.base64.decode(object.RcvUserName, message.RcvUserName = $util.newBuffer($util.base64.length(object.RcvUserName)), 0); + else if (object.RcvUserName.length >= 0) + message.RcvUserName = object.RcvUserName; + if (object.SndAddr != null) + if (typeof object.SndAddr === "string") + $util.base64.decode(object.SndAddr, message.SndAddr = $util.newBuffer($util.base64.length(object.SndAddr)), 0); + else if (object.SndAddr.length >= 0) + message.SndAddr = object.SndAddr; + if (object.SndUserName != null) + if (typeof object.SndUserName === "string") + $util.base64.decode(object.SndUserName, message.SndUserName = $util.newBuffer($util.base64.length(object.SndUserName)), 0); + else if (object.SndUserName.length >= 0) + message.SndUserName = object.SndUserName; + if (object.GasPrice != null) + if ($util.Long) + (message.GasPrice = $util.Long.fromValue(object.GasPrice)).unsigned = true; + else if (typeof object.GasPrice === "string") + message.GasPrice = parseInt(object.GasPrice, 10); + else if (typeof object.GasPrice === "number") + message.GasPrice = object.GasPrice; + else if (typeof object.GasPrice === "object") + message.GasPrice = new $util.LongBits(object.GasPrice.low >>> 0, object.GasPrice.high >>> 0).toNumber(true); + if (object.GasLimit != null) + if ($util.Long) + (message.GasLimit = $util.Long.fromValue(object.GasLimit)).unsigned = true; + else if (typeof object.GasLimit === "string") + message.GasLimit = parseInt(object.GasLimit, 10); + else if (typeof object.GasLimit === "number") + message.GasLimit = object.GasLimit; + else if (typeof object.GasLimit === "object") + message.GasLimit = new $util.LongBits(object.GasLimit.low >>> 0, object.GasLimit.high >>> 0).toNumber(true); + if (object.Data != null) + if (typeof object.Data === "string") + $util.base64.decode(object.Data, message.Data = $util.newBuffer($util.base64.length(object.Data)), 0); + else if (object.Data.length >= 0) + message.Data = object.Data; + if (object.ChainID != null) + if (typeof object.ChainID === "string") + $util.base64.decode(object.ChainID, message.ChainID = $util.newBuffer($util.base64.length(object.ChainID)), 0); + else if (object.ChainID.length >= 0) + message.ChainID = object.ChainID; + if (object.Version != null) + message.Version = object.Version >>> 0; + if (object.Signature != null) + if (typeof object.Signature === "string") + $util.base64.decode(object.Signature, message.Signature = $util.newBuffer($util.base64.length(object.Signature)), 0); + else if (object.Signature.length >= 0) + message.Signature = object.Signature; + if (object.Options != null) + message.Options = object.Options >>> 0; + if (object.GuardianAddr != null) + if (typeof object.GuardianAddr === "string") + $util.base64.decode(object.GuardianAddr, message.GuardianAddr = $util.newBuffer($util.base64.length(object.GuardianAddr)), 0); + else if (object.GuardianAddr.length >= 0) + message.GuardianAddr = object.GuardianAddr; + if (object.GuardianSignature != null) + if (typeof object.GuardianSignature === "string") + $util.base64.decode(object.GuardianSignature, message.GuardianSignature = $util.newBuffer($util.base64.length(object.GuardianSignature)), 0); + else if (object.GuardianSignature.length >= 0) + message.GuardianSignature = object.GuardianSignature; + return message; + }; + + /** + * Creates a plain object from a Transaction message. Also converts values to other types if specified. + * @function toObject + * @memberof proto.Transaction + * @static + * @param {proto.Transaction} message Transaction + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Transaction.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.Nonce = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.Nonce = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.Value = ""; + else { + object.Value = []; + if (options.bytes !== Array) + object.Value = $util.newBuffer(object.Value); + } + if (options.bytes === String) + object.RcvAddr = ""; + else { + object.RcvAddr = []; + if (options.bytes !== Array) + object.RcvAddr = $util.newBuffer(object.RcvAddr); + } + if (options.bytes === String) + object.RcvUserName = ""; + else { + object.RcvUserName = []; + if (options.bytes !== Array) + object.RcvUserName = $util.newBuffer(object.RcvUserName); + } + if (options.bytes === String) + object.SndAddr = ""; + else { + object.SndAddr = []; + if (options.bytes !== Array) + object.SndAddr = $util.newBuffer(object.SndAddr); + } + if (options.bytes === String) + object.SndUserName = ""; + else { + object.SndUserName = []; + if (options.bytes !== Array) + object.SndUserName = $util.newBuffer(object.SndUserName); + } + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.GasPrice = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.GasPrice = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.GasLimit = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.GasLimit = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.Data = ""; + else { + object.Data = []; + if (options.bytes !== Array) + object.Data = $util.newBuffer(object.Data); + } + if (options.bytes === String) + object.ChainID = ""; + else { + object.ChainID = []; + if (options.bytes !== Array) + object.ChainID = $util.newBuffer(object.ChainID); + } + object.Version = 0; + if (options.bytes === String) + object.Signature = ""; + else { + object.Signature = []; + if (options.bytes !== Array) + object.Signature = $util.newBuffer(object.Signature); + } + object.Options = 0; + if (options.bytes === String) + object.GuardianAddr = ""; + else { + object.GuardianAddr = []; + if (options.bytes !== Array) + object.GuardianAddr = $util.newBuffer(object.GuardianAddr); + } + if (options.bytes === String) + object.GuardianSignature = ""; + else { + object.GuardianSignature = []; + if (options.bytes !== Array) + object.GuardianSignature = $util.newBuffer(object.GuardianSignature); + } } - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.GasPrice = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.GasPrice = options.longs === String ? "0" : 0; - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.GasLimit = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.GasLimit = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.Data = ""; - else { - object.Data = []; - if (options.bytes !== Array) - object.Data = $util.newBuffer(object.Data); - } - if (options.bytes === String) - object.ChainID = ""; - else { - object.ChainID = []; - if (options.bytes !== Array) - object.ChainID = $util.newBuffer(object.ChainID); - } - object.Version = 0; - if (options.bytes === String) - object.Signature = ""; - else { - object.Signature = []; - if (options.bytes !== Array) - object.Signature = $util.newBuffer(object.Signature); - } - object.Options = 0; - if (options.bytes === String) - object.GuardAddr = ""; - else { - object.GuardAddr = []; - if (options.bytes !== Array) - object.GuardAddr = $util.newBuffer(object.GuardAddr); - } - if (options.bytes === String) - object.GuardSignature = ""; - else { - object.GuardSignature = []; - if (options.bytes !== Array) - object.GuardSignature = $util.newBuffer(object.GuardSignature); + if (message.Nonce != null && message.hasOwnProperty("Nonce")) + if (typeof message.Nonce === "number") + object.Nonce = options.longs === String ? String(message.Nonce) : message.Nonce; + else + object.Nonce = options.longs === String ? $util.Long.prototype.toString.call(message.Nonce) : options.longs === Number ? new $util.LongBits(message.Nonce.low >>> 0, message.Nonce.high >>> 0).toNumber(true) : message.Nonce; + if (message.Value != null && message.hasOwnProperty("Value")) + object.Value = options.bytes === String ? $util.base64.encode(message.Value, 0, message.Value.length) : options.bytes === Array ? Array.prototype.slice.call(message.Value) : message.Value; + if (message.RcvAddr != null && message.hasOwnProperty("RcvAddr")) + object.RcvAddr = options.bytes === String ? $util.base64.encode(message.RcvAddr, 0, message.RcvAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.RcvAddr) : message.RcvAddr; + if (message.RcvUserName != null && message.hasOwnProperty("RcvUserName")) + object.RcvUserName = options.bytes === String ? $util.base64.encode(message.RcvUserName, 0, message.RcvUserName.length) : options.bytes === Array ? Array.prototype.slice.call(message.RcvUserName) : message.RcvUserName; + if (message.SndAddr != null && message.hasOwnProperty("SndAddr")) + object.SndAddr = options.bytes === String ? $util.base64.encode(message.SndAddr, 0, message.SndAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.SndAddr) : message.SndAddr; + if (message.SndUserName != null && message.hasOwnProperty("SndUserName")) + object.SndUserName = options.bytes === String ? $util.base64.encode(message.SndUserName, 0, message.SndUserName.length) : options.bytes === Array ? Array.prototype.slice.call(message.SndUserName) : message.SndUserName; + if (message.GasPrice != null && message.hasOwnProperty("GasPrice")) + if (typeof message.GasPrice === "number") + object.GasPrice = options.longs === String ? String(message.GasPrice) : message.GasPrice; + else + object.GasPrice = options.longs === String ? $util.Long.prototype.toString.call(message.GasPrice) : options.longs === Number ? new $util.LongBits(message.GasPrice.low >>> 0, message.GasPrice.high >>> 0).toNumber(true) : message.GasPrice; + if (message.GasLimit != null && message.hasOwnProperty("GasLimit")) + if (typeof message.GasLimit === "number") + object.GasLimit = options.longs === String ? String(message.GasLimit) : message.GasLimit; + else + object.GasLimit = options.longs === String ? $util.Long.prototype.toString.call(message.GasLimit) : options.longs === Number ? new $util.LongBits(message.GasLimit.low >>> 0, message.GasLimit.high >>> 0).toNumber(true) : message.GasLimit; + if (message.Data != null && message.hasOwnProperty("Data")) + object.Data = options.bytes === String ? $util.base64.encode(message.Data, 0, message.Data.length) : options.bytes === Array ? Array.prototype.slice.call(message.Data) : message.Data; + if (message.ChainID != null && message.hasOwnProperty("ChainID")) + object.ChainID = options.bytes === String ? $util.base64.encode(message.ChainID, 0, message.ChainID.length) : options.bytes === Array ? Array.prototype.slice.call(message.ChainID) : message.ChainID; + if (message.Version != null && message.hasOwnProperty("Version")) + object.Version = message.Version; + if (message.Signature != null && message.hasOwnProperty("Signature")) + object.Signature = options.bytes === String ? $util.base64.encode(message.Signature, 0, message.Signature.length) : options.bytes === Array ? Array.prototype.slice.call(message.Signature) : message.Signature; + if (message.Options != null && message.hasOwnProperty("Options")) + object.Options = message.Options; + if (message.GuardianAddr != null && message.hasOwnProperty("GuardianAddr")) + object.GuardianAddr = options.bytes === String ? $util.base64.encode(message.GuardianAddr, 0, message.GuardianAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.GuardianAddr) : message.GuardianAddr; + if (message.GuardianSignature != null && message.hasOwnProperty("GuardianSignature")) + object.GuardianSignature = options.bytes === String ? $util.base64.encode(message.GuardianSignature, 0, message.GuardianSignature.length) : options.bytes === Array ? Array.prototype.slice.call(message.GuardianSignature) : message.GuardianSignature; + return object; + }; + + /** + * Converts this Transaction to JSON. + * @function toJSON + * @memberof proto.Transaction + * @instance + * @returns {Object.} JSON object + */ + Transaction.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Transaction + * @function getTypeUrl + * @memberof proto.Transaction + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Transaction.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; } - } - if (message.Nonce != null && message.hasOwnProperty("Nonce")) - if (typeof message.Nonce === "number") - object.Nonce = options.longs === String ? String(message.Nonce) : message.Nonce; - else - object.Nonce = options.longs === String ? $util.Long.prototype.toString.call(message.Nonce) : options.longs === Number ? new $util.LongBits(message.Nonce.low >>> 0, message.Nonce.high >>> 0).toNumber(true) : message.Nonce; - if (message.Value != null && message.hasOwnProperty("Value")) - object.Value = options.bytes === String ? $util.base64.encode(message.Value, 0, message.Value.length) : options.bytes === Array ? Array.prototype.slice.call(message.Value) : message.Value; - if (message.RcvAddr != null && message.hasOwnProperty("RcvAddr")) - object.RcvAddr = options.bytes === String ? $util.base64.encode(message.RcvAddr, 0, message.RcvAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.RcvAddr) : message.RcvAddr; - if (message.RcvUserName != null && message.hasOwnProperty("RcvUserName")) - object.RcvUserName = options.bytes === String ? $util.base64.encode(message.RcvUserName, 0, message.RcvUserName.length) : options.bytes === Array ? Array.prototype.slice.call(message.RcvUserName) : message.RcvUserName; - if (message.SndAddr != null && message.hasOwnProperty("SndAddr")) - object.SndAddr = options.bytes === String ? $util.base64.encode(message.SndAddr, 0, message.SndAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.SndAddr) : message.SndAddr; - if (message.SndUserName != null && message.hasOwnProperty("SndUserName")) - object.SndUserName = options.bytes === String ? $util.base64.encode(message.SndUserName, 0, message.SndUserName.length) : options.bytes === Array ? Array.prototype.slice.call(message.SndUserName) : message.SndUserName; - if (message.GasPrice != null && message.hasOwnProperty("GasPrice")) - if (typeof message.GasPrice === "number") - object.GasPrice = options.longs === String ? String(message.GasPrice) : message.GasPrice; - else - object.GasPrice = options.longs === String ? $util.Long.prototype.toString.call(message.GasPrice) : options.longs === Number ? new $util.LongBits(message.GasPrice.low >>> 0, message.GasPrice.high >>> 0).toNumber(true) : message.GasPrice; - if (message.GasLimit != null && message.hasOwnProperty("GasLimit")) - if (typeof message.GasLimit === "number") - object.GasLimit = options.longs === String ? String(message.GasLimit) : message.GasLimit; - else - object.GasLimit = options.longs === String ? $util.Long.prototype.toString.call(message.GasLimit) : options.longs === Number ? new $util.LongBits(message.GasLimit.low >>> 0, message.GasLimit.high >>> 0).toNumber(true) : message.GasLimit; - if (message.Data != null && message.hasOwnProperty("Data")) - object.Data = options.bytes === String ? $util.base64.encode(message.Data, 0, message.Data.length) : options.bytes === Array ? Array.prototype.slice.call(message.Data) : message.Data; - if (message.ChainID != null && message.hasOwnProperty("ChainID")) - object.ChainID = options.bytes === String ? $util.base64.encode(message.ChainID, 0, message.ChainID.length) : options.bytes === Array ? Array.prototype.slice.call(message.ChainID) : message.ChainID; - if (message.Version != null && message.hasOwnProperty("Version")) - object.Version = message.Version; - if (message.Signature != null && message.hasOwnProperty("Signature")) - object.Signature = options.bytes === String ? $util.base64.encode(message.Signature, 0, message.Signature.length) : options.bytes === Array ? Array.prototype.slice.call(message.Signature) : message.Signature; - if (message.Options != null && message.hasOwnProperty("Options")) - object.Options = message.Options; - if (message.GuardAddr != null && message.hasOwnProperty("GuardAddr")) - object.GuardAddr = options.bytes === String ? $util.base64.encode(message.GuardAddr, 0, message.GuardAddr.length) : options.bytes === Array ? Array.prototype.slice.call(message.GuardAddr) : message.GuardAddr; - if (message.GuardSignature != null && message.hasOwnProperty("GuardSignature")) - object.GuardSignature = options.bytes === String ? $util.base64.encode(message.GuardSignature, 0, message.GuardSignature.length) : options.bytes === Array ? Array.prototype.slice.call(message.GuardSignature) : message.GuardSignature; - return object; - }; - - /** - * Converts this Transaction to JSON. - * @function toJSON - * @memberof proto.Transaction - * @instance - * @returns {Object.} JSON object - */ - Transaction.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return Transaction; + return typeUrlPrefix + "/proto.Transaction"; + }; + + return Transaction; + })(); + + return proto; })(); - return proto; -})(); - -module.exports = $root; + return $root; +}); diff --git a/src/proto/transaction.proto b/src/proto/transaction.proto index ed6674c89..c3e46e993 100644 --- a/src/proto/transaction.proto +++ b/src/proto/transaction.proto @@ -8,26 +8,21 @@ syntax = "proto3"; package proto; -option go_package = "transaction"; -option (gogoproto.stable_marshaler_all) = true; - -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; - // Transaction holds all the data needed for a value transfer or SC call message Transaction { - uint64 Nonce = 1 [(gogoproto.jsontag) = "nonce"]; - bytes Value = 2 [(gogoproto.jsontag) = "value", (gogoproto.casttypewith) = "math/big.Int;github.com/ElrondNetwork/elrond-go/data.BigIntCaster"]; - bytes RcvAddr = 3 [(gogoproto.jsontag) = "receiver"]; - bytes RcvUserName = 4 [(gogoproto.jsontag) = "rcvUserName,omitempty"]; - bytes SndAddr = 5 [(gogoproto.jsontag) = "sender"]; - bytes SndUserName = 6 [(gogoproto.jsontag) = "sndUserName,omitempty"]; - uint64 GasPrice = 7 [(gogoproto.jsontag) = "gasPrice,omitempty"]; - uint64 GasLimit = 8 [(gogoproto.jsontag) = "gasLimit,omitempty"]; - bytes Data = 9 [(gogoproto.jsontag) = "data,omitempty"]; - bytes ChainID = 10 [(gogoproto.jsontag) = "chainID"]; - uint32 Version = 11 [(gogoproto.jsontag) = "version"]; - bytes Signature = 12 [(gogoproto.jsontag) = "signature,omitempty"]; - uint32 Options = 13 [(gogoproto.jsontag) = "options,omitempty"]; - bytes GuardAddr = 14 [(gogoproto.jsontag) = "guardian,omitempty"]; - bytes GuardSignature = 15 [(gogoproto.jsontag) = "guardianSignature,omitempty"]; + uint64 Nonce = 1; + bytes Value = 2; + bytes RcvAddr = 3; + bytes RcvUserName = 4; + bytes SndAddr = 5; + bytes SndUserName = 6; + uint64 GasPrice = 7; + uint64 GasLimit = 8; + bytes Data = 9; + bytes ChainID = 10; + uint32 Version = 11; + bytes Signature = 12; + uint32 Options = 13; + bytes GuardianAddr = 14; + bytes GuardianSignature = 15; } From 1437c60dbb1f3c7fea5e04162cb641f536409dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 15:27:26 +0200 Subject: [PATCH 184/275] Undo changes in workflow. --- .github/workflows/publish-not-main.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-not-main.yml b/.github/workflows/publish-not-main.yml index 3f8f0e69c..92b3c521a 100644 --- a/.github/workflows/publish-not-main.yml +++ b/.github/workflows/publish-not-main.yml @@ -31,9 +31,8 @@ jobs: RELEASE_TAG=v$(node -p "require('./package.json').version") gh release create --prerelease $RELEASE_TAG --target=$GITHUB_SHA --title="$RELEASE_TAG" --generate-notes - # - run: npm ci - # - run: npm test - - run: npm install + - run: npm ci + - run: npm test - name: Publish to npmjs env: From f991fc57fa07d408c0b5d472f9622455d38420d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 15:28:12 +0200 Subject: [PATCH 185/275] Run audit fix. --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e955cb2b..71dd559c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2292,9 +2292,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -6922,9 +6922,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, "for-each": { From 3b143d53f4e11acdfed97124d3cefd445b951427 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 20 Mar 2024 15:37:37 +0200 Subject: [PATCH 186/275] more fixes after review --- src/transactionsFactories/transferTransactionsFactory.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 135ae56e5..5d8973461 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -60,8 +60,8 @@ export class TransferTransactionsFactory { * Should be instantiated using `Config` and `TokenComputer`. * Instantiating this class using GasEstimator represents the legacy version of this class. * The legacy version contains methods like `createEGLDTransfer`, `createESDTTransfer`, `createESDTNFTTransfer` and `createMultiESDTNFTTransfer`. + * This was done in order to minimize breaking changes in client code. */ - // this was done to minimize breaking changes in client code constructor(options: IGasEstimator | { config: IConfig; tokenComputer: ITokenComputer }) { if (this.isGasEstimator(options)) { this.gasEstimator = options; @@ -83,10 +83,7 @@ export class TransferTransactionsFactory { } private isGasEstimatorDefined(): boolean { - if (this.gasEstimator === undefined) { - return false; - } - return true; + return this.gasEstimator !== undefined; } private ensureMembersAreDefined() { From 74a0cc1596e6cb5a1b8ae3d1b57eb0cb4e0ade7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 15:42:25 +0200 Subject: [PATCH 187/275] Outcome parser - work in progress. --- src/converters/transactionsConverter.ts | 4 +-- src/smartcontracts/resultsParser.ts | 13 ++++++--- .../smartContractTransactionsOutcomeParser.ts | 28 +++++++++++++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index eb5631b9d..7d8d15a13 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -74,8 +74,8 @@ export class TransactionsConverter { public transactionOnNetworkToOutcome(transactionOnNetwork: ITransactionOnNetwork): TransactionOutcome { // In the future, this will not be needed because the transaction, as returned from the API, // will hold the data corresponding to the direct smart contract call outcome (in case of smart contract calls). - const resultsParser = new ResultsParser(); - const callOutcomeBundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); + const legacyResultsParser = new ResultsParser(); + const callOutcomeBundle = legacyResultsParser.parseUntypedOutcome(transactionOnNetwork); const callOutcome = new SmartContractCallOutcome({ returnCode: callOutcomeBundle.returnCode.toString(), returnMessage: callOutcomeBundle.returnMessage, diff --git a/src/smartcontracts/resultsParser.ts b/src/smartcontracts/resultsParser.ts index 6186e8e6c..03504a05f 100644 --- a/src/smartcontracts/resultsParser.ts +++ b/src/smartcontracts/resultsParser.ts @@ -89,12 +89,17 @@ export class ResultsParser { } parseOutcome(transaction: ITransactionOnNetwork, endpoint: { output: IParameterDefinition[] }): TypedOutcomeBundle { - let untypedBundle = this.parseUntypedOutcome(transaction); - let values = this.argsSerializer.buffersToValues(untypedBundle.values, endpoint.output); + const untypedBundle = this.parseUntypedOutcome(transaction); + const typedBundle = this.parseOutcomeFromUntypedBundle(untypedBundle, endpoint); + return typedBundle; + } + + parseOutcomeFromUntypedBundle(bundle: UntypedOutcomeBundle, endpoint: { output: IParameterDefinition[] }) { + const values = this.argsSerializer.buffersToValues(bundle.values, endpoint.output); return { - returnCode: untypedBundle.returnCode, - returnMessage: untypedBundle.returnMessage, + returnCode: bundle.returnCode, + returnMessage: bundle.returnMessage, values: values, firstValue: values[0], secondValue: values[1], diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 212ce6c48..efd4b50b9 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,4 +1,4 @@ -import { EndpointDefinition, ResultsParser } from "../smartcontracts"; +import { EndpointDefinition, ResultsParser, ReturnCode } from "../smartcontracts"; import { TransactionOutcome } from "./resources"; interface Abi { @@ -19,16 +19,34 @@ export class SmartContractTransactionsOutcomeParser { returnCode: string; returnMessage: string; } { - const functionName = options.function || options.outcome.function; + const directCallOutcome = options.outcome.directSmartContractCallOutcome; + const functionName = options.function || directCallOutcome.function; if (this.abi) { const endpoint = this.abi.getEndpoint(functionName); + const legacyUntypedBundle = { + returnCode: new ReturnCode(directCallOutcome.returnCode), + returnMessage: directCallOutcome.returnMessage, + values: directCallOutcome.returnDataParts.map((part) => Buffer.from(part)), + }; + + const legacyTypedBundle = this.legacyResultsParser.parseOutcomeFromUntypedBundle( + legacyUntypedBundle, + endpoint, + ); + + // TODO: maybe also apply "valueOf()"? + return { + values: legacyTypedBundle.values, + returnCode: legacyTypedBundle.returnCode.toString(), + returnMessage: legacyTypedBundle.returnMessage, + }; } return { - values: [], - returnCode: "", - returnMessage: "", + values: directCallOutcome.returnDataParts, + returnCode: directCallOutcome.returnCode, + returnMessage: directCallOutcome.returnMessage, }; } } From c4a265cfaa8ba8feac9ba47f7bd73e25d656482a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 15:46:29 +0200 Subject: [PATCH 188/275] Refactoring, adjust result. --- src/converters/transactionsConverter.ts | 1 + .../smartContractTransactionsOutcomeParser.ts | 36 +++++++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index 7d8d15a13..44e1f76b0 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -77,6 +77,7 @@ export class TransactionsConverter { const legacyResultsParser = new ResultsParser(); const callOutcomeBundle = legacyResultsParser.parseUntypedOutcome(transactionOnNetwork); const callOutcome = new SmartContractCallOutcome({ + function: transactionOnNetwork.function, returnCode: callOutcomeBundle.returnCode.toString(), returnMessage: callOutcomeBundle.returnMessage, returnDataParts: callOutcomeBundle.values, diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index efd4b50b9..22a5292d0 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -20,33 +20,29 @@ export class SmartContractTransactionsOutcomeParser { returnMessage: string; } { const directCallOutcome = options.outcome.directSmartContractCallOutcome; - const functionName = options.function || directCallOutcome.function; - if (this.abi) { - const endpoint = this.abi.getEndpoint(functionName); - const legacyUntypedBundle = { - returnCode: new ReturnCode(directCallOutcome.returnCode), + if (!this.abi) { + return { + values: directCallOutcome.returnDataParts, + returnCode: directCallOutcome.returnCode, returnMessage: directCallOutcome.returnMessage, - values: directCallOutcome.returnDataParts.map((part) => Buffer.from(part)), }; + } - const legacyTypedBundle = this.legacyResultsParser.parseOutcomeFromUntypedBundle( - legacyUntypedBundle, - endpoint, - ); + const functionName = options.function || directCallOutcome.function; + const endpoint = this.abi.getEndpoint(functionName); + const legacyUntypedBundle = { + returnCode: new ReturnCode(directCallOutcome.returnCode), + returnMessage: directCallOutcome.returnMessage, + values: directCallOutcome.returnDataParts.map((part) => Buffer.from(part)), + }; - // TODO: maybe also apply "valueOf()"? - return { - values: legacyTypedBundle.values, - returnCode: legacyTypedBundle.returnCode.toString(), - returnMessage: legacyTypedBundle.returnMessage, - }; - } + const legacyTypedBundle = this.legacyResultsParser.parseOutcomeFromUntypedBundle(legacyUntypedBundle, endpoint); return { - values: directCallOutcome.returnDataParts, - returnCode: directCallOutcome.returnCode, - returnMessage: directCallOutcome.returnMessage, + values: legacyTypedBundle.values.map((value) => value.valueOf()), + returnCode: legacyTypedBundle.returnCode.toString(), + returnMessage: legacyTypedBundle.returnMessage, }; } } From 8fb14f5327e75c3b97c955292fe66f8cd2f372ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 17:29:09 +0200 Subject: [PATCH 189/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9d9c0ab4d..617db93eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.6", + "version": "13.0.0-beta.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.6", + "version": "13.0.0-beta.7", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 767b0ccac..a553e106e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.6", + "version": "13.0.0-beta.7", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 1b43cb6f73fe8d01a1dda2be44e2782e45eb8cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 20 Mar 2024 17:37:43 +0200 Subject: [PATCH 190/275] Fix field names. --- src/proto/serializer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto/serializer.ts b/src/proto/serializer.ts index 9868041fc..9e1565b07 100644 --- a/src/proto/serializer.ts +++ b/src/proto/serializer.ts @@ -42,8 +42,8 @@ export class ProtoSerializer { if (transaction.isGuardedTransaction()) { const guardianAddress = transaction.getGuardian(); - protoTransaction.GuardAddr = new Address(guardianAddress.bech32()).pubkey(); - protoTransaction.GuardSignature = transaction.getGuardianSignature(); + protoTransaction.GuardianAddr = new Address(guardianAddress.bech32()).pubkey(); + protoTransaction.GuardianSignature = transaction.getGuardianSignature(); } const encoded = proto.Transaction.encode(protoTransaction).finish(); From c72db77a532de91c38415514297598d624877e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 13:42:42 +0200 Subject: [PATCH 191/275] Reference newer network providers & wallet (dev-dependencies, for tests). --- package-lock.json | 28 ++++++++-------- package.json | 4 +-- src/message.spec.ts | 8 ++--- src/transaction.local.net.spec.ts | 4 +-- src/transaction.spec.ts | 8 ++--- .../relayedTransactionsFactory.spec.ts | 32 +++++++++---------- 6 files changed, 40 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 617db93eb..55d01c751 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,8 +17,8 @@ "keccak": "3.0.2" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.3.0", - "@multiversx/sdk-wallet": "4.2.0", + "@multiversx/sdk-network-providers": "2.4.0", + "@multiversx/sdk-wallet": "4.4.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", "@types/mocha": "9.1.0", @@ -584,9 +584,9 @@ } }, "node_modules/@multiversx/sdk-network-providers": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.3.0.tgz", - "integrity": "sha512-dY7HI3rMgHHulxY9XR/O6/tCWji6ZvkuetW0NmLUjFnfOtkIdnhUzQ0u5wZaMN0SeuJIWf1QPZEsiGN82ilfTQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.0.tgz", + "integrity": "sha512-Db6OU5SNBqJRzhUYidXahWohgj9MHEy1/OnCrrijQ95PfQ1bIQlBg6lShXCdUnaXoA0oePzbxIILV6f03uZnJQ==", "dev": true, "dependencies": { "axios": "1.6.5", @@ -610,9 +610,9 @@ "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/@multiversx/sdk-wallet": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.2.0.tgz", - "integrity": "sha512-EjSb9AnqMcpmDjZ7ebkUpOzpTfxj1plTuVXwZ6AaqJsdpxMfrE2izbPy18+bg5xFlr8V27wYZcW8zOhkBR50BA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.4.0.tgz", + "integrity": "sha512-wS4P8a2ts3cNaSLUw9VFf4yhWSMTYng+nyHKi3/9QalLP5lxBumUfD/mUkb9sK13UPJ5Xp/zB3j8a4Qdllw2Ag==", "dev": true, "dependencies": { "@multiversx/sdk-bls-wasm": "0.3.5", @@ -6588,9 +6588,9 @@ "dev": true }, "@multiversx/sdk-network-providers": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.3.0.tgz", - "integrity": "sha512-dY7HI3rMgHHulxY9XR/O6/tCWji6ZvkuetW0NmLUjFnfOtkIdnhUzQ0u5wZaMN0SeuJIWf1QPZEsiGN82ilfTQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.0.tgz", + "integrity": "sha512-Db6OU5SNBqJRzhUYidXahWohgj9MHEy1/OnCrrijQ95PfQ1bIQlBg6lShXCdUnaXoA0oePzbxIILV6f03uZnJQ==", "dev": true, "requires": { "axios": "1.6.5", @@ -6616,9 +6616,9 @@ } }, "@multiversx/sdk-wallet": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.2.0.tgz", - "integrity": "sha512-EjSb9AnqMcpmDjZ7ebkUpOzpTfxj1plTuVXwZ6AaqJsdpxMfrE2izbPy18+bg5xFlr8V27wYZcW8zOhkBR50BA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-4.4.0.tgz", + "integrity": "sha512-wS4P8a2ts3cNaSLUw9VFf4yhWSMTYng+nyHKi3/9QalLP5lxBumUfD/mUkb9sK13UPJ5Xp/zB3j8a4Qdllw2Ag==", "dev": true, "requires": { "@multiversx/sdk-bls-wasm": "0.3.5", diff --git a/package.json b/package.json index a553e106e..7f1c78c79 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "keccak": "3.0.2" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.3.0", - "@multiversx/sdk-wallet": "4.2.0", + "@multiversx/sdk-network-providers": "2.4.0", + "@multiversx/sdk-wallet": "4.4.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", "@types/mocha": "9.1.0", diff --git a/src/message.spec.ts b/src/message.spec.ts index 3abe9cef2..dfa97e4c6 100644 --- a/src/message.spec.ts +++ b/src/message.spec.ts @@ -1,8 +1,8 @@ -import { assert } from "chai"; -import { Message, MessageComputer } from "./message"; -import { loadTestWallets, TestWallet } from "./testutils"; import { UserVerifier } from "@multiversx/sdk-wallet"; +import { assert } from "chai"; import { DEFAULT_MESSAGE_VERSION } from "./constants"; +import { Message, MessageComputer } from "./message"; +import { TestWallet, loadTestWallets } from "./testutils"; describe("test message", () => { let alice: TestWallet; @@ -35,7 +35,7 @@ describe("test message", () => { address: alice.getAddress(), }); - message.signature = await alice.signer.sign(Buffer.from(messageComputer.computeBytesForSigning(message))); + message.signature = await alice.signer.sign(messageComputer.computeBytesForSigning(message)); assert.equal( Buffer.from(message.signature).toString("hex"), diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 94ebefd2a..865302bbf 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -167,9 +167,7 @@ describe("test transaction", function () { transaction.nonce = BigInt(alice.account.nonce.valueOf()); const transactionComputer = new TransactionComputer(); - transaction.signature = await alice.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(transaction)), - ); + transaction.signature = await alice.signer.sign(transactionComputer.computeBytesForSigning(transaction)); const txHash = await provider.sendTransaction(transaction); await watcher.awaitCompleted(txHash); diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 257248ade..bfca6cf29 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -6,8 +6,8 @@ import { ProtoSerializer } from "./proto"; import { TestWallet, loadTestWallets } from "./testutils"; import { TokenTransfer } from "./tokenTransfer"; import { Transaction } from "./transaction"; -import { TransactionPayload } from "./transactionPayload"; import { TransactionComputer } from "./transactionComputer"; +import { TransactionPayload } from "./transactionPayload"; describe("test transaction", async () => { let wallets: Record; @@ -129,7 +129,7 @@ describe("test transaction", async () => { }); transaction.signature = await wallets.carol.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(transaction)), + transactionComputer.computeBytesForSigning(transaction), ); assert.equal( @@ -382,9 +382,7 @@ describe("test transaction", async () => { guardian: "erd1x23lzn8483xs2su4fak0r0dqx6w38enpmmqf2yrkylwq7mfnvyhsxqw57y", }); transaction.guardianSignature = new Uint8Array(64); - transaction.signature = new Uint8Array( - await alice.signer.sign(Buffer.from(transactionComputer.computeBytesForSigning(transaction))), - ); + transaction.signature = await alice.signer.sign(transactionComputer.computeBytesForSigning(transaction)); const serializer = new ProtoSerializer(); const buffer = serializer.serializeTransaction(transaction); diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/transactionsFactories/relayedTransactionsFactory.spec.ts index ca06cd8de..e48c995d5 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/transactionsFactories/relayedTransactionsFactory.spec.ts @@ -1,9 +1,9 @@ import { assert } from "chai"; import { TestWallet, loadTestWallets } from "../testutils"; import { Transaction } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; -import { TransactionComputer } from "../transactionComputer"; describe("test relayed v1 transaction builder", function () { const config = new TransactionsFactoryConfig({ chainID: "T" }); @@ -49,7 +49,7 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, @@ -58,7 +58,7 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.nonce = 2627n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await alice.signer.sign(serializedRelayedTransaction); assert.equal( Buffer.from(relayedTransaction.data).toString(), @@ -83,7 +83,7 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await carol.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await carol.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, @@ -92,7 +92,7 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.nonce = 715n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await frank.signer.sign(serializedRelayedTransaction); assert.equal( Buffer.from(relayedTransaction.data).toString(), @@ -117,7 +117,7 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await carol.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await carol.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, @@ -126,7 +126,7 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.nonce = 715n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await frank.signer.sign(serializedRelayedTransaction); assert.equal( Buffer.from(relayedTransaction.data).toString(), @@ -152,8 +152,8 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); - innerTransaction.guardianSignature = await grace.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); + innerTransaction.guardianSignature = await grace.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, @@ -162,7 +162,7 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.nonce = 2627n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await alice.signer.sign(serializedRelayedTransaction); assert.equal( Buffer.from(relayedTransaction.data).toString(), @@ -188,8 +188,8 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); - innerTransaction.guardianSignature = await grace.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); + innerTransaction.guardianSignature = await grace.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, @@ -200,8 +200,8 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.guardian = frank.address.bech32(); const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); - relayedTransaction.guardianSignature = await frank.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await alice.signer.sign(serializedRelayedTransaction); + relayedTransaction.guardianSignature = await frank.signer.sign(serializedRelayedTransaction); assert.equal( Buffer.from(relayedTransaction.data).toString(), @@ -255,7 +255,7 @@ describe("test relayed v1 transaction builder", function () { }); const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); - innerTransaction.signature = await bob.signer.sign(Buffer.from(serializedInnerTransaction)); + innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); const relayedTransaction = factory.createRelayedV2Transaction({ innerTransaction: innerTransaction, @@ -265,7 +265,7 @@ describe("test relayed v1 transaction builder", function () { relayedTransaction.nonce = 37n; const serializedRelayedTransaction = transactionComputer.computeBytesForSigning(relayedTransaction); - relayedTransaction.signature = await alice.signer.sign(Buffer.from(serializedRelayedTransaction)); + relayedTransaction.signature = await alice.signer.sign(serializedRelayedTransaction); assert.equal(relayedTransaction.version, 2); assert.equal(relayedTransaction.options, 0); From 137503e31630478b778fe2086acb1b944534a4c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 15:11:41 +0200 Subject: [PATCH 192/275] Allow one to pass a legacy, but custom ResultsParser to the new SC transactions outcome parser. --- .../smartContractTransactionsOutcomeParser.ts | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 22a5292d0..d80bcfdad 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,17 +1,37 @@ -import { EndpointDefinition, ResultsParser, ReturnCode } from "../smartcontracts"; +import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; import { TransactionOutcome } from "./resources"; interface Abi { getEndpoint(name: string): EndpointDefinition; } +interface ILegacyResultsParser { + parseOutcomeFromUntypedBundle( + bundle: UntypedOutcomeBundle, + endpoint: { output: IParameterDefinition[] }, + ): { + values: any[]; + returnCode: { valueOf(): string }; + returnMessage: string; + }; +} + +interface IParameterDefinition { + type: Type; +} + export class SmartContractTransactionsOutcomeParser { private readonly abi?: Abi; - private readonly legacyResultsParser: ResultsParser; + private readonly legacyResultsParser: ILegacyResultsParser; - constructor(options: { abi?: Abi }) { + constructor(options: { abi?: Abi; legacyResultsParser?: ILegacyResultsParser }) { this.abi = options.abi; - this.legacyResultsParser = new ResultsParser(); + + // Prior v13, we've advertised that people can override the "ResultsParser" to alter it's behavior in case of exotic flows. + // Now, since the new "SmartContractTransactionsOutcomeParser" (still) depends on the legacy "ResultsParser", + // at least until "return data parts of direct outcome of contract call" are included on API & Proxy responses (on GET transaction), + // we have to allow the same level of customization (for exotic flows). + this.legacyResultsParser = options.legacyResultsParser || new ResultsParser(); } parseExecute(options: { outcome: TransactionOutcome; function?: string }): { From d682f56c70dc6f1adbb2eb575445e8a42ba60d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 15:39:49 +0200 Subject: [PATCH 193/275] Add some tests. --- ...tContractTransactionsOutcomeParser.spec.ts | 48 +++++++++++++++++++ .../smartContractTransactionsOutcomeParser.ts | 17 ++++--- 2 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts new file mode 100644 index 000000000..ddb31101f --- /dev/null +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -0,0 +1,48 @@ +import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@multiversx/sdk-network-providers"; +import { assert } from "chai"; +import { TransactionsConverter } from "../converters/transactionsConverter"; +import { SmartContractCallOutcome, TransactionOutcome } from "./resources"; +import { SmartContractTransactionsOutcomeParser } from "./smartContractTransactionsOutcomeParser"; + +describe("test smart contract transactions outcome parser", () => { + it("parses execute outcome, without ABI (minimalistic)", function () { + const parser = new SmartContractTransactionsOutcomeParser(); + + const parsed = parser.parseExecute({ + transactionOutcome: new TransactionOutcome({ + directSmartContractCallOutcome: new SmartContractCallOutcome({ + function: "hello", + returnCode: "ok", + returnMessage: "ok", + returnDataParts: [Buffer.from([42])], + }), + }), + }); + + assert.deepEqual(parsed.values, [Buffer.from([42])]); + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + }); + + it("parses execute outcome, without ABI", function () { + const parser = new SmartContractTransactionsOutcomeParser(); + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b@2a", + }), + ]), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + + const parsed = parser.parseExecute({ transactionOutcome }); + + assert.deepEqual(parsed.values, [Buffer.from([42])]); + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + }); +}); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index d80bcfdad..219b54b83 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,5 +1,9 @@ import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; -import { TransactionOutcome } from "./resources"; +import { SmartContractCallOutcome } from "./resources"; + +interface ITransactionOutcome { + directSmartContractCallOutcome: SmartContractCallOutcome; +} interface Abi { getEndpoint(name: string): EndpointDefinition; @@ -24,22 +28,22 @@ export class SmartContractTransactionsOutcomeParser { private readonly abi?: Abi; private readonly legacyResultsParser: ILegacyResultsParser; - constructor(options: { abi?: Abi; legacyResultsParser?: ILegacyResultsParser }) { - this.abi = options.abi; + constructor(options?: { abi?: Abi; legacyResultsParser?: ILegacyResultsParser }) { + this.abi = options?.abi; // Prior v13, we've advertised that people can override the "ResultsParser" to alter it's behavior in case of exotic flows. // Now, since the new "SmartContractTransactionsOutcomeParser" (still) depends on the legacy "ResultsParser", // at least until "return data parts of direct outcome of contract call" are included on API & Proxy responses (on GET transaction), // we have to allow the same level of customization (for exotic flows). - this.legacyResultsParser = options.legacyResultsParser || new ResultsParser(); + this.legacyResultsParser = options?.legacyResultsParser || new ResultsParser(); } - parseExecute(options: { outcome: TransactionOutcome; function?: string }): { + parseExecute(options: { transactionOutcome: ITransactionOutcome; function?: string }): { values: any[]; returnCode: string; returnMessage: string; } { - const directCallOutcome = options.outcome.directSmartContractCallOutcome; + const directCallOutcome = options.transactionOutcome.directSmartContractCallOutcome; if (!this.abi) { return { @@ -51,6 +55,7 @@ export class SmartContractTransactionsOutcomeParser { const functionName = options.function || directCallOutcome.function; const endpoint = this.abi.getEndpoint(functionName); + const legacyUntypedBundle = { returnCode: new ReturnCode(directCallOutcome.returnCode), returnMessage: directCallOutcome.returnMessage, From 403bcdbb733c7d169a9e05064106b6e7ade5a5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 16:11:03 +0200 Subject: [PATCH 194/275] Extra tests. --- ...tContractTransactionsOutcomeParser.spec.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index ddb31101f..50831b525 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -1,6 +1,8 @@ import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@multiversx/sdk-network-providers"; +import BigNumber from "bignumber.js"; import { assert } from "chai"; import { TransactionsConverter } from "../converters/transactionsConverter"; +import { loadAbiRegistry } from "../testutils"; import { SmartContractCallOutcome, TransactionOutcome } from "./resources"; import { SmartContractTransactionsOutcomeParser } from "./smartContractTransactionsOutcomeParser"; @@ -45,4 +47,53 @@ describe("test smart contract transactions outcome parser", () => { assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); + + it("parses execute outcome, with ABI (minimalistic)", async function () { + const parser = new SmartContractTransactionsOutcomeParser({ + abi: await loadAbiRegistry("src/testdata/answer.abi.json"), + }); + + const parsed = parser.parseExecute({ + transactionOutcome: new TransactionOutcome({ + directSmartContractCallOutcome: new SmartContractCallOutcome({ + // For the sake of the test, let's say that we've called this function as a transaction, not as a query. + function: "getUltimateAnswer", + returnCode: "ok", + returnMessage: "ok", + returnDataParts: [Buffer.from([42])], + }), + }), + }); + + // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. + assert.deepEqual(parsed.values, [new BigNumber("42")]); + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + }); + + it("parses execute outcome, with ABI", async function () { + const parser = new SmartContractTransactionsOutcomeParser({ + abi: await loadAbiRegistry("src/testdata/answer.abi.json"), + }); + + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + function: "getUltimateAnswer", + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b@2a", + }), + ]), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const parsed = parser.parseExecute({ transactionOutcome }); + + // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. + assert.deepEqual(parsed.values, [new BigNumber("42")]); + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + }); }); From dead1be4c9c12ba1a7934d713760994b279eed90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 16:22:26 +0200 Subject: [PATCH 195/275] Handle missing function. --- ...tContractTransactionsOutcomeParser.spec.ts | 23 +++++++++++++++++++ .../smartContractTransactionsOutcomeParser.ts | 8 +++++++ 2 files changed, 31 insertions(+) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index 50831b525..92491168a 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -96,4 +96,27 @@ describe("test smart contract transactions outcome parser", () => { assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); + + it("cannot parse execute outcome, with ABI, when function name is missing", async function () { + const parser = new SmartContractTransactionsOutcomeParser({ + abi: await loadAbiRegistry("src/testdata/answer.abi.json"), + }); + + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b@2a", + }), + ]), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + + assert.throws(() => { + parser.parseExecute({ transactionOutcome }); + }, 'Function name is not available in the transaction outcome, thus endpoint definition (ABI) cannot be picked (for parsing). Maybe provide the "function" parameter explicitly?'); + }); }); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 219b54b83..4d1a16480 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,3 +1,4 @@ +import { Err } from "../errors"; import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; import { SmartContractCallOutcome } from "./resources"; @@ -54,6 +55,13 @@ export class SmartContractTransactionsOutcomeParser { } const functionName = options.function || directCallOutcome.function; + + if (!functionName) { + throw new Err( + `Function name is not available in the transaction outcome, thus endpoint definition (ABI) cannot be picked (for parsing). Maybe provide the "function" parameter explicitly?`, + ); + } + const endpoint = this.abi.getEndpoint(functionName); const legacyUntypedBundle = { From afd4c11e60ffd8be03e129cbe3003860cd70be41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 21 Mar 2024 19:03:32 +0200 Subject: [PATCH 196/275] More robust conversion of plain object to Transaction (same as v12). --- package-lock.json | 4 ++-- package.json | 2 +- src/converters/transactionsConverter.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 617db93eb..7915458b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.7", + "version": "13.0.0-beta.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.7", + "version": "13.0.0-beta.8", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index a553e106e..970a10c43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.7", + "version": "13.0.0-beta.8", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index c45c3de64..92cb6f757 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -45,8 +45,8 @@ export class TransactionsConverter { gasLimit: BigInt(object.gasLimit), data: this.bufferFromBase64(object.data), chainID: String(object.chainID), - version: object.version, - options: object.options, + version: Number(object.version), + options: Number(object.options), signature: this.bufferFromHex(object.signature), guardianSignature: this.bufferFromHex(object.guardianSignature), }); From 5d366fe401ba8f9817b4e1d9453d020cd8249b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 11:21:22 +0200 Subject: [PATCH 197/275] Test converter, fix converter. --- src/converters/transactionsConverter.ts | 3 +- src/converters/transactionsConverters.spec.ts | 166 +++++++++++++++++- src/interfaceOfNetwork.ts | 4 + 3 files changed, 170 insertions(+), 3 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index 44e1f76b0..2b667f946 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -106,6 +106,7 @@ export class TransactionsConverter { receiver: resultOnNetwork.receiver.bech32(), data: Buffer.from(resultOnNetwork.data), logs: new TransactionLogs({ + address: resultOnNetwork.logs.address.bech32(), events: resultOnNetwork.logs.events.map((event) => this.eventOnNetworkToEvent(event)), }), }); @@ -116,7 +117,7 @@ export class TransactionsConverter { address: eventOnNetwork.address.bech32(), identifier: eventOnNetwork.identifier, // TODO: Fix this workaround. - topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex()).toString("base64")), + topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex(), "hex").toString("base64")), // TODO: Check if OK. data: Buffer.from(eventOnNetwork.data), }); diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts index 0cd0a4e39..32fff30dc 100644 --- a/src/converters/transactionsConverters.spec.ts +++ b/src/converters/transactionsConverters.spec.ts @@ -1,8 +1,26 @@ +import { + ContractResultItem, + ContractResults, + TransactionEvent as TransactionEventOnNetwork, + TransactionEventTopic, + TransactionLogs, + TransactionOnNetwork, +} from "@multiversx/sdk-network-providers"; import { assert } from "chai"; +import { Address } from "../address"; import { Transaction } from "../transaction"; +import { + SmartContractCallOutcome, + SmartContractResult, + TransactionEvent, + TransactionOutcome, +} from "../transactionsOutcomeParsers/resources"; +import { TransactionsConverter } from "./transactionsConverter"; describe("test transactions converter", async () => { it("converts transaction to plain object and back", () => { + const converter = new TransactionsConverter(); + const transaction = new Transaction({ nonce: 90, value: BigInt("123456789000000000000000000000"), @@ -14,10 +32,154 @@ describe("test transactions converter", async () => { gasLimit: 80000, data: Buffer.from("hello"), chainID: "localnet", + version: 2, }); - const plainObject = transaction.toPlainObject(); - const restoredTransaction = Transaction.fromPlainObject(plainObject); + const plainObject = converter.transactionToPlainObject(transaction); + const restoredTransaction = converter.plainObjectToTransaction(plainObject); + + assert.deepEqual(plainObject, transaction.toPlainObject()); + assert.deepEqual(restoredTransaction, Transaction.fromPlainObject(plainObject)); assert.deepEqual(restoredTransaction, transaction); + assert.deepEqual(plainObject, { + nonce: 90, + value: "123456789000000000000000000000", + sender: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + senderUsername: "YWxpY2U=", + receiverUsername: "Ym9i", + gasPrice: 1000000000, + gasLimit: 80000, + data: "aGVsbG8=", + chainID: "localnet", + version: 2, + options: undefined, + guardian: undefined, + signature: undefined, + guardianSignature: undefined, + }); + }); + + it("converts transaction on network to transaction outcome", () => { + const converter = new TransactionsConverter(); + + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + function: "hello", + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b@2a", + logs: new TransactionLogs({ + address: Address.fromBech32("erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8"), + events: [ + new TransactionEventOnNetwork({ + identifier: "writeLog", + topics: [ + new TransactionEventTopic( + // '@too much gas provided for processing: gas provided = 596384500, gas used = 733010' + "QHRvbyBtdWNoIGdhcyBwcm92aWRlZCBmb3IgcHJvY2Vzc2luZzogZ2FzIHByb3ZpZGVkID0gNTk2Mzg0NTAwLCBnYXMgdXNlZCA9IDczMzAxMA==", + ), + ], + data: Buffer.from("QDZmNmI=", "base64").toString(), + }), + ], + }), + }), + ]), + }); + + const actualTransactionOutcome = converter.transactionOnNetworkToOutcome(transactionOnNetwork); + const expectedTransactionOutcome = new TransactionOutcome({ + directSmartContractCallOutcome: new SmartContractCallOutcome({ + function: "hello", + returnCode: "ok", + returnMessage: "ok", + returnDataParts: [Buffer.from([42])], + }), + smartContractResults: [ + new SmartContractResult({ + sender: "", + receiver: "", + data: Buffer.from("@6f6b@2a"), + logs: { + address: "erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8", + events: [ + new TransactionEvent({ + address: "", + identifier: "writeLog", + topics: [ + "QHRvbyBtdWNoIGdhcyBwcm92aWRlZCBmb3IgcHJvY2Vzc2luZzogZ2FzIHByb3ZpZGVkID0gNTk2Mzg0NTAwLCBnYXMgdXNlZCA9IDczMzAxMA==", + ], + data: Buffer.from("QDZmNmI=", "base64"), + }), + ], + }, + }), + ], + }); + + assert.deepEqual(actualTransactionOutcome, expectedTransactionOutcome); + }); + + it.only("converts transaction on network to transaction outcome (with signal error)", () => { + const converter = new TransactionsConverter(); + + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 42, + function: "hello", + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 42, + data: "@657865637574696f6e206661696c6564", + logs: new TransactionLogs({ + address: Address.fromBech32("erd1qqqqqqqqqqqqqpgqj8k976l59n7fyth8ujl4as5uyn3twn0ha0wsge5r5x"), + events: [ + new TransactionEventOnNetwork({ + address: Address.fromBech32( + "erd1qqqqqqqqqqqqqpgqj8k976l59n7fyth8ujl4as5uyn3twn0ha0wsge5r5x", + ), + identifier: "signalError", + topics: [ + new TransactionEventTopic("XmC5/yOF6ie6DD2kaJd5qPc2Ss7h2w7nvuWaxmCiiXQ="), + new TransactionEventTopic("aW5zdWZmaWNpZW50IGZ1bmRz"), + ], + data: "@657865637574696f6e206661696c6564", + }), + ], + }), + }), + ]), + }); + + const actualTransactionOutcome = converter.transactionOnNetworkToOutcome(transactionOnNetwork); + const expectedTransactionOutcome = new TransactionOutcome({ + directSmartContractCallOutcome: new SmartContractCallOutcome({ + function: "hello", + returnCode: "execution failed", + returnMessage: "execution failed", + returnDataParts: [], + }), + smartContractResults: [ + new SmartContractResult({ + sender: "", + receiver: "", + data: Buffer.from("@657865637574696f6e206661696c6564"), + logs: { + address: "erd1qqqqqqqqqqqqqpgqj8k976l59n7fyth8ujl4as5uyn3twn0ha0wsge5r5x", + events: [ + new TransactionEvent({ + address: "erd1qqqqqqqqqqqqqpgqj8k976l59n7fyth8ujl4as5uyn3twn0ha0wsge5r5x", + identifier: "signalError", + topics: ["XmC5/yOF6ie6DD2kaJd5qPc2Ss7h2w7nvuWaxmCiiXQ=", "aW5zdWZmaWNpZW50IGZ1bmRz"], + data: Buffer.from("@657865637574696f6e206661696c6564"), + }), + ], + }, + }), + ], + }); + + assert.deepEqual(actualTransactionOutcome, expectedTransactionOutcome); }); }); diff --git a/src/interfaceOfNetwork.ts b/src/interfaceOfNetwork.ts index 35acd76f4..15d236180 100644 --- a/src/interfaceOfNetwork.ts +++ b/src/interfaceOfNetwork.ts @@ -64,6 +64,7 @@ export interface IContractReturnCode { } export interface ITransactionLogs { + address: IAddress; events: ITransactionEvent[]; findSingleOrNoneEvent( @@ -77,6 +78,9 @@ export interface ITransactionEvent { readonly identifier: string; readonly topics: ITransactionEventTopic[]; readonly data: string; + // TODO: https://github.com/multiversx/mx-sdk-js-network-providers/blob/v2.4.0/src/transactionEvents.ts#L13 + // TODO: readonly dataPayload?: { valueOf(): Uint8Array }; + // TODO: readonly additionalData?: { valueOf(): Uint8Array }[]; findFirstOrNoneTopic(predicate: (topic: ITransactionEventTopic) => boolean): ITransactionEventTopic | undefined; getLastTopic(): ITransactionEventTopic; From c04b3eaaae02e1ef6a1f1fcd0e639c5f1fcb1e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 11:22:05 +0200 Subject: [PATCH 198/275] Return typed values from SC txs outcome parser, as well. --- .../smartContractTransactionsOutcomeParser.spec.ts | 5 +++++ .../smartContractTransactionsOutcomeParser.ts | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index 92491168a..ba7e3cb52 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -2,6 +2,7 @@ import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@mult import BigNumber from "bignumber.js"; import { assert } from "chai"; import { TransactionsConverter } from "../converters/transactionsConverter"; +import { U64Value } from "../smartcontracts"; import { loadAbiRegistry } from "../testutils"; import { SmartContractCallOutcome, TransactionOutcome } from "./resources"; import { SmartContractTransactionsOutcomeParser } from "./smartContractTransactionsOutcomeParser"; @@ -22,6 +23,7 @@ describe("test smart contract transactions outcome parser", () => { }); assert.deepEqual(parsed.values, [Buffer.from([42])]); + assert.isUndefined(parsed.valuesTyped); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -44,6 +46,7 @@ describe("test smart contract transactions outcome parser", () => { const parsed = parser.parseExecute({ transactionOutcome }); assert.deepEqual(parsed.values, [Buffer.from([42])]); + assert.isUndefined(parsed.valuesTyped); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -67,6 +70,7 @@ describe("test smart contract transactions outcome parser", () => { // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. assert.deepEqual(parsed.values, [new BigNumber("42")]); + assert.deepEqual(parsed.valuesTyped, [new U64Value(42)]); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -93,6 +97,7 @@ describe("test smart contract transactions outcome parser", () => { // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. assert.deepEqual(parsed.values, [new BigNumber("42")]); + assert.deepEqual(parsed.valuesTyped, [new U64Value(42)]); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 4d1a16480..d012f1bee 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,5 +1,12 @@ import { Err } from "../errors"; -import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; +import { + EndpointDefinition, + ResultsParser, + ReturnCode, + Type, + TypedValue, + UntypedOutcomeBundle, +} from "../smartcontracts"; import { SmartContractCallOutcome } from "./resources"; interface ITransactionOutcome { @@ -41,6 +48,7 @@ export class SmartContractTransactionsOutcomeParser { parseExecute(options: { transactionOutcome: ITransactionOutcome; function?: string }): { values: any[]; + valuesTyped?: TypedValue[]; returnCode: string; returnMessage: string; } { @@ -49,6 +57,7 @@ export class SmartContractTransactionsOutcomeParser { if (!this.abi) { return { values: directCallOutcome.returnDataParts, + valuesTyped: undefined, returnCode: directCallOutcome.returnCode, returnMessage: directCallOutcome.returnMessage, }; @@ -74,6 +83,7 @@ export class SmartContractTransactionsOutcomeParser { return { values: legacyTypedBundle.values.map((value) => value.valueOf()), + valuesTyped: legacyTypedBundle.values, returnCode: legacyTypedBundle.returnCode.toString(), returnMessage: legacyTypedBundle.returnMessage, }; From f9851696e0b33a3b5326b75005414b4f6a4b7574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 11:49:24 +0200 Subject: [PATCH 199/275] Sketch parse events. --- ...tContractTransactionsOutcomeParser.spec.ts | 5 -- .../smartContractTransactionsOutcomeParser.ts | 54 ++++++++++++------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index ba7e3cb52..92491168a 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -2,7 +2,6 @@ import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@mult import BigNumber from "bignumber.js"; import { assert } from "chai"; import { TransactionsConverter } from "../converters/transactionsConverter"; -import { U64Value } from "../smartcontracts"; import { loadAbiRegistry } from "../testutils"; import { SmartContractCallOutcome, TransactionOutcome } from "./resources"; import { SmartContractTransactionsOutcomeParser } from "./smartContractTransactionsOutcomeParser"; @@ -23,7 +22,6 @@ describe("test smart contract transactions outcome parser", () => { }); assert.deepEqual(parsed.values, [Buffer.from([42])]); - assert.isUndefined(parsed.valuesTyped); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -46,7 +44,6 @@ describe("test smart contract transactions outcome parser", () => { const parsed = parser.parseExecute({ transactionOutcome }); assert.deepEqual(parsed.values, [Buffer.from([42])]); - assert.isUndefined(parsed.valuesTyped); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -70,7 +67,6 @@ describe("test smart contract transactions outcome parser", () => { // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. assert.deepEqual(parsed.values, [new BigNumber("42")]); - assert.deepEqual(parsed.valuesTyped, [new U64Value(42)]); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); @@ -97,7 +93,6 @@ describe("test smart contract transactions outcome parser", () => { // At this moment, U64Value.valueOf() returns a BigNumber. This might change in the future. assert.deepEqual(parsed.values, [new BigNumber("42")]); - assert.deepEqual(parsed.valuesTyped, [new U64Value(42)]); assert.equal(parsed.returnCode, "ok"); assert.equal(parsed.returnMessage, "ok"); }); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index d012f1bee..b2429abc6 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,22 +1,27 @@ import { Err } from "../errors"; -import { - EndpointDefinition, - ResultsParser, - ReturnCode, - Type, - TypedValue, - UntypedOutcomeBundle, -} from "../smartcontracts"; -import { SmartContractCallOutcome } from "./resources"; - -interface ITransactionOutcome { - directSmartContractCallOutcome: SmartContractCallOutcome; +import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; +import { TransactionOutcome } from "./resources"; + +interface ITransactionEvent { + readonly topics: { valueOf(): Uint8Array }[]; + readonly dataPayload?: { valueOf(): Uint8Array }; + readonly additionalData?: { valueOf(): Uint8Array }[]; } interface Abi { getEndpoint(name: string): EndpointDefinition; } +interface IParameterDefinition { + type: Type; +} + +interface IEventInputDefinition { + name: string; + type: Type; + indexed: boolean; +} + interface ILegacyResultsParser { parseOutcomeFromUntypedBundle( bundle: UntypedOutcomeBundle, @@ -26,10 +31,8 @@ interface ILegacyResultsParser { returnCode: { valueOf(): string }; returnMessage: string; }; -} -interface IParameterDefinition { - type: Type; + parseEvent(transactionEvent: ITransactionEvent, eventDefinition: { inputs: IEventInputDefinition[] }): any; } export class SmartContractTransactionsOutcomeParser { @@ -46,9 +49,8 @@ export class SmartContractTransactionsOutcomeParser { this.legacyResultsParser = options?.legacyResultsParser || new ResultsParser(); } - parseExecute(options: { transactionOutcome: ITransactionOutcome; function?: string }): { + parseExecute(options: { transactionOutcome: TransactionOutcome; function?: string }): { values: any[]; - valuesTyped?: TypedValue[]; returnCode: string; returnMessage: string; } { @@ -57,7 +59,6 @@ export class SmartContractTransactionsOutcomeParser { if (!this.abi) { return { values: directCallOutcome.returnDataParts, - valuesTyped: undefined, returnCode: directCallOutcome.returnCode, returnMessage: directCallOutcome.returnMessage, }; @@ -83,9 +84,24 @@ export class SmartContractTransactionsOutcomeParser { return { values: legacyTypedBundle.values.map((value) => value.valueOf()), - valuesTyped: legacyTypedBundle.values, returnCode: legacyTypedBundle.returnCode.toString(), returnMessage: legacyTypedBundle.returnMessage, }; } + + parseExecuteEvent(options: { transactionOutcome: TransactionOutcome; eventIdentifier: string }): any { + if (!this.abi) { + throw new Err("For parsing an event, the ABI must be present (provided to the constructor)."); + } + + // this.legacyResultsParser.parseEvent({ + // topic: + // }) + + return {}; + } } + +// readonly topics: { valueOf(): Uint8Array }[]; +// readonly dataPayload?: { valueOf(): Uint8Array }; +// readonly additionalData?: { valueOf(): Uint8Array }[]; From f0e4c392edbc519e41d6158f1dbca51ffecdbfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 12:01:34 +0200 Subject: [PATCH 200/275] Extract common operations on resources. --- .../delegationTransactionsOutcomeParser.ts | 28 +-------- src/transactionsOutcomeParsers/resources.ts | 24 +++++++ ...okenManagementTransactionsOutcomeParser.ts | 62 ++++++------------- 3 files changed, 47 insertions(+), 67 deletions(-) diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index 036706ee2..9bfedca43 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -1,6 +1,6 @@ -import { ErrParseTransactionOutcome } from "../errors"; -import { TransactionEvent, TransactionOutcome } from "./resources"; import { Address } from "../address"; +import { ErrParseTransactionOutcome } from "../errors"; +import { TransactionEvent, TransactionOutcome, findEventsByIdentifier } from "./resources"; export class DelegationTransactionsOutcomeParser { constructor() {} @@ -8,7 +8,7 @@ export class DelegationTransactionsOutcomeParser { parseCreateNewDelegationContract(transactionOutcome: TransactionOutcome): { contractAddress: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "SCDeploy"); + const events = findEventsByIdentifier(transactionOutcome, "SCDeploy"); return events.map((event) => ({ contractAddress: this.extractContractAddress(event) })); } @@ -26,28 +26,6 @@ export class DelegationTransactionsOutcomeParser { } } - private findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { - const events = this.gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); - - if (events.length == 0) { - throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); - } - - return events; - } - - private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { - const allEvents = []; - - allEvents.push(...transactionOutcome.transactionLogs.events); - - for (const item of transactionOutcome.smartContractResults) { - allEvents.push(...item.logs.events); - } - - return allEvents; - } - private extractContractAddress(event: TransactionEvent): string { if (!event.topics[0]) { return ""; diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 4fd7249ad..d6463a91a 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -1,3 +1,5 @@ +import { ErrParseTransactionOutcome } from "../errors"; + export class TransactionEvent { address: string; identifier: string; @@ -53,3 +55,25 @@ export class TransactionOutcome { Object.assign(this, init); } } + +export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { + const events = gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); + + if (events.length == 0) { + throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); + } + + return events; +} + +export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { + const allEvents = []; + + allEvents.push(...transactionOutcome.transactionLogs.events); + + for (const item of transactionOutcome.smartContractResults) { + allEvents.push(...item.logs.events); + } + + return allEvents; +} diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index 5cbd89b20..724835879 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -1,7 +1,7 @@ -import { TransactionEvent, TransactionOutcome } from "./resources"; -import { ErrParseTransactionOutcome } from "../errors"; import { Address } from "../address"; +import { ErrParseTransactionOutcome } from "../errors"; import { bufferToBigInt } from "../smartcontracts/codec/utils"; +import { TransactionEvent, TransactionOutcome, findEventsByIdentifier } from "./resources"; export class TokenManagementTransactionsOutcomeParser { constructor() {} @@ -9,28 +9,28 @@ export class TokenManagementTransactionsOutcomeParser { parseIssueFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "issue"); + const events = findEventsByIdentifier(transactionOutcome, "issue"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseIssueNonFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "issueNonFungible"); + const events = findEventsByIdentifier(transactionOutcome, "issueNonFungible"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseIssueSemiFungible(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "issueSemiFungible"); + const events = findEventsByIdentifier(transactionOutcome, "issueSemiFungible"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseRegisterMetaEsdt(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "registerMetaESDT"); + const events = findEventsByIdentifier(transactionOutcome, "registerMetaESDT"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } @@ -38,8 +38,8 @@ export class TokenManagementTransactionsOutcomeParser { transactionOutcome: TransactionOutcome, ): { tokenIdentifier: string; roles: string[] }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const registerEvents = this.findEventsByIdentifier(transactionOutcome, "registerAndSetAllRoles"); - const setRoleEvents = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); + const registerEvents = findEventsByIdentifier(transactionOutcome, "registerAndSetAllRoles"); + const setRoleEvents = findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); if (registerEvents.length !== setRoleEvents.length) { throw new ErrParseTransactionOutcome( @@ -70,7 +70,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTSetRole"); return events.map((event) => this.getOutputForSetSpecialRoleEvent(event)); } @@ -94,7 +94,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTCreate"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTNFTCreate"); return events.map((event) => this.getOutputForNftCreateEvent(event)); } @@ -118,7 +118,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalMint"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTLocalMint"); return events.map((event) => this.getOutputForLocalMintEvent(event)); } @@ -149,7 +149,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTLocalBurn"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTLocalBurn"); return events.map((event) => this.getOutputForLocalBurnEvent(event)); } @@ -175,14 +175,14 @@ export class TokenManagementTransactionsOutcomeParser { parsePause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTPause"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTPause"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } parseUnpause(transactionOutcome: TransactionOutcome): { tokenIdentifier: string }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnPause"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTUnPause"); return events.map((event) => ({ tokenIdentifier: this.extractTokenIdentifier(event) })); } @@ -194,7 +194,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTFreeze"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTFreeze"); return events.map((event) => this.getOutputForFreezeEvent(event)); } @@ -225,7 +225,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTUnFreeze"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTUnFreeze"); return events.map((event) => this.getOutputForUnfreezeEvent(event)); } @@ -256,7 +256,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTWipe"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTWipe"); return events.map((event) => this.getOutputForWipeEvent(event)); } @@ -286,7 +286,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTNFTUpdateAttributes"); return events.map((event) => this.getOutputForUpdateAttributesEvent(event)); } @@ -313,7 +313,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTNFTAddQuantity"); return events.map((event) => this.getOutputForAddQuantityEvent(event)); } @@ -340,7 +340,7 @@ export class TokenManagementTransactionsOutcomeParser { }[] { this.ensureNoError(transactionOutcome.transactionLogs.events); - const events = this.findEventsByIdentifier(transactionOutcome, "ESDTNFTBurn"); + const events = findEventsByIdentifier(transactionOutcome, "ESDTNFTBurn"); return events.map((event) => this.getOutputForBurnQuantityEvent(event)); } @@ -373,28 +373,6 @@ export class TokenManagementTransactionsOutcomeParser { } } - private findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { - const events = this.gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); - - if (events.length == 0) { - throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); - } - - return events; - } - - private gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { - const allEvents = []; - - allEvents.push(...transactionOutcome.transactionLogs.events); - - for (const item of transactionOutcome.smartContractResults) { - allEvents.push(...item.logs.events); - } - - return allEvents; - } - private extractTokenIdentifier(event: TransactionEvent): string { if (!event.topics[0]) { return ""; From df0780a75d2b5e2d47c0b3a703637cf3d506b197 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Mar 2024 13:15:26 +0200 Subject: [PATCH 201/275] add apply options for hash signing --- src/transaction.spec.ts | 66 +++++++++++++++++++++++++++++++------- src/transactionComputer.ts | 33 ++++++++++++++++--- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 3b6c74162..07b9fb4f7 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -204,16 +204,9 @@ describe("test transaction", async () => { options: new TransactionOptions(1), }); - transaction.applySignature(await wallets.alice.signer.sign(transaction.serializeForSigning())); - - assert.equal( - "c83e69b853a891bf2130c1839362fe2a7a8db327dcc0c9f130497a4f24b0236140b394801bb2e04ce061a6f873cb432bf1bb1e6072e295610904662ac427a30a", - transaction.getSignature().toString("hex"), - ); - assert.equal( - transaction.getHash().toString(), - "32fb1681bd532b226b5bdeed61ae62ce9416bf5e92e48caf96253ff72d1670ac", - ); + assert.throws(() => { + transaction.serializeForSigning(); + }, "The `version` field should be 2 so the `options` field can be set."); }); it("should sign & compute hash (with data, with value) (legacy)", async () => { @@ -646,12 +639,63 @@ describe("test transaction", async () => { receiver: wallets.bob.address.toBech32(), gasLimit: 50000n, chainID: "localnet", + options: 1, }); transactionComputer.applyGuardian(transaction, wallets.carol.address.toBech32()); assert.equal(transaction.version, 2); - assert.equal(transaction.options, 2); + assert.equal(transaction.options, 3); assert.equal(transaction.guardian, wallets.carol.address.toBech32()); }); + + it("should apply options for hash signing", async () => { + let transaction = new Transaction({ + nonce: 89n, + value: 0n, + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "localnet", + version: 1, + options: 2, + }); + + transactionComputer.applyOptionsForHashSigning(transaction); + + assert.equal(transaction.version, 2); + assert.equal(transaction.options, 3); + }); + + it("should ensure transaction is valid", async () => { + let transaction = new Transaction({ + sender: "invalidAddress", + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "", + }); + + assert.throws(() => { + transactionComputer.computeBytesForSigning(transaction); + }, "Invalid `sender` field. Should be the bech32 address of the sender."); + + transaction.sender = wallets.alice.address.toBech32(); + + assert.throws(() => { + transactionComputer.computeBytesForSigning(transaction); + }, "The `chainID` field is not set"); + + transaction.chainID = "localnet"; + transaction.version = 1; + transaction.options = 2; + + assert.throws(() => { + transactionComputer.computeBytesForSigning(transaction); + }, "The `version` field should be 2 so the `options` field can be set."); + + transactionComputer.applyOptionsForHashSigning(transaction); + + assert.equal(transaction.version, 2); + assert.equal(transaction.options, 3); + }); }); diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index a5fc99843..0599e91c3 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -4,7 +4,12 @@ import BigNumber from "bignumber.js"; import { ITransaction } from "./interface"; import { ProtoSerializer } from "./proto"; import { Transaction } from "./transaction"; -import { BECH32_ADDRESS_LENGTH, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN } from "./constants"; +import { + BECH32_ADDRESS_LENGTH, + TRANSACTION_OPTIONS_TX_GUARDED, + TRANSACTION_OPTIONS_TX_HASH_SIGN, + TRANSACTION_VERSION_DEFAULT, +} from "./constants"; const createTransactionHasher = require("blake2b"); const createKeccakHash = require("keccak"); @@ -43,7 +48,7 @@ export class TransactionComputer { } computeBytesForSigning(transaction: ITransaction): Uint8Array { - this.ensureFields(transaction); + this.ensureValidTransactionFields(transaction); if (transaction.version >= 2 && this.hasOptionsSetForHashSigning(transaction)) { return this.computeHashForSigning(transaction); @@ -77,11 +82,21 @@ export class TransactionComputer { } applyGuardian(transaction: ITransaction, guardian: string) { - transaction.version = 2; + if (transaction.version < TRANSACTION_VERSION_DEFAULT) { + transaction.version = TRANSACTION_VERSION_DEFAULT; + } + transaction.options = transaction.options | TRANSACTION_OPTIONS_TX_GUARDED; transaction.guardian = guardian; } + applyOptionsForHashSigning(transaction: ITransaction) { + if (transaction.version < TRANSACTION_VERSION_DEFAULT) { + transaction.version = TRANSACTION_VERSION_DEFAULT; + } + transaction.options = transaction.options | TRANSACTION_OPTIONS_TX_HASH_SIGN; + } + private toPlainObjectForSigning(transaction: ITransaction) { return { nonce: Number(transaction.nonce), @@ -104,7 +119,7 @@ export class TransactionComputer { return value && value.length ? Buffer.from(value).toString("base64") : undefined; } - private ensureFields(transaction: ITransaction) { + private ensureValidTransactionFields(transaction: ITransaction) { if (transaction.sender.length !== BECH32_ADDRESS_LENGTH) { throw new errors.ErrBadUsage("Invalid `sender` field. Should be the bech32 address of the sender."); } @@ -116,5 +131,15 @@ export class TransactionComputer { if (!transaction.chainID.length) { throw new errors.ErrBadUsage("The `chainID` field is not set"); } + + if (transaction.version < TRANSACTION_VERSION_DEFAULT) { + if (this.hasOptionsSetForGuardedTransaction(transaction) || this.hasOptionsSetForHashSigning(transaction)) { + throw new errors.ErrBadUsage( + "The `version` field should be " + + `${TRANSACTION_VERSION_DEFAULT}` + + " so the `options` field can be set.", + ); + } + } } } From 651bd20d0734169256838c991cdc8a78f4820db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 14:13:53 +0200 Subject: [PATCH 202/275] Bit of cleanup. --- .../smartContractTransactionsOutcomeParser.ts | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index b2429abc6..eede9d6f3 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -2,13 +2,7 @@ import { Err } from "../errors"; import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; import { TransactionOutcome } from "./resources"; -interface ITransactionEvent { - readonly topics: { valueOf(): Uint8Array }[]; - readonly dataPayload?: { valueOf(): Uint8Array }; - readonly additionalData?: { valueOf(): Uint8Array }[]; -} - -interface Abi { +interface IAbi { getEndpoint(name: string): EndpointDefinition; } @@ -16,12 +10,6 @@ interface IParameterDefinition { type: Type; } -interface IEventInputDefinition { - name: string; - type: Type; - indexed: boolean; -} - interface ILegacyResultsParser { parseOutcomeFromUntypedBundle( bundle: UntypedOutcomeBundle, @@ -31,15 +19,13 @@ interface ILegacyResultsParser { returnCode: { valueOf(): string }; returnMessage: string; }; - - parseEvent(transactionEvent: ITransactionEvent, eventDefinition: { inputs: IEventInputDefinition[] }): any; } export class SmartContractTransactionsOutcomeParser { - private readonly abi?: Abi; + private readonly abi?: IAbi; private readonly legacyResultsParser: ILegacyResultsParser; - constructor(options?: { abi?: Abi; legacyResultsParser?: ILegacyResultsParser }) { + constructor(options?: { abi?: IAbi; legacyResultsParser?: ILegacyResultsParser }) { this.abi = options?.abi; // Prior v13, we've advertised that people can override the "ResultsParser" to alter it's behavior in case of exotic flows. @@ -88,20 +74,4 @@ export class SmartContractTransactionsOutcomeParser { returnMessage: legacyTypedBundle.returnMessage, }; } - - parseExecuteEvent(options: { transactionOutcome: TransactionOutcome; eventIdentifier: string }): any { - if (!this.abi) { - throw new Err("For parsing an event, the ABI must be present (provided to the constructor)."); - } - - // this.legacyResultsParser.parseEvent({ - // topic: - // }) - - return {}; - } } - -// readonly topics: { valueOf(): Uint8Array }[]; -// readonly dataPayload?: { valueOf(): Uint8Array }; -// readonly additionalData?: { valueOf(): Uint8Array }[]; From cfca1e708955443799d9ed2ceb44eba4c959540a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Mar 2024 14:47:28 +0200 Subject: [PATCH 203/275] fixes after review --- src/constants.ts | 1 + src/transaction.spec.ts | 14 ++++++++------ src/transactionComputer.ts | 16 +++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 42dd256d0..826563261 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -3,6 +3,7 @@ export const TRANSACTION_OPTIONS_DEFAULT = 0; export const TRANSACTION_OPTIONS_TX_HASH_SIGN = 0b0001; export const TRANSACTION_OPTIONS_TX_GUARDED = 0b0010; export const TRANSACTION_VERSION_DEFAULT = 2; +export const MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS = 2; export const ESDT_TRANSFER_GAS_LIMIT = 500000; export const ESDT_TRANSFER_FUNCTION_NAME = "ESDTTransfer"; export const ESDTNFT_TRANSFER_FUNCTION_NAME = "ESDTNFTTransfer"; diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 07b9fb4f7..ea38e94f4 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -8,6 +8,7 @@ import { TokenTransfer } from "./tokenTransfer"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { TransactionComputer } from "./transactionComputer"; +import { MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS } from "./constants"; describe("test transaction", async () => { let wallets: Record; @@ -206,7 +207,7 @@ describe("test transaction", async () => { assert.throws(() => { transaction.serializeForSigning(); - }, "The `version` field should be 2 so the `options` field can be set."); + }, `Non-empty transaction options requires transaction version >= ${MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS}`); }); it("should sign & compute hash (with data, with value) (legacy)", async () => { @@ -639,17 +640,16 @@ describe("test transaction", async () => { receiver: wallets.bob.address.toBech32(), gasLimit: 50000n, chainID: "localnet", - options: 1, }); transactionComputer.applyGuardian(transaction, wallets.carol.address.toBech32()); assert.equal(transaction.version, 2); - assert.equal(transaction.options, 3); + assert.equal(transaction.options, 2); assert.equal(transaction.guardian, wallets.carol.address.toBech32()); }); - it("should apply options for hash signing", async () => { + it("should apply guardian with options set for hash signing", async () => { let transaction = new Transaction({ nonce: 89n, value: 0n, @@ -658,11 +658,13 @@ describe("test transaction", async () => { gasLimit: 50000n, chainID: "localnet", version: 1, - options: 2, }); transactionComputer.applyOptionsForHashSigning(transaction); + assert.equal(transaction.version, 2); + assert.equal(transaction.options, 1); + transactionComputer.applyGuardian(transaction, wallets.carol.address.toBech32()); assert.equal(transaction.version, 2); assert.equal(transaction.options, 3); }); @@ -691,7 +693,7 @@ describe("test transaction", async () => { assert.throws(() => { transactionComputer.computeBytesForSigning(transaction); - }, "The `version` field should be 2 so the `options` field can be set."); + }, `Non-empty transaction options requires transaction version >= ${MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS}`); transactionComputer.applyOptionsForHashSigning(transaction); diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 0599e91c3..359712f77 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -6,9 +6,9 @@ import { ProtoSerializer } from "./proto"; import { Transaction } from "./transaction"; import { BECH32_ADDRESS_LENGTH, + MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS, TRANSACTION_OPTIONS_TX_GUARDED, TRANSACTION_OPTIONS_TX_HASH_SIGN, - TRANSACTION_VERSION_DEFAULT, } from "./constants"; const createTransactionHasher = require("blake2b"); @@ -82,8 +82,8 @@ export class TransactionComputer { } applyGuardian(transaction: ITransaction, guardian: string) { - if (transaction.version < TRANSACTION_VERSION_DEFAULT) { - transaction.version = TRANSACTION_VERSION_DEFAULT; + if (transaction.version < MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS) { + transaction.version = MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS; } transaction.options = transaction.options | TRANSACTION_OPTIONS_TX_GUARDED; @@ -91,8 +91,8 @@ export class TransactionComputer { } applyOptionsForHashSigning(transaction: ITransaction) { - if (transaction.version < TRANSACTION_VERSION_DEFAULT) { - transaction.version = TRANSACTION_VERSION_DEFAULT; + if (transaction.version < MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS) { + transaction.version = MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS; } transaction.options = transaction.options | TRANSACTION_OPTIONS_TX_HASH_SIGN; } @@ -132,12 +132,10 @@ export class TransactionComputer { throw new errors.ErrBadUsage("The `chainID` field is not set"); } - if (transaction.version < TRANSACTION_VERSION_DEFAULT) { + if (transaction.version < MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS) { if (this.hasOptionsSetForGuardedTransaction(transaction) || this.hasOptionsSetForHashSigning(transaction)) { throw new errors.ErrBadUsage( - "The `version` field should be " + - `${TRANSACTION_VERSION_DEFAULT}` + - " so the `options` field can be set.", + `Non-empty transaction options requires transaction version >= ${MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS}`, ); } } From 678c46e0514c5baf5744fe55a0c9cf95c62bd0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 15:10:29 +0200 Subject: [PATCH 204/275] AdditionalData on events. --- package-lock.json | 14 +++++++------- package.json | 2 +- src/converters/transactionsConverter.ts | 3 ++- src/converters/transactionsConverters.spec.ts | 8 +++++++- src/interfaceOfNetwork.ts | 6 +++--- src/transactionsOutcomeParsers/resources.ts | 2 ++ 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2dacacd4a..c8e294b00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "keccak": "3.0.2" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.4.0", + "@multiversx/sdk-network-providers": "2.4.1", "@multiversx/sdk-wallet": "4.4.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", @@ -584,9 +584,9 @@ } }, "node_modules/@multiversx/sdk-network-providers": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.0.tgz", - "integrity": "sha512-Db6OU5SNBqJRzhUYidXahWohgj9MHEy1/OnCrrijQ95PfQ1bIQlBg6lShXCdUnaXoA0oePzbxIILV6f03uZnJQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.1.tgz", + "integrity": "sha512-AyKLxt51v4Y94NC3/0witz7XPpZ6+2mOi8CVW+j7HP6RtDl5vJinxCriSKb0Z/PzV6LdmJmwCW5iDRebMIk6fg==", "dev": true, "dependencies": { "axios": "1.6.5", @@ -6588,9 +6588,9 @@ "dev": true }, "@multiversx/sdk-network-providers": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.0.tgz", - "integrity": "sha512-Db6OU5SNBqJRzhUYidXahWohgj9MHEy1/OnCrrijQ95PfQ1bIQlBg6lShXCdUnaXoA0oePzbxIILV6f03uZnJQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.1.tgz", + "integrity": "sha512-AyKLxt51v4Y94NC3/0witz7XPpZ6+2mOi8CVW+j7HP6RtDl5vJinxCriSKb0Z/PzV6LdmJmwCW5iDRebMIk6fg==", "dev": true, "requires": { "axios": "1.6.5", diff --git a/package.json b/package.json index cfd28d684..ab363b343 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "keccak": "3.0.2" }, "devDependencies": { - "@multiversx/sdk-network-providers": "2.4.0", + "@multiversx/sdk-network-providers": "2.4.1", "@multiversx/sdk-wallet": "4.4.0", "@types/assert": "1.4.6", "@types/chai": "4.2.11", diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index 73599a117..f2d86402b 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -119,7 +119,8 @@ export class TransactionsConverter { // TODO: Fix this workaround. topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex(), "hex").toString("base64")), // TODO: Check if OK. - data: Buffer.from(eventOnNetwork.data), + data: eventOnNetwork.dataPayload?.valueOf() || Buffer.from(eventOnNetwork.data), + additionalData: eventOnNetwork.additionalData?.map((data) => data.valueOf()) || [], }); } } diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts index 32fff30dc..4e36df3b9 100644 --- a/src/converters/transactionsConverters.spec.ts +++ b/src/converters/transactionsConverters.spec.ts @@ -1,6 +1,7 @@ import { ContractResultItem, ContractResults, + TransactionEventData, TransactionEvent as TransactionEventOnNetwork, TransactionEventTopic, TransactionLogs, @@ -144,7 +145,11 @@ describe("test transactions converter", async () => { new TransactionEventTopic("XmC5/yOF6ie6DD2kaJd5qPc2Ss7h2w7nvuWaxmCiiXQ="), new TransactionEventTopic("aW5zdWZmaWNpZW50IGZ1bmRz"), ], - data: "@657865637574696f6e206661696c6564", + dataPayload: new TransactionEventData(Buffer.from("@657865637574696f6e206661696c6564")), + additionalData: [ + new TransactionEventData(Buffer.from("foo")), + new TransactionEventData(Buffer.from("bar")), + ], }), ], }), @@ -173,6 +178,7 @@ describe("test transactions converter", async () => { identifier: "signalError", topics: ["XmC5/yOF6ie6DD2kaJd5qPc2Ss7h2w7nvuWaxmCiiXQ=", "aW5zdWZmaWNpZW50IGZ1bmRz"], data: Buffer.from("@657865637574696f6e206661696c6564"), + additionalData: [Buffer.from("foo"), Buffer.from("bar")], }), ], }, diff --git a/src/interfaceOfNetwork.ts b/src/interfaceOfNetwork.ts index 15d236180..4fefd39e2 100644 --- a/src/interfaceOfNetwork.ts +++ b/src/interfaceOfNetwork.ts @@ -78,9 +78,9 @@ export interface ITransactionEvent { readonly identifier: string; readonly topics: ITransactionEventTopic[]; readonly data: string; - // TODO: https://github.com/multiversx/mx-sdk-js-network-providers/blob/v2.4.0/src/transactionEvents.ts#L13 - // TODO: readonly dataPayload?: { valueOf(): Uint8Array }; - // TODO: readonly additionalData?: { valueOf(): Uint8Array }[]; + // See https://github.com/multiversx/mx-sdk-js-network-providers/blob/v2.4.0/src/transactionEvents.ts#L13 + readonly dataPayload?: { valueOf(): Uint8Array }; + readonly additionalData?: { valueOf(): Uint8Array }[]; findFirstOrNoneTopic(predicate: (topic: ITransactionEventTopic) => boolean): ITransactionEventTopic | undefined; getLastTopic(): ITransactionEventTopic; diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 541583952..c079845c9 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -5,12 +5,14 @@ export class TransactionEvent { identifier: string; topics: string[]; data: Uint8Array; + additionalData: Uint8Array[]; constructor(init: Partial) { this.address = ""; this.identifier = ""; this.topics = []; this.data = new Uint8Array(); + this.additionalData = []; Object.assign(this, init); } From 80381c2f7aa05236da68476b8e234f6e31ae95ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 16:01:59 +0200 Subject: [PATCH 205/275] Fix after self review. --- src/converters/transactionsConverter.ts | 4 +-- src/converters/transactionsConverters.spec.ts | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index f2d86402b..1981268b5 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -88,6 +88,7 @@ export class TransactionsConverter { ); const logs = new TransactionLogs({ + address: transactionOnNetwork.logs.address.bech32(), events: transactionOnNetwork.logs.events.map((event) => this.eventOnNetworkToEvent(event)), }); @@ -116,9 +117,8 @@ export class TransactionsConverter { return new TransactionEvent({ address: eventOnNetwork.address.bech32(), identifier: eventOnNetwork.identifier, - // TODO: Fix this workaround. + // TODO: Workaround will be fixed soon, once "topics" become Uint8Array[]. topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex(), "hex").toString("base64")), - // TODO: Check if OK. data: eventOnNetwork.dataPayload?.valueOf() || Buffer.from(eventOnNetwork.data), additionalData: eventOnNetwork.additionalData?.map((data) => data.valueOf()) || [], }); diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts index 4e36df3b9..0a10e0114 100644 --- a/src/converters/transactionsConverters.spec.ts +++ b/src/converters/transactionsConverters.spec.ts @@ -4,7 +4,7 @@ import { TransactionEventData, TransactionEvent as TransactionEventOnNetwork, TransactionEventTopic, - TransactionLogs, + TransactionLogs as TransactionLogsOnNetwork, TransactionOnNetwork, } from "@multiversx/sdk-network-providers"; import { assert } from "chai"; @@ -14,6 +14,7 @@ import { SmartContractCallOutcome, SmartContractResult, TransactionEvent, + TransactionLogs, TransactionOutcome, } from "../transactionsOutcomeParsers/resources"; import { TransactionsConverter } from "./transactionsConverter"; @@ -67,11 +68,22 @@ describe("test transactions converter", async () => { const transactionOnNetwork = new TransactionOnNetwork({ nonce: 7, function: "hello", + logs: new TransactionLogsOnNetwork({ + address: Address.fromBech32("erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8"), + events: [ + new TransactionEventOnNetwork({ + identifier: "foobar", + topics: [], + data: Buffer.from("foo").toString(), + additionalData: [], + }), + ], + }), contractResults: new ContractResults([ new ContractResultItem({ nonce: 8, data: "@6f6b@2a", - logs: new TransactionLogs({ + logs: new TransactionLogsOnNetwork({ address: Address.fromBech32("erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8"), events: [ new TransactionEventOnNetwork({ @@ -118,6 +130,18 @@ describe("test transactions converter", async () => { }, }), ], + logs: new TransactionLogs({ + address: "erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8", + events: [ + new TransactionEvent({ + address: "", + identifier: "foobar", + topics: [], + data: Buffer.from("foo"), + additionalData: [], + }), + ], + }), }); assert.deepEqual(actualTransactionOutcome, expectedTransactionOutcome); @@ -133,7 +157,7 @@ describe("test transactions converter", async () => { new ContractResultItem({ nonce: 42, data: "@657865637574696f6e206661696c6564", - logs: new TransactionLogs({ + logs: new TransactionLogsOnNetwork({ address: Address.fromBech32("erd1qqqqqqqqqqqqqpgqj8k976l59n7fyth8ujl4as5uyn3twn0ha0wsge5r5x"), events: [ new TransactionEventOnNetwork({ From 7a625ed9e8142264e4a843e58b1d5a961e135333 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Mar 2024 16:06:27 +0200 Subject: [PATCH 206/275] change type of event topics from string to UInt8Array --- ...elegationTransactionsOutcomeParser.spec.ts | 37 ++++-- .../delegationTransactionsOutcomeParser.ts | 8 +- src/transactionsOutcomeParsers/resources.ts | 2 +- ...anagementTransactionsOutcomeParser.spec.ts | 111 ++++++++++++------ ...okenManagementTransactionsOutcomeParser.ts | 20 ++-- 5 files changed, 118 insertions(+), 60 deletions(-) diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts index f94887951..3a0d3b475 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts @@ -3,36 +3,42 @@ import { DelegationTransactionsOutcomeParser } from "./delegationTransactionsOut import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; import { Address } from "../address"; -describe("test token management transactions outcome parser", () => { +describe("test delegation transactions outcome parser", () => { const parser = new DelegationTransactionsOutcomeParser(); it("should test parseCreateNewDelegationContract ", () => { const contractAddress = Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqy8lllls62y8s5"); + let encodedTopics = [ + "Q8M8GTdWSAAA", + "Q8M8GTdWSAAA", + "AQ==", + "Q8M8GTdWSAAA", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", + ]; const delegateEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "delegate", - topics: [ - "Q8M8GTdWSAAA", - "Q8M8GTdWSAAA", - "AQ==", - "Q8M8GTdWSAAA", - "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", - ], + topics: b64TopicsToBytes(encodedTopics), }); + encodedTopics = [ + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", + "PDXX6ssamaSgzKpTfvDMCuEJ9B9sK0AiA+Yzv7sHH1w=", + ]; const scDeployEvent = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqy8lllls62y8s5", identifier: "SCDeploy", - topics: ["AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAABD///8=", "PDXX6ssamaSgzKpTfvDMCuEJ9B9sK0AiA+Yzv7sHH1w="], + topics: b64TopicsToBytes(encodedTopics), }); const logs = new TransactionLogs({ events: [delegateEvent, scDeployEvent] }); + encodedTopics = ["b2g6sUl6beG17FCUIkFwCOTGJjoJJi5SjkP2077e6xA="]; const scResultEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "completedTxEvent", - topics: ["b2g6sUl6beG17FCUIkFwCOTGJjoJJi5SjkP2077e6xA="], + topics: b64TopicsToBytes(encodedTopics), }); const scResultLog = new TransactionLogs({ @@ -57,4 +63,15 @@ describe("test token management transactions outcome parser", () => { assert.lengthOf(outcome, 1); assert.equal(outcome[0].contractAddress, contractAddress.toBech32()); }); + + function b64TopicsToBytes(topics: string[]): Uint8Array[] { + const decodedTopics: Buffer[] = []; + + for (let i = 0; i < topics.length; i++) { + const decodedTopic = Buffer.from(topics[i], "base64"); + decodedTopics.push(decodedTopic); + } + + return decodedTopics; + } }); diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index 9bfedca43..13c24aebb 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -27,14 +27,14 @@ export class DelegationTransactionsOutcomeParser { } private extractContractAddress(event: TransactionEvent): string { - if (!event.topics[0]) { + if (!event.topics[0].length) { return ""; } - const address = Buffer.from(event.topics[0], "base64"); + const address = Buffer.from(event.topics[0]); return Address.fromBuffer(address).bech32(); } - private decodeTopicAsString(topic: string): string { - return Buffer.from(topic, "base64").toString(); + private decodeTopicAsString(topic: Uint8Array): string { + return Buffer.from(topic).toString(); } } diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index d6463a91a..4b23f8c23 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -3,7 +3,7 @@ import { ErrParseTransactionOutcome } from "../errors"; export class TransactionEvent { address: string; identifier: string; - topics: string[]; + topics: Uint8Array[]; data: Uint8Array; constructor(init: Partial) { diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index cecccfaf0..33d16736c 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -7,10 +7,11 @@ describe("test token management transactions outcome parser", () => { const parser = new TokenManagementTransactionsOutcomeParser(); it("should test ensure error", () => { + const encodedTopics = ["Avk0jZ1kR+l9c76wQQoYcu4hvXPz+jxxTdqQeaCrbX8=", "dGlja2VyIG5hbWUgaXMgbm90IHZhbGlk"]; const event = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", identifier: "signalError", - topics: ["Avk0jZ1kR+l9c76wQQoYcu4hvXPz+jxxTdqQeaCrbX8=", "dGlja2VyIG5hbWUgaXMgbm90IHZhbGlk"], + topics: b64TopicsToBytes(encodedTopics), data: Buffer.from("QDc1NzM2NTcyMjA2NTcyNzI2Zjcy", "base64"), }); @@ -30,10 +31,11 @@ describe("test token management transactions outcome parser", () => { const identifier = "ZZZ-9ee87d"; const base64Identifier = Buffer.from(identifier).toString("base64"); + const encodedTopics = [base64Identifier, "U0VDT05E", "Wlpa", "RnVuZ2libGVFU0RU", "Ag=="]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "issue", - topics: [base64Identifier, "U0VDT05E", "Wlpa", "RnVuZ2libGVFU0RU", "Ag=="], + topics: b64TopicsToBytes(encodedTopics), }); const logs = new TransactionLogs({ @@ -52,22 +54,32 @@ describe("test token management transactions outcome parser", () => { const identifier = "NFT-f01d1e"; const base64Identifier = Buffer.from(identifier).toString("base64"); + let encodedTopics = [ + "TkZULWYwMWQxZQ==", + "", + "Y2FuVXBncmFkZQ==", + "dHJ1ZQ==", + "Y2FuQWRkU3BlY2lhbFJvbGVz", + "dHJ1ZQ==", + ]; const firstEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "upgradeProperties", - topics: ["TkZULWYwMWQxZQ==", "", "Y2FuVXBncmFkZQ==", "dHJ1ZQ==", "Y2FuQWRkU3BlY2lhbFJvbGVz", "dHJ1ZQ=="], + topics: b64TopicsToBytes(encodedTopics), }); + encodedTopics = ["TkZULWYwMWQxZQ==", "", "", "RVNEVFJvbGVCdXJuRm9yQWxs"]; const secondEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTSetBurnRoleForAll", - topics: ["TkZULWYwMWQxZQ==", "", "", "RVNEVFJvbGVCdXJuRm9yQWxs"], + topics: b64TopicsToBytes(encodedTopics), }); + encodedTopics = [base64Identifier, "TkZURVNU", "TkZU", "Tm9uRnVuZ2libGVFU0RU"]; const thirdEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "issueNonFungible", - topics: [base64Identifier, "TkZURVNU", "TkZU", "Tm9uRnVuZ2libGVFU0RU"], + topics: b64TopicsToBytes(encodedTopics), }); const logs = new TransactionLogs({ @@ -86,10 +98,11 @@ describe("test token management transactions outcome parser", () => { const identifier = "SEMIFNG-2c6d9f"; const base64Identifier = Buffer.from(identifier).toString("base64"); + const encodedTopics = [base64Identifier, "U0VNSQ==", "U0VNSUZORw==", "U2VtaUZ1bmdpYmxlRVNEVA=="]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "issueSemiFungible", - topics: [base64Identifier, "U0VNSQ==", "U0VNSUZORw==", "U2VtaUZ1bmdpYmxlRVNEVA=="], + topics: b64TopicsToBytes(encodedTopics), }); const logs = new TransactionLogs({ @@ -108,10 +121,11 @@ describe("test token management transactions outcome parser", () => { const identifier = "METATEST-e05d11"; const base64Identifier = Buffer.from(identifier).toString("base64"); + const encodedTopics = [base64Identifier, "TUVURVNU", "TUVUQVRFU1Q=", "TWV0YUVTRFQ="]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "registerMetaESDT", - topics: [base64Identifier, "TUVURVNU", "TUVUQVRFU1Q=", "TWV0YUVTRFQ="], + topics: b64TopicsToBytes(encodedTopics), }); const logs = new TransactionLogs({ @@ -135,16 +149,18 @@ describe("test token management transactions outcome parser", () => { const roles = ["ESDTRoleLocalMint", "ESDTRoleLocalBurn"]; + let encodedTopics = [firstBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="]; const firstEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "registerAndSetAllRoles", - topics: [firstBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], + topics: b64TopicsToBytes(encodedTopics), }); + encodedTopics = [secondBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="]; const secondEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "registerAndSetAllRoles", - topics: [secondBase64Identifier, "TE1BTw==", "TE1BTw==", "RnVuZ2libGVFU0RU", "Ag=="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -152,16 +168,18 @@ describe("test token management transactions outcome parser", () => { events: [firstEvent, secondEvent], }); + encodedTopics = ["TE1BTy1kOWY4OTI=", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="]; const firstResultEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTSetRole", - topics: ["TE1BTy1kOWY4OTI=", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="], + topics: b64TopicsToBytes(encodedTopics), }); + encodedTopics = ["VFNULTEyMzQ1Ng==", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="]; const secondResultEvent = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTSetRole", - topics: ["VFNULTEyMzQ1Ng==", "", "", "RVNEVFJvbGVMb2NhbE1pbnQ=", "RVNEVFJvbGVMb2NhbEJ1cm4="], + topics: b64TopicsToBytes(encodedTopics), }); const resultLogs = new TransactionLogs({ @@ -199,17 +217,18 @@ describe("test token management transactions outcome parser", () => { const base64Identifier = Buffer.from(identifier).toString("base64"); const roles = ["ESDTRoleNFTCreate", "ESDTRoleNFTAddQuantity", "ESDTRoleNFTBurn"]; + const encodedTopics = [ + base64Identifier, + "", + "", + "RVNEVFJvbGVORlRDcmVhdGU=", + "RVNEVFJvbGVORlRBZGRRdWFudGl0eQ==", + "RVNEVFJvbGVORlRCdXJu", + ]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTSetRole", - topics: [ - base64Identifier, - "", - "", - "RVNEVFJvbGVORlRDcmVhdGU=", - "RVNEVFJvbGVORlRBZGRRdWFudGl0eQ==", - "RVNEVFJvbGVORlRCdXJu", - ], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -234,15 +253,16 @@ describe("test token management transactions outcome parser", () => { const nonce = BigInt(1); const initialQuantity = BigInt(1); + const encodedTopics = [ + base64Identifier, + "AQ==", + "AQ==", + "CAESAgABIuUBCAESCE5GVEZJUlNUGiA8NdfqyxqZpKDMqlN+8MwK4Qn0H2wrQCID5jO/uwcfXCDEEyouUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4RzJDaHR0cHM6Ly9pcGZzLmlvL2lwZnMvUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4Rzo9dGFnczo7bWV0YWRhdGE6UW1SY1A5NGtYcjV6WmpSR3ZpN21KNnVuN0xweFVoWVZSNFI0UnBpY3h6Z1lrdA==", + ]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTNFTCreate", - topics: [ - base64Identifier, - "AQ==", - "AQ==", - "CAESAgABIuUBCAESCE5GVEZJUlNUGiA8NdfqyxqZpKDMqlN+8MwK4Qn0H2wrQCID5jO/uwcfXCDEEyouUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4RzJDaHR0cHM6Ly9pcGZzLmlvL2lwZnMvUW1ZM3ZKQ3NVcWpNM3hxeGR3VWczemJoVFNMUWZoN0szbW5aWXhyaGNRRFl4Rzo9dGFnczo7bWV0YWRhdGE6UW1SY1A5NGtYcjV6WmpSR3ZpN21KNnVuN0xweFVoWVZSNFI0UnBpY3h6Z1lrdA==", - ], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -267,10 +287,11 @@ describe("test token management transactions outcome parser", () => { const nonce = BigInt(0); const mintedSupply = BigInt(100000); + const encodedTopics = [base64Identifier, "", "AYag"]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTLocalMint", - topics: [base64Identifier, "", "AYag"], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -296,10 +317,11 @@ describe("test token management transactions outcome parser", () => { const nonce = BigInt(0); const burntSupply = BigInt(100000); + const encodedTopics = [base64Identifier, "", "AYag"]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTLocalBurn", - topics: [base64Identifier, "", "AYag"], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -323,10 +345,11 @@ describe("test token management transactions outcome parser", () => { const identifier = "AAA-29c4c9"; const base64Identifier = Buffer.from(identifier).toString("base64"); + const encodedTopics = [base64Identifier]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTPause", - topics: [base64Identifier], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -347,10 +370,11 @@ describe("test token management transactions outcome parser", () => { const identifier = "AAA-29c4c9"; const base64Identifier = Buffer.from(identifier).toString("base64"); + const encodedTopics = [base64Identifier]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTUnPause", - topics: [base64Identifier], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -374,10 +398,11 @@ describe("test token management transactions outcome parser", () => { const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + const encodedTopics = [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="]; const event = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", identifier: "ESDTFreeze", - topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -411,10 +436,11 @@ describe("test token management transactions outcome parser", () => { const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + const encodedTopics = [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="]; const event = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", identifier: "ESDTUnFreeze", - topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -448,10 +474,11 @@ describe("test token management transactions outcome parser", () => { const balance = BigInt(10000000); const address = "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"; + const encodedTopics = [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="]; const event = new TransactionEvent({ address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", identifier: "ESDTWipe", - topics: [base64Identifier, "", "mJaA", "ATlHLv9ohncamC8wg9pdQh8kwpGB5jiIIo3IHKYNaeE="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -485,10 +512,11 @@ describe("test token management transactions outcome parser", () => { const attributes = "metadata:ipfsCID/test.json;tags:tag1,tag2"; const base64Attributes = Buffer.from(attributes).toString("base64"); + const encodedTopics = [base64Identifier, "AQ==", "", base64Attributes]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTNFTUpdateAttributes", - topics: [base64Identifier, "AQ==", "", base64Attributes], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -513,10 +541,11 @@ describe("test token management transactions outcome parser", () => { const nonce = BigInt(1); const addedQuantity = BigInt(10); + const encodedTopics = [base64Identifier, "AQ==", "Cg=="]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTNFTAddQuantity", - topics: [base64Identifier, "AQ==", "Cg=="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -541,10 +570,11 @@ describe("test token management transactions outcome parser", () => { const nonce = BigInt(1); const burntQuantity = BigInt(16); + const encodedTopics = [base64Identifier, "AQ==", "EA=="]; const event = new TransactionEvent({ address: "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2", identifier: "ESDTNFTBurn", - topics: [base64Identifier, "AQ==", "EA=="], + topics: b64TopicsToBytes(encodedTopics), }); const transactionLogs = new TransactionLogs({ @@ -562,4 +592,15 @@ describe("test token management transactions outcome parser", () => { assert.equal(outcome[0].nonce, nonce); assert.equal(outcome[0].burntQuantity, burntQuantity); }); + + function b64TopicsToBytes(topics: string[]): Uint8Array[] { + const decodedTopics: Buffer[] = []; + + for (let i = 0; i < topics.length; i++) { + const decodedTopic = Buffer.from(topics[i], "base64"); + decodedTopics.push(decodedTopic); + } + + return decodedTopics; + } }); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index 724835879..e5dfbbc95 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -297,7 +297,7 @@ export class TokenManagementTransactionsOutcomeParser { } { const tokenIdentifier = this.extractTokenIdentifier(event); const nonce = this.extractNonce(event); - const attributes = event.topics[3] ? Buffer.from(event.topics[3], "base64") : new Uint8Array(); + const attributes = event.topics[3] ? event.topics[3] : new Uint8Array(); return { tokenIdentifier: tokenIdentifier, @@ -374,37 +374,37 @@ export class TokenManagementTransactionsOutcomeParser { } private extractTokenIdentifier(event: TransactionEvent): string { - if (!event.topics[0]) { + if (!event.topics[0].length) { return ""; } return this.decodeTopicAsString(event.topics[0]); } private extractNonce(event: TransactionEvent): bigint { - if (!event.topics[1]) { + if (!event.topics[1].length) { return BigInt(0); } - const nonce = Buffer.from(event.topics[1], "base64"); + const nonce = Buffer.from(event.topics[1]); return BigInt(bufferToBigInt(nonce).toFixed(0)); } private extractAmount(event: TransactionEvent): bigint { - if (!event.topics[2]) { + if (!event.topics[2].length) { return BigInt(0); } - const amount = Buffer.from(event.topics[2], "base64"); + const amount = Buffer.from(event.topics[2]); return BigInt(bufferToBigInt(amount).toFixed(0)); } private extractAddress(event: TransactionEvent): string { - if (!event.topics[3]) { + if (!event.topics[3].length) { return ""; } - const address = Buffer.from(event.topics[3], "base64"); + const address = Buffer.from(event.topics[3]); return Address.fromBuffer(address).bech32(); } - private decodeTopicAsString(topic: string): string { - return Buffer.from(topic, "base64").toString(); + private decodeTopicAsString(topic: Uint8Array): string { + return Buffer.from(topic).toString(); } } From b52b511665e935c3987214b3db4b518118db852a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Mar 2024 16:25:14 +0200 Subject: [PATCH 207/275] fixes after review --- src/testutils/utils.ts | 11 +++++++++++ .../delegationTransactionsOutcomeParser.spec.ts | 12 +----------- .../delegationTransactionsOutcomeParser.ts | 2 +- .../tokenManagementTransactionsOutcomeParser.spec.ts | 12 +----------- .../tokenManagementTransactionsOutcomeParser.ts | 8 ++++---- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/testutils/utils.ts b/src/testutils/utils.ts index 252e6b13f..c94f3c753 100644 --- a/src/testutils/utils.ts +++ b/src/testutils/utils.ts @@ -90,3 +90,14 @@ export function setupUnitTestWatcherTimeouts() { export function createAccountBalance(egld: number): BigNumber { return new BigNumber(egld.toString() + "0".repeat(18)); } + +export function b64TopicsToBytes(topics: string[]): Uint8Array[] { + const decodedTopics: Buffer[] = []; + + topics.map((topic) => { + const decodedTopic = Buffer.from(topic, "base64"); + decodedTopics.push(decodedTopic); + }); + + return decodedTopics; +} diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts index 3a0d3b475..26140ce35 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.spec.ts @@ -2,6 +2,7 @@ import { assert } from "chai"; import { DelegationTransactionsOutcomeParser } from "./delegationTransactionsOutcomeParser"; import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; import { Address } from "../address"; +import { b64TopicsToBytes } from "../testutils"; describe("test delegation transactions outcome parser", () => { const parser = new DelegationTransactionsOutcomeParser(); @@ -63,15 +64,4 @@ describe("test delegation transactions outcome parser", () => { assert.lengthOf(outcome, 1); assert.equal(outcome[0].contractAddress, contractAddress.toBech32()); }); - - function b64TopicsToBytes(topics: string[]): Uint8Array[] { - const decodedTopics: Buffer[] = []; - - for (let i = 0; i < topics.length; i++) { - const decodedTopic = Buffer.from(topics[i], "base64"); - decodedTopics.push(decodedTopic); - } - - return decodedTopics; - } }); diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index 13c24aebb..9a7189bcf 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -27,7 +27,7 @@ export class DelegationTransactionsOutcomeParser { } private extractContractAddress(event: TransactionEvent): string { - if (!event.topics[0].length) { + if (!event.topics[0]?.length) { return ""; } const address = Buffer.from(event.topics[0]); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index 33d16736c..4df967623 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -2,6 +2,7 @@ import { assert } from "chai"; import { ErrParseTransactionOutcome } from "../errors"; import { TokenManagementTransactionsOutcomeParser } from "./tokenManagementTransactionsOutcomeParser"; import { SmartContractResult, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; +import { b64TopicsToBytes } from "../testutils"; describe("test token management transactions outcome parser", () => { const parser = new TokenManagementTransactionsOutcomeParser(); @@ -592,15 +593,4 @@ describe("test token management transactions outcome parser", () => { assert.equal(outcome[0].nonce, nonce); assert.equal(outcome[0].burntQuantity, burntQuantity); }); - - function b64TopicsToBytes(topics: string[]): Uint8Array[] { - const decodedTopics: Buffer[] = []; - - for (let i = 0; i < topics.length; i++) { - const decodedTopic = Buffer.from(topics[i], "base64"); - decodedTopics.push(decodedTopic); - } - - return decodedTopics; - } }); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index e5dfbbc95..2ba426b8e 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -374,14 +374,14 @@ export class TokenManagementTransactionsOutcomeParser { } private extractTokenIdentifier(event: TransactionEvent): string { - if (!event.topics[0].length) { + if (!event.topics[0]?.length) { return ""; } return this.decodeTopicAsString(event.topics[0]); } private extractNonce(event: TransactionEvent): bigint { - if (!event.topics[1].length) { + if (!event.topics[1]?.length) { return BigInt(0); } const nonce = Buffer.from(event.topics[1]); @@ -389,7 +389,7 @@ export class TokenManagementTransactionsOutcomeParser { } private extractAmount(event: TransactionEvent): bigint { - if (!event.topics[2].length) { + if (!event.topics[2]?.length) { return BigInt(0); } const amount = Buffer.from(event.topics[2]); @@ -397,7 +397,7 @@ export class TokenManagementTransactionsOutcomeParser { } private extractAddress(event: TransactionEvent): string { - if (!event.topics[3].length) { + if (!event.topics[3]?.length) { return ""; } const address = Buffer.from(event.topics[3]); From afd326e45c0d70b4b06732574ea4e588ca1d4498 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 22 Mar 2024 16:29:27 +0200 Subject: [PATCH 208/275] small refactoring --- src/testutils/utils.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/testutils/utils.ts b/src/testutils/utils.ts index c94f3c753..76ef1b9f8 100644 --- a/src/testutils/utils.ts +++ b/src/testutils/utils.ts @@ -92,12 +92,5 @@ export function createAccountBalance(egld: number): BigNumber { } export function b64TopicsToBytes(topics: string[]): Uint8Array[] { - const decodedTopics: Buffer[] = []; - - topics.map((topic) => { - const decodedTopic = Buffer.from(topic, "base64"); - decodedTopics.push(decodedTopic); - }); - - return decodedTopics; + return topics.map((topic) => Buffer.from(topic, "base64")); } From 00852070803c57aa8a970f9bf38814db1a2a2670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 17:39:29 +0200 Subject: [PATCH 209/275] findEventsByPredicate. --- src/transactionsOutcomeParsers/resources.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index c079845c9..3cc3b73cf 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -86,6 +86,13 @@ export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, i return events; } +export function findEventsByPredicate( + transactionOutcome: TransactionOutcome, + predicate: (event: TransactionEvent) => boolean, +): TransactionEvent[] { + return gatherAllEvents(transactionOutcome).filter(predicate); +} + export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { const allEvents = []; From 7fe17c0cd6cf4970c032b9d39d2f0608c8a59b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 17:48:09 +0200 Subject: [PATCH 210/275] Undo change. --- src/transactionsOutcomeParsers/resources.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 452330b08..abbb580f7 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -1,5 +1,3 @@ -import { ErrParseTransactionOutcome } from "../errors"; - export class TransactionEvent { address: string; identifier: string; @@ -76,16 +74,6 @@ export class SmartContractCallOutcome { } } -export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { - const events = gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); - - if (events.length == 0) { - throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); - } - - return events; -} - export function findEventsByPredicate( transactionOutcome: TransactionOutcome, predicate: (event: TransactionEvent) => boolean, From 09e396e8e2f14d8eeaa90c1fd23d61d278bf7485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 17:48:38 +0200 Subject: [PATCH 211/275] Undo change. --- src/transactionsOutcomeParsers/resources.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index abbb580f7..a25d0da9c 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -1,3 +1,5 @@ +import { ErrParseTransactionOutcome } from "../errors"; + export class TransactionEvent { address: string; identifier: string; @@ -74,11 +76,14 @@ export class SmartContractCallOutcome { } } -export function findEventsByPredicate( - transactionOutcome: TransactionOutcome, - predicate: (event: TransactionEvent) => boolean, -): TransactionEvent[] { - return gatherAllEvents(transactionOutcome).filter(predicate); +export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { + const events = gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); + + if (events.length == 0) { + throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); + } + + return events; } export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { From 348c13f3c1593f7ec22e831c547f45507c0c243a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 22 Mar 2024 17:52:29 +0200 Subject: [PATCH 212/275] Fix after review / fix tests. --- src/converters/transactionsConverters.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts index fc0c67fdf..cca388dc6 100644 --- a/src/converters/transactionsConverters.spec.ts +++ b/src/converters/transactionsConverters.spec.ts @@ -74,7 +74,7 @@ describe("test transactions converter", async () => { new TransactionEventOnNetwork({ identifier: "foobar", topics: [], - data: Buffer.from("foo").toString(), + dataPayload: new TransactionEventData(Buffer.from("foo")), additionalData: [], }), ], @@ -94,7 +94,7 @@ describe("test transactions converter", async () => { "QHRvbyBtdWNoIGdhcyBwcm92aWRlZCBmb3IgcHJvY2Vzc2luZzogZ2FzIHByb3ZpZGVkID0gNTk2Mzg0NTAwLCBnYXMgdXNlZCA9IDczMzAxMA==", ), ], - data: Buffer.from("QDZmNmI=", "base64").toString(), + dataPayload: TransactionEventData.fromBase64("QDZmNmI="), }), ], }), @@ -149,7 +149,7 @@ describe("test transactions converter", async () => { assert.deepEqual(actualTransactionOutcome, expectedTransactionOutcome); }); - it.only("converts transaction on network to transaction outcome (with signal error)", () => { + it("converts transaction on network to transaction outcome (with signal error)", () => { const converter = new TransactionsConverter(); const transactionOnNetwork = new TransactionOnNetwork({ From c2c7e168691d35596f30bb916095c09929e00d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 23 Mar 2024 21:14:10 +0200 Subject: [PATCH 213/275] Sketch events parser. --- src/transactionsOutcomeParsers/resources.ts | 9 +++- .../transactionEventsParser.ts | 42 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/transactionsOutcomeParsers/transactionEventsParser.ts diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index a25d0da9c..a2534ec49 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -76,8 +76,15 @@ export class SmartContractCallOutcome { } } +export function findEventsByPredicate( + transactionOutcome: TransactionOutcome, + predicate: (event: TransactionEvent) => boolean, +): TransactionEvent[] { + return gatherAllEvents(transactionOutcome).filter(predicate); +} + export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { - const events = gatherAllEvents(transactionOutcome).filter((event) => event.identifier == identifier); + const events = findEventsByPredicate(transactionOutcome, (event) => event.identifier == identifier); if (events.length == 0) { throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts new file mode 100644 index 000000000..cd17845d5 --- /dev/null +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -0,0 +1,42 @@ +import { ResultsParser } from "../smartcontracts"; +import { EventDefinition } from "../smartcontracts/typesystem/event"; +import { TransactionEvent } from "./resources"; + +interface IAbi { + getEvent(name: string): EventDefinition; +} + +export class TransactionEventsParser { + private readonly abi: IAbi; + private readonly legacyResultsParser: ResultsParser; + + constructor(options: { abi: IAbi }) { + this.abi = options.abi; + this.legacyResultsParser = new ResultsParser(); + } + + parseEvents(options: { events: TransactionEvent[] }): any[] { + const results = []; + + for (const event of options.events) { + const parsedEvent = this.parseEvent({ event }); + results.push(parsedEvent); + } + + return results; + } + + parseEvent(options: { event: TransactionEvent }): any { + const eventDefinition = this.abi.getEvent(options.event.identifier); + const parsedEvent = this.legacyResultsParser.parseEvent( + { + topics: options.event.topics, + dataPayload: options.event.data, + additionalData: options.event.additionalData, + }, + eventDefinition, + ); + + return parsedEvent; + } +} From c0f91782b91dfc0516dd4955dad132818c97c919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:18:23 +0200 Subject: [PATCH 214/275] Event.data, event.additionalData -> "dataItems". --- src/converters/transactionsConverters.spec.ts | 12 +++++------- .../delegationTransactionsOutcomeParser.ts | 2 +- src/transactionsOutcomeParsers/resources.ts | 6 ++---- .../tokenManagementTransactionsOutcomeParser.spec.ts | 2 +- .../tokenManagementTransactionsOutcomeParser.ts | 2 +- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/converters/transactionsConverters.spec.ts b/src/converters/transactionsConverters.spec.ts index cca388dc6..dd44b173f 100644 --- a/src/converters/transactionsConverters.spec.ts +++ b/src/converters/transactionsConverters.spec.ts @@ -126,7 +126,7 @@ describe("test transactions converter", async () => { "@too much gas provided for processing: gas provided = 596384500, gas used = 733010", ), ], - data: Buffer.from("QDZmNmI=", "base64"), + dataItems: [Buffer.from("QDZmNmI=", "base64")], }), ], }, @@ -139,8 +139,7 @@ describe("test transactions converter", async () => { address: "", identifier: "foobar", topics: [], - data: Buffer.from("foo"), - additionalData: [], + dataItems: [Buffer.from("foo")], }), ], }), @@ -173,8 +172,8 @@ describe("test transactions converter", async () => { ], dataPayload: new TransactionEventData(Buffer.from("@657865637574696f6e206661696c6564")), additionalData: [ - new TransactionEventData(Buffer.from("foo")), - new TransactionEventData(Buffer.from("bar")), + new TransactionEventData(Buffer.from("@657865637574696f6e206661696c6564")), + new TransactionEventData(Buffer.from("foobar")), ], }), ], @@ -208,8 +207,7 @@ describe("test transactions converter", async () => { ).getPublicKey(), Buffer.from("insufficient funds"), ], - data: Buffer.from("@657865637574696f6e206661696c6564"), - additionalData: [Buffer.from("foo"), Buffer.from("bar")], + dataItems: [Buffer.from("@657865637574696f6e206661696c6564"), Buffer.from("foobar")], }), ], }, diff --git a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts index cad18b2bc..305949058 100644 --- a/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/delegationTransactionsOutcomeParser.ts @@ -16,7 +16,7 @@ export class DelegationTransactionsOutcomeParser { private ensureNoError(transactionEvents: TransactionEvent[]) { for (const event of transactionEvents) { if (event.identifier == "signalError") { - const data = Buffer.from(event.data.toString().slice(1)).toString(); + const data = Buffer.from(event.dataItems[0]?.toString().slice(1)).toString() || ""; const message = this.decodeTopicAsString(event.topics[1]); throw new ErrParseTransactionOutcome( diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index a2534ec49..60ae05bc1 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -4,15 +4,13 @@ export class TransactionEvent { address: string; identifier: string; topics: Uint8Array[]; - data: Uint8Array; - additionalData: Uint8Array[]; + dataItems: Uint8Array[]; constructor(init: Partial) { this.address = ""; this.identifier = ""; this.topics = []; - this.data = new Uint8Array(); - this.additionalData = []; + this.dataItems = []; Object.assign(this, init); } diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts index b48c310be..136fe6d5b 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.spec.ts @@ -13,7 +13,7 @@ describe("test token management transactions outcome parser", () => { address: "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", identifier: "signalError", topics: b64TopicsToBytes(encodedTopics), - data: Buffer.from("QDc1NzM2NTcyMjA2NTcyNzI2Zjcy", "base64"), + dataItems: [Buffer.from("QDc1NzM2NTcyMjA2NTcyNzI2Zjcy", "base64")], }); const logs = new TransactionLogs({ events: [event] }); diff --git a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts index 869095697..0702cba6c 100644 --- a/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/tokenManagementTransactionsOutcomeParser.ts @@ -363,7 +363,7 @@ export class TokenManagementTransactionsOutcomeParser { private ensureNoError(transactionEvents: TransactionEvent[]) { for (const event of transactionEvents) { if (event.identifier == "signalError") { - const data = Buffer.from(event.data.toString().slice(1)).toString(); + const data = Buffer.from(event.dataItems[0]?.toString().slice(1)).toString() || ""; const message = this.decodeTopicAsString(event.topics[1]); throw new ErrParseTransactionOutcome( From 3d4b044582fb426bd3e22644edc7329aafd81781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:22:06 +0200 Subject: [PATCH 215/275] ResultsParser - some refactoring. Kept logic as it was. --- src/converters/transactionsConverter.ts | 15 ++++- src/smartcontracts/resultsParser.ts | 87 +++++++++++++++++++------ 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index ab1190290..e095063f1 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -114,12 +114,23 @@ export class TransactionsConverter { } private eventOnNetworkToEvent(eventOnNetwork: ITransactionEvent): TransactionEvent { + // Before Sirius, there was no "additionalData" field on transaction logs. + // After Sirius, the "additionalData" field includes the payload of the legacy "data" field, as well (as its first element): + // https://github.com/multiversx/mx-chain-go/blob/v1.6.18/process/transactionLog/process.go#L159 + const legacyData = eventOnNetwork.dataPayload?.valueOf() || Buffer.from([]); + const dataItems = eventOnNetwork.additionalData?.map((data) => Buffer.from(data.valueOf())) || []; + + if (dataItems.length == 0) { + if (legacyData.length) { + dataItems.push(Buffer.from(legacyData)); + } + } + return new TransactionEvent({ address: eventOnNetwork.address.bech32(), identifier: eventOnNetwork.identifier, topics: eventOnNetwork.topics.map((topic) => Buffer.from(topic.hex(), "hex")), - data: eventOnNetwork.dataPayload?.valueOf() || Buffer.from(eventOnNetwork.data), - additionalData: eventOnNetwork.additionalData?.map((data) => data.valueOf()) || [], + dataItems: dataItems, }); } } diff --git a/src/smartcontracts/resultsParser.ts b/src/smartcontracts/resultsParser.ts index 2748024f7..3519528ca 100644 --- a/src/smartcontracts/resultsParser.ts +++ b/src/smartcontracts/resultsParser.ts @@ -1,8 +1,16 @@ -import { TransactionDecoder, TransactionMetadata } from "@multiversx/sdk-transaction-decoder/lib/src/transaction.decoder"; +import { + TransactionDecoder, + TransactionMetadata, +} from "@multiversx/sdk-transaction-decoder/lib/src/transaction.decoder"; import { Address } from "../address"; import { ErrCannotParseContractResults } from "../errors"; import { IAddress } from "../interface"; -import { IContractQueryResponse, IContractResults, ITransactionLogs, ITransactionOnNetwork } from "../interfaceOfNetwork"; +import { + IContractQueryResponse, + IContractResults, + ITransactionLogs, + ITransactionOnNetwork, +} from "../interfaceOfNetwork"; import { Logger } from "../logger"; import { ArgSerializer } from "./argSerializer"; import { TypedOutcomeBundle, UntypedOutcomeBundle } from "./interface"; @@ -51,6 +59,11 @@ const defaultResultsParserOptions: IResultsParserOptions = { }; /** + * Legacy component. + * For parsing contract query responses, use the "SmartContractQueriesController" instead. + * For parsing smart contract outcome (return data), use the "SmartContractTransactionsOutcomeParser" instead. + * For parding smart contract events, use the "TransactionEventsParser" instead. + * * Parses contract query responses and smart contract results. * The parsing involves some heuristics, in order to handle slight inconsistencies (e.g. some SCRs are present on API, but missing on Gateway). */ @@ -62,6 +75,9 @@ export class ResultsParser { this.argsSerializer = options.argsSerializer; } + /** + * Legacy method, use "SmartContractQueriesController.parseQueryResponse()" instead. + */ parseQueryResponse(queryResponse: IContractQueryResponse, endpoint: { output: IParameterDefinition[] }): TypedOutcomeBundle { let parts = queryResponse.getReturnDataParts(); let values = this.argsSerializer.buffersToValues(parts, endpoint.output); @@ -78,6 +94,9 @@ export class ResultsParser { }; } + /** + * Legacy method, use "SmartContractQueriesController.parseQueryResponse()" instead. + */ parseUntypedQueryResponse(queryResponse: IContractQueryResponse): UntypedOutcomeBundle { let returnCode = new ReturnCode(queryResponse.returnCode.toString()) @@ -88,12 +107,19 @@ export class ResultsParser { }; } + /** + * Legacy method, use "SmartContractTransactionsOutcomeParser.parseExecute()" instead. + */ parseOutcome(transaction: ITransactionOnNetwork, endpoint: { output: IParameterDefinition[] }): TypedOutcomeBundle { const untypedBundle = this.parseUntypedOutcome(transaction); const typedBundle = this.parseOutcomeFromUntypedBundle(untypedBundle, endpoint); return typedBundle; } + /** + * @internal + * For internal use only. + */ parseOutcomeFromUntypedBundle(bundle: UntypedOutcomeBundle, endpoint: { output: IParameterDefinition[] }) { const values = this.argsSerializer.buffersToValues(bundle.values, endpoint.output); @@ -108,12 +134,15 @@ export class ResultsParser { }; } + /** + * Legacy method, use "SmartContractTransactionsOutcomeParser.parseExecute()" instead. + */ parseUntypedOutcome(transaction: ITransactionOnNetwork): UntypedOutcomeBundle { let bundle: UntypedOutcomeBundle | null; let transactionMetadata = this.parseTransactionMetadata(transaction); - bundle = this.createBundleOnSimpleMoveBalance(transaction) + bundle = this.createBundleOnSimpleMoveBalance(transaction); if (bundle) { Logger.trace("parseUntypedOutcome(): on simple move balance"); return bundle; @@ -254,7 +283,7 @@ export class ResultsParser { return { returnCode: returnCode, returnMessage: returnMessage, - values: returnDataParts + values: returnDataParts, }; } @@ -337,34 +366,54 @@ export class ResultsParser { return { returnCode, returnDataParts }; } + /** + * Legacy method, use "TransactionEventsParser.parseEvent()" instead. + */ parseEvent(transactionEvent: ITransactionEvent, eventDefinition: { inputs: IEventInputDefinition[] }): any { - const result: any = {}; - - // We skip the first topic, because that's the event identifier. - const topics = transactionEvent.topics.map(topic => Buffer.from(topic.valueOf())).slice(1); - // < Sirius. + // We skip the first topic, because, for log entries emitted by smart contracts, that's the same as the event identifier. See: + // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L283 + const topics = transactionEvent.topics.map((topic) => Buffer.from(topic.valueOf())).slice(1); + + // Before Sirius, there was no "additionalData" field on transaction logs. + // After Sirius, the "additionalData" field includes the "data" field, as well (as the first element): + // https://github.com/multiversx/mx-chain-go/blob/v1.6.18/process/transactionLog/process.go#L159 + // Right now, the logic below is duplicated (see "TransactionsConverter"). However, "ResultsParser" will be deprecated & removed at a later time. const legacyData = transactionEvent.dataPayload?.valueOf() || Buffer.from([]); - // >= Sirius. - const additionalData = transactionEvent.additionalData?.map(data => Buffer.from(data.valueOf())) || []; + const dataItems = transactionEvent.additionalData?.map((data) => Buffer.from(data.valueOf())) || []; - // < Sirius. - if (additionalData.length == 0) { - if (legacyData.length > 0) { - additionalData.push(Buffer.from(legacyData)); + if (dataItems.length == 0) { + if (legacyData.length) { + dataItems.push(Buffer.from(legacyData)); } } + return this.doParseEvent({ topics, dataItems, eventDefinition }); + } + + /** + * @internal + * For internal use only. + * + * Once the legacy "ResultParser" is deprecated & removed, this logic will be absorbed into "TransactionEventsParser". + */ + doParseEvent(options: { + topics: Buffer[]; + dataItems: Buffer[]; + eventDefinition: { inputs: IEventInputDefinition[] }; + }): any { + const result: any = {}; + // "Indexed" ABI "event.inputs" correspond to "event.topics[1:]": - const indexedInputs = eventDefinition.inputs.filter(input => input.indexed); - const decodedTopics = this.argsSerializer.buffersToValues(topics, indexedInputs); + const indexedInputs = options.eventDefinition.inputs.filter((input) => input.indexed); + const decodedTopics = this.argsSerializer.buffersToValues(options.topics, indexedInputs); for (let i = 0; i < indexedInputs.length; i++) { result[indexedInputs[i].name] = decodedTopics[i].valueOf(); } // "Non-indexed" ABI "event.inputs" correspond to "event.data": - const nonIndexedInputs = eventDefinition.inputs.filter(input => !input.indexed); - const decodedDataParts = this.argsSerializer.buffersToValues(additionalData, nonIndexedInputs); + const nonIndexedInputs = options.eventDefinition.inputs.filter((input) => !input.indexed); + const decodedDataParts = this.argsSerializer.buffersToValues(options.dataItems, nonIndexedInputs); for (let i = 0; i < nonIndexedInputs.length; i++) { result[nonIndexedInputs[i].name] = decodedDataParts[i].valueOf(); From 4e1abcd1e48357d0501e831801b1fa586aae8554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:23:01 +0200 Subject: [PATCH 216/275] TransactionEventsParser: handle (omit) first topic (event identifier). --- .../transactionEventsParser.ts | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts index cd17845d5..6887b11af 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -15,27 +15,39 @@ export class TransactionEventsParser { this.legacyResultsParser = new ResultsParser(); } - parseEvents(options: { events: TransactionEvent[] }): any[] { + parseEvents(options: { events: TransactionEvent[]; firstTopicIsIdentifier?: boolean }): any[] { + const firstTopicIsIdentifier = options.firstTopicIsIdentifier; const results = []; for (const event of options.events) { - const parsedEvent = this.parseEvent({ event }); + const parsedEvent = this.parseEvent({ event, firstTopicIsIdentifier }); results.push(parsedEvent); } return results; } - parseEvent(options: { event: TransactionEvent }): any { + parseEvent(options: { event: TransactionEvent; firstTopicIsIdentifier?: boolean }): any { + // By default, we consider that the first topic is the event identifier. + // This is true for log entries emitted by smart contracts: + // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L283 + const firstTopicIsIdentifier = + options.firstTopicIsIdentifier === undefined ? true : options.firstTopicIsIdentifier; + + const topics = options.event.topics.map((topic) => Buffer.from(topic)); + const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); const eventDefinition = this.abi.getEvent(options.event.identifier); - const parsedEvent = this.legacyResultsParser.parseEvent( - { - topics: options.event.topics, - dataPayload: options.event.data, - additionalData: options.event.additionalData, - }, - eventDefinition, - ); + + if (firstTopicIsIdentifier) { + // Discard the first topic (not useful). + topics.shift(); + } + + const parsedEvent = this.legacyResultsParser.doParseEvent({ + topics: topics, + dataItems: dataItems, + eventDefinition: eventDefinition, + }); return parsedEvent; } From 68ded951a52e5d8572d0d2ba7573ad507257d429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:24:37 +0200 Subject: [PATCH 217/275] Add TODO. --- src/smartcontracts/argSerializer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/smartcontracts/argSerializer.ts b/src/smartcontracts/argSerializer.ts index f065ba7ae..4adf35a7f 100644 --- a/src/smartcontracts/argSerializer.ts +++ b/src/smartcontracts/argSerializer.ts @@ -94,6 +94,8 @@ export class ArgSerializer { // Non-composite (singular), non-variadic (fixed) type. // The only branching without a recursive call. const typedValue = decodeNextBuffer(type); + + // TODO: Handle the case (maybe throw error) when "typedValue" is, actually, null. return typedValue!; } From b6624ad511cfba68a2a4657a2fd975a28d6e349a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:34:13 +0200 Subject: [PATCH 218/275] Add tests for event parser. --- .../transactionEventsParser.spec.ts | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/transactionsOutcomeParsers/transactionEventsParser.spec.ts diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts new file mode 100644 index 000000000..f709cc9bb --- /dev/null +++ b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts @@ -0,0 +1,160 @@ +import { + ContractResultItem, + ContractResults, + TransactionEventData, + TransactionEvent as TransactionEventOnNetwork, + TransactionEventTopic, + TransactionLogs as TransactionLogsOnNetwork, + TransactionOnNetwork, +} from "@multiversx/sdk-network-providers"; +import BigNumber from "bignumber.js"; +import { assert } from "chai"; +import { Address } from "../address"; +import { TransactionsConverter } from "../converters/transactionsConverter"; +import { AbiRegistry } from "../smartcontracts"; +import { loadAbiRegistry } from "../testutils"; +import { TransactionEvent, findEventsByIdentifier } from "./resources"; +import { TransactionEventsParser } from "./transactionEventsParser"; + +describe("test transaction events parser", () => { + it("parses events (minimalistic)", async function () { + const parser = new TransactionEventsParser({ + abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), + }); + + const values = parser.parseEvents({ + events: [ + new TransactionEvent({ + identifier: "transferOverMaxAmount", + topics: [Buffer.from("transferOverMaxAmount"), Buffer.from([0x2a]), Buffer.from([0x2b])], + }), + ], + }); + + assert.deepEqual(values, [ + { + batch_id: new BigNumber(42), + tx_id: new BigNumber(43), + }, + ]); + }); + + it("parses events", async function () { + const parser = new TransactionEventsParser({ + abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), + }); + + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b", + logs: new TransactionLogsOnNetwork({ + events: [ + new TransactionEventOnNetwork({ + identifier: "deposit", + topics: [ + new TransactionEventTopic("ZGVwb3NpdA=="), + new TransactionEventTopic("cmzC1LRt1r10pMhNAnFb+FyudjGMq4G8CefCYdQUmmc="), + new TransactionEventTopic("AAAADFdFR0xELTAxZTQ5ZAAAAAAAAAAAAAAAAWQ="), + ], + dataPayload: new TransactionEventData(Buffer.from("AAAAAAAAA9sAAAA=", "base64")), + }), + ], + }), + }), + ]), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const events = findEventsByIdentifier(transactionOutcome, "deposit"); + const parsed = parser.parseEvents({ events }); + + assert.deepEqual(parsed, [ + { + dest_address: Address.fromBech32("erd1wfkv9495dhtt6a9yepxsyu2mlpw2ua333j4cr0qfulpxr4q5nfnshgyqun"), + tokens: [ + { + token_identifier: "WEGLD-01e49d", + token_nonce: new BigNumber(0), + amount: new BigNumber(100), + }, + ], + event_data: { + tx_nonce: new BigNumber(987), + opt_function: null, + opt_arguments: null, + opt_gas_limit: null, + }, + }, + ]); + }); + + it("cannot parse events, when definition is missing", async function () { + const parser = new TransactionEventsParser({ + abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), + }); + + assert.throws(() => { + parser.parseEvents({ + events: [ + new TransactionEvent({ + identifier: "foobar", + }), + ], + }); + }, "Invariant failed: [event [foobar] not found]"); + }); + + it("parses event (with multi-values)", async function () { + const abi = AbiRegistry.create({ + events: [ + { + identifier: "foobar", + inputs: [ + { + name: "a", + type: "multi", + indexed: true, + }, + { + name: "b", + type: "multi", + indexed: true, + }, + { + name: "c", + type: "u8", + indexed: false, + }, + ], + }, + ], + }); + + const parser = new TransactionEventsParser({ abi }); + const parsed = parser.parseEvent({ + event: new TransactionEvent({ + identifier: "foobar", + topics: [ + Buffer.from("foobar"), + Buffer.from([42]), + Buffer.from("test"), + Buffer.from([43]), + Buffer.from("test"), + Buffer.from("test"), + Buffer.from([44]), + ], + dataItems: [Buffer.from([42])], + }), + }); + + assert.deepEqual(parsed, { + a: [new BigNumber(42), "test", new BigNumber(43), "test"], + b: ["test", new BigNumber(44)], + c: new BigNumber(42), + }); + }); +}); From 0388311a786fade048b409b649c8855eee7229fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:42:17 +0200 Subject: [PATCH 219/275] Adjust constructor of the new "TokenTransfer" class. --- src/tokens.ts | 6 +++--- src/transaction.local.net.spec.ts | 2 +- .../smartContractTransactionsFactory.spec.ts | 12 ++++++------ .../transferTransactionsFactory.spec.ts | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tokens.ts b/src/tokens.ts index 361800ac7..342eda2f6 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -14,9 +14,9 @@ export class NextTokenTransfer { token: Token; amount: bigint; - constructor(token: Token, amount: bigint) { - this.token = token; - this.amount = amount; + constructor(options: { token: Token; amount: bigint }) { + this.token = options.token; + this.amount = options.amount; } } diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index e7d76718f..d7aa0c561 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -140,7 +140,7 @@ describe("test transaction", function () { Logger.trace(JSON.stringify(await provider.simulateTransaction(transactionTwo), null, 4)); }); - it("should create transaction using the NextTokenTransferFactory", async function () { + it("should create transaction using the TokenTransferFactory", async function () { this.timeout(70000); const provider = createLocalnetProvider(); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 74fb18033..6fcf9b874 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -152,7 +152,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000n; const args = [new U32Value(7)]; const token = new Token("FOO-6ce17b", 0n); - const transfer = new NextTokenTransfer(token, 10n); + const transfer = new NextTokenTransfer({ token, amount: 10n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -189,9 +189,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const fooToken = new Token("FOO-6ce17b", 0n); - const fooTransfer = new NextTokenTransfer(fooToken, 10n); + const fooTransfer = new NextTokenTransfer({ token: fooToken, amount: 10n }); const barToken = new Token("BAR-5bc08f", 0n); - const barTransfer = new NextTokenTransfer(barToken, 3140n); + const barTransfer = new NextTokenTransfer({ token: barToken, amount: 3140n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -235,7 +235,7 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const token = new Token("NFT-123456", 1n); - const transfer = new NextTokenTransfer(token, 1n); + const transfer = new NextTokenTransfer({ token, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -280,9 +280,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const firstToken = new Token("NFT-123456", 1n); - const firstTransfer = new NextTokenTransfer(firstToken, 1n); + const firstTransfer = new NextTokenTransfer({ token: firstToken, amount: 1n }); const secondToken = new Token("NFT-123456", 42n); - const secondTransfer = new NextTokenTransfer(secondToken, 1n); + const secondTransfer = new NextTokenTransfer({ token: secondToken, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 78af08903..240c2cc19 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -62,7 +62,7 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for esdt transfer", async () => { const fooToken = new Token("FOO-123456", 0n); - const transfer = new NextTokenTransfer(fooToken, 1000000n); + const transfer = new NextTokenTransfer({ token: fooToken, amount: 1000000n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -79,7 +79,7 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for nft transfer", async () => { const nft = new Token("NFT-123456", 10n); - const transfer = new NextTokenTransfer(nft, 1n); + const transfer = new NextTokenTransfer({ token: nft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -99,10 +99,10 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for multiple nft transfers", async () => { const firstNft = new Token("NFT-123456", 10n); - const firstTransfer = new NextTokenTransfer(firstNft, 1n); + const firstTransfer = new NextTokenTransfer({ token: firstNft, amount: 1n }); const secondNft = new Token("TEST-987654", 1n); - const secondTransfer = new NextTokenTransfer(secondNft, 1n); + const secondTransfer = new NextTokenTransfer({ token: secondNft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, From 3d82525969fc92572843f958b7c8d75c0dd3c3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:46:02 +0200 Subject: [PATCH 220/275] Minor constraints on fields: readonly. --- src/tokens.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tokens.ts b/src/tokens.ts index 342eda2f6..6a5e3ef31 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -1,8 +1,8 @@ import { ErrInvalidTokenIdentifier } from "./errors"; export class Token { - identifier: string; - nonce: bigint; + readonly identifier: string; + readonly nonce: bigint; constructor(identifier: string, nonce: bigint) { this.identifier = identifier; @@ -11,8 +11,8 @@ export class Token { } export class NextTokenTransfer { - token: Token; - amount: bigint; + readonly token: Token; + readonly amount: bigint; constructor(options: { token: Token; amount: bigint }) { this.token = options.token; From 72da628204b2c8a2ad712d28fc845caf8a47f6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 20:54:48 +0200 Subject: [PATCH 221/275] Adjust constructor. Use "options" pattern. --- src/tokens.spec.ts | 4 ++-- src/tokens.ts | 6 +++--- .../smartContractTransactionsFactory.spec.ts | 12 ++++++------ .../transferTransactionsFactory.spec.ts | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index e7949b56a..093417651 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -5,8 +5,8 @@ describe("test token computer", async () => { const tokenComputer = new TokenComputer(); it("should test if token is fungible", async () => { - const fungibleToken = new Token("TEST-123456", 0n); - const nonFungibleToken = new Token("NFT-987654", 7n); + const fungibleToken = new Token({ identifier: "TEST-123456", nonce: 0n }); + const nonFungibleToken = new Token({ identifier: "NFT-987654", nonce: 7n }); assert.equal(tokenComputer.isFungible(fungibleToken), true); assert.equal(tokenComputer.isFungible(nonFungibleToken), false); diff --git a/src/tokens.ts b/src/tokens.ts index 6a5e3ef31..d3bab272d 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -4,9 +4,9 @@ export class Token { readonly identifier: string; readonly nonce: bigint; - constructor(identifier: string, nonce: bigint) { - this.identifier = identifier; - this.nonce = nonce; + constructor(options: { identifier: string; nonce: bigint }) { + this.identifier = options.identifier; + this.nonce = options.nonce; } } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index 6fcf9b874..cc301787b 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -151,7 +151,7 @@ describe("test smart contract transactions factory", function () { const func = "add"; const gasLimit = 6000000n; const args = [new U32Value(7)]; - const token = new Token("FOO-6ce17b", 0n); + const token = new Token({ identifier: "FOO-6ce17b", nonce: 0n }); const transfer = new NextTokenTransfer({ token, amount: 10n }); const transaction = smartContractFactory.createTransactionForExecute({ @@ -188,9 +188,9 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000n; const args = [new U32Value(7)]; - const fooToken = new Token("FOO-6ce17b", 0n); + const fooToken = new Token({ identifier: "FOO-6ce17b", nonce: 0n }); const fooTransfer = new NextTokenTransfer({ token: fooToken, amount: 10n }); - const barToken = new Token("BAR-5bc08f", 0n); + const barToken = new Token({ identifier: "BAR-5bc08f", nonce: 0n }); const barTransfer = new NextTokenTransfer({ token: barToken, amount: 3140n }); const transaction = smartContractFactory.createTransactionForExecute({ @@ -234,7 +234,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000n; const args = [new U32Value(7)]; - const token = new Token("NFT-123456", 1n); + const token = new Token({ identifier: "NFT-123456", nonce: 1n }); const transfer = new NextTokenTransfer({ token, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ @@ -279,9 +279,9 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000n; const args = [new U32Value(7)]; - const firstToken = new Token("NFT-123456", 1n); + const firstToken = new Token({ identifier: "NFT-123456", nonce: 1n }); const firstTransfer = new NextTokenTransfer({ token: firstToken, amount: 1n }); - const secondToken = new Token("NFT-123456", 42n); + const secondToken = new Token({ identifier: "NFT-123456", nonce: 42n }); const secondTransfer = new NextTokenTransfer({ token: secondToken, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 240c2cc19..93f7002f8 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -61,7 +61,7 @@ describe("test transfer transcations factory", function () { }); it("should create 'Transaction' for esdt transfer", async () => { - const fooToken = new Token("FOO-123456", 0n); + const fooToken = new Token({ identifier: "FOO-123456", nonce: 0n }); const transfer = new NextTokenTransfer({ token: fooToken, amount: 1000000n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ @@ -78,7 +78,7 @@ describe("test transfer transcations factory", function () { }); it("should create 'Transaction' for nft transfer", async () => { - const nft = new Token("NFT-123456", 10n); + const nft = new Token({ identifier: "NFT-123456", nonce: 10n }); const transfer = new NextTokenTransfer({ token: nft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ @@ -98,10 +98,10 @@ describe("test transfer transcations factory", function () { }); it("should create 'Transaction' for multiple nft transfers", async () => { - const firstNft = new Token("NFT-123456", 10n); + const firstNft = new Token({ identifier: "NFT-123456", nonce: 10n }); const firstTransfer = new NextTokenTransfer({ token: firstNft, amount: 1n }); - const secondNft = new Token("TEST-987654", 1n); + const secondNft = new Token({ identifier: "TEST-987654", nonce: 1n }); const secondTransfer = new NextTokenTransfer({ token: secondNft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ From 0ec447f1c55fd5672750f010276f2f9ff3e3a8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 21:29:24 +0200 Subject: [PATCH 222/275] Merge legacy "TokenTransfer" into "NextTokenTransfer". --- src/index.ts | 3 +- src/proto/serializer.spec.ts | 2 +- src/relayedTransactionV1Builder.spec.ts | 2 +- src/smartcontracts/interaction.spec.ts | 2 +- src/smartcontracts/interactionChecker.spec.ts | 2 +- src/tokenTransfer.spec.ts | 66 ------ src/tokenTransfer.ts | 141 ----------- src/tokenTransferBuilders.spec.ts | 2 +- src/tokenTransferBuilders.ts | 2 +- src/tokens.spec.ts | 68 +++++- src/tokens.ts | 219 +++++++++++++++++- src/transaction.local.net.spec.ts | 2 +- src/transaction.spec.ts | 2 +- .../smartContractTransactionsFactory.spec.ts | 14 +- .../smartContractTransactionsFactory.ts | 4 +- .../tokenTransfersDataBuilder.ts | 8 +- .../transferTransactionsFactory.spec.ts | 10 +- .../transferTransactionsFactory.ts | 6 +- src/transferTransactionsFactory.spec.ts | 2 +- 19 files changed, 311 insertions(+), 246 deletions(-) delete mode 100644 src/tokenTransfer.spec.ts delete mode 100644 src/tokenTransfer.ts diff --git a/src/index.ts b/src/index.ts index 3043ba6cd..0ce32cab4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,10 +14,9 @@ export * from "./relayedTransactionV2Builder"; export * from "./signableMessage"; export * from "./smartcontracts"; export * from "./tokenOperations"; -export * from "./tokenTransfer"; export * from "./tokens"; export * from "./transaction"; +export * from "./transactionComputer"; export * from "./transactionPayload"; export * from "./transactionWatcher"; export * from "./utils"; -export * from "./transactionComputer"; diff --git a/src/proto/serializer.spec.ts b/src/proto/serializer.spec.ts index 174f8af2b..f92acf0ed 100644 --- a/src/proto/serializer.spec.ts +++ b/src/proto/serializer.spec.ts @@ -3,7 +3,7 @@ import { Address } from "../address"; import { TransactionVersion } from "../networkParams"; import { Signature } from "../signature"; import { loadTestWallets, TestWallet } from "../testutils"; -import { TokenTransfer } from "../tokenTransfer"; +import { TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { TransactionPayload } from "../transactionPayload"; import { ProtoSerializer } from "./serializer"; diff --git a/src/relayedTransactionV1Builder.spec.ts b/src/relayedTransactionV1Builder.spec.ts index aeb5a060a..55bbc9c09 100644 --- a/src/relayedTransactionV1Builder.spec.ts +++ b/src/relayedTransactionV1Builder.spec.ts @@ -4,7 +4,7 @@ import * as errors from "./errors"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { RelayedTransactionV1Builder } from "./relayedTransactionV1Builder"; import { TestWallet, loadTestWallets } from "./testutils"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index fbad250e2..b005ddf10 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -10,7 +10,7 @@ import { TestWallet } from "../testutils"; import { ContractController } from "../testutils/contractController"; -import { TokenTransfer } from "../tokenTransfer"; +import { TokenTransfer } from "../tokens"; import { ContractFunction } from "./function"; import { Interaction } from "./interaction"; import { ReturnCode } from "./returnCode"; diff --git a/src/smartcontracts/interactionChecker.spec.ts b/src/smartcontracts/interactionChecker.spec.ts index 157ba2907..00f511176 100644 --- a/src/smartcontracts/interactionChecker.spec.ts +++ b/src/smartcontracts/interactionChecker.spec.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { Address } from "../address"; import * as errors from "../errors"; import { loadAbiRegistry } from "../testutils"; -import { TokenTransfer } from "../tokenTransfer"; +import { TokenTransfer } from "../tokens"; import { Interaction } from "./interaction"; import { InteractionChecker } from "./interactionChecker"; import { SmartContract } from "./smartContract"; diff --git a/src/tokenTransfer.spec.ts b/src/tokenTransfer.spec.ts deleted file mode 100644 index 274121a70..000000000 --- a/src/tokenTransfer.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { assert } from "chai"; -import { TokenTransfer } from "./tokenTransfer"; - -describe("test token transfer", () => { - it("should work with EGLD", () => { - assert.equal(TokenTransfer.egldFromAmount("1").toString(), "1000000000000000000"); - assert.equal(TokenTransfer.egldFromAmount("10").toString(), "10000000000000000000"); - assert.equal(TokenTransfer.egldFromAmount("100").toString(), "100000000000000000000"); - assert.equal(TokenTransfer.egldFromAmount("1000").toString(), "1000000000000000000000"); - assert.equal(TokenTransfer.egldFromAmount("0.1").toString(), "100000000000000000"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789").toString(), "123456789000000000"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789").toString(), "123456789123456789"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789777").toString(), "123456789123456789"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toString(), "123456789123456789"); - - assert.equal(TokenTransfer.egldFromAmount(0.1).toPrettyString(), "0.100000000000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount(1).toPrettyString(), "1.000000000000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount(10).toPrettyString(), "10.000000000000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount(100).toPrettyString(), "100.000000000000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount(1000).toPrettyString(), "1000.000000000000000000 EGLD"); - assert.equal(TokenTransfer.egldFromAmount("0.123456789").toPrettyString(), "0.123456789000000000 EGLD"); - assert.equal( - TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toPrettyString(), - "0.123456789123456789 EGLD", - ); - - assert.equal(TokenTransfer.egldFromBigInteger("1").toString(), "1"); - assert.equal(TokenTransfer.egldFromBigInteger("1").toPrettyString(), "0.000000000000000001 EGLD"); - assert.isTrue(TokenTransfer.egldFromAmount("1").isEgld()); - }); - - it("should work with USDC", () => { - const identifier = "USDC-c76f1f"; - const numDecimals = 6; - - assert.equal(TokenTransfer.fungibleFromAmount(identifier, "1", numDecimals).toString(), "1000000"); - assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.1", numDecimals).toString(), "100000"); - assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.123456789", numDecimals).toString(), "123456"); - assert.equal(TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toString(), "1000000"); - assert.equal( - TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toPrettyString(), - "1.000000 USDC-c76f1f", - ); - }); - - it("should work with MetaESDT", () => { - const identifier = "MEXFARML-28d646"; - const numDecimals = 18; - const nonce = 12345678; - const transfer = TokenTransfer.metaEsdtFromAmount(identifier, nonce, "0.1", numDecimals); - - assert.equal(transfer.tokenIdentifier, identifier); - assert.equal(transfer.nonce, nonce); - assert.equal(transfer.toString(), "100000000000000000"); - }); - - it("should work with NFTs", () => { - const identifier = "TEST-38f249"; - const nonce = 1; - const transfer = TokenTransfer.nonFungible(identifier, nonce); - - assert.equal(transfer.tokenIdentifier, identifier); - assert.equal(transfer.nonce, nonce); - assert.equal(transfer.toPrettyString(), "1 TEST-38f249"); - }); -}); diff --git a/src/tokenTransfer.ts b/src/tokenTransfer.ts deleted file mode 100644 index ab81d89a4..000000000 --- a/src/tokenTransfer.ts +++ /dev/null @@ -1,141 +0,0 @@ -import BigNumber from "bignumber.js"; -import { ErrInvalidArgument } from "./errors"; - -const EGLDTokenIdentifier = "EGLD"; -const EGLDNumDecimals = 18; - -// Note: this will actually set the default rounding mode for all BigNumber objects in the environment (in the application / dApp). -BigNumber.set({ ROUNDING_MODE: 1 }); - -interface ITokenTransferOptions { - tokenIdentifier: string; - nonce: number; - amountAsBigInteger: BigNumber.Value; - numDecimals?: number; -} - -export class TokenTransfer { - readonly tokenIdentifier: string; - readonly nonce: number; - readonly amountAsBigInteger: BigNumber; - readonly numDecimals: number; - - public constructor(options: ITokenTransferOptions) { - const amount = new BigNumber(options.amountAsBigInteger); - if (!amount.isInteger() || amount.isNegative()) { - throw new ErrInvalidArgument(`bad amountAsBigInteger: ${options.amountAsBigInteger}`); - } - - this.tokenIdentifier = options.tokenIdentifier; - this.nonce = options.nonce; - this.amountAsBigInteger = amount; - this.numDecimals = options.numDecimals || 0; - } - - static egldFromAmount(amount: BigNumber.Value) { - const amountAsBigInteger = new BigNumber(amount).shiftedBy(EGLDNumDecimals).decimalPlaces(0); - return this.egldFromBigInteger(amountAsBigInteger); - } - - static egldFromBigInteger(amountAsBigInteger: BigNumber.Value) { - return new TokenTransfer({ - tokenIdentifier: EGLDTokenIdentifier, - nonce: 0, - amountAsBigInteger, - numDecimals: EGLDNumDecimals, - }); - } - - static fungibleFromAmount(tokenIdentifier: string, amount: BigNumber.Value, numDecimals: number) { - const amountAsBigInteger = new BigNumber(amount).shiftedBy(numDecimals).decimalPlaces(0); - return this.fungibleFromBigInteger(tokenIdentifier, amountAsBigInteger, numDecimals); - } - - static fungibleFromBigInteger( - tokenIdentifier: string, - amountAsBigInteger: BigNumber.Value, - numDecimals: number = 0, - ) { - return new TokenTransfer({ - tokenIdentifier, - nonce: 0, - amountAsBigInteger, - numDecimals, - }); - } - - static nonFungible(tokenIdentifier: string, nonce: number) { - return new TokenTransfer({ - tokenIdentifier, - nonce, - amountAsBigInteger: 1, - numDecimals: 0, - }); - } - - static semiFungible(tokenIdentifier: string, nonce: number, quantity: number) { - return new TokenTransfer({ - tokenIdentifier, - nonce, - amountAsBigInteger: quantity, - numDecimals: 0, - }); - } - - static metaEsdtFromAmount(tokenIdentifier: string, nonce: number, amount: BigNumber.Value, numDecimals: number) { - const amountAsBigInteger = new BigNumber(amount).shiftedBy(numDecimals).decimalPlaces(0); - return this.metaEsdtFromBigInteger(tokenIdentifier, nonce, amountAsBigInteger, numDecimals); - } - - static metaEsdtFromBigInteger( - tokenIdentifier: string, - nonce: number, - amountAsBigInteger: BigNumber.Value, - numDecimals = 0, - ) { - return new TokenTransfer({ - tokenIdentifier, - nonce, - amountAsBigInteger, - numDecimals, - }); - } - - toString() { - return this.amountAsBigInteger.toFixed(0); - } - - valueOf(): BigNumber { - return this.amountAsBigInteger; - } - - toPrettyString(): string { - return `${this.toAmount()} ${this.tokenIdentifier}`; - } - - private toAmount(): string { - return this.amountAsBigInteger.shiftedBy(-this.numDecimals).toFixed(this.numDecimals); - } - - isEgld(): boolean { - return this.tokenIdentifier == EGLDTokenIdentifier; - } - - isFungible(): boolean { - return this.nonce == 0; - } -} - -/** - * @deprecated use {@link TokenTransfer} instead. - */ -export class TokenPayment extends TokenTransfer { - constructor(tokenIdentifier: string, nonce: number, amountAsBigInteger: BigNumber.Value, numDecimals: number) { - super({ - tokenIdentifier, - nonce, - amountAsBigInteger, - numDecimals, - }); - } -} diff --git a/src/tokenTransferBuilders.spec.ts b/src/tokenTransferBuilders.spec.ts index abddcb375..e3fd02add 100644 --- a/src/tokenTransferBuilders.spec.ts +++ b/src/tokenTransferBuilders.spec.ts @@ -1,6 +1,6 @@ import { assert } from "chai"; import { Address } from "./address"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { ESDTNFTTransferPayloadBuilder, ESDTTransferPayloadBuilder, diff --git a/src/tokenTransferBuilders.ts b/src/tokenTransferBuilders.ts index edc476416..1c6f70097 100644 --- a/src/tokenTransferBuilders.ts +++ b/src/tokenTransferBuilders.ts @@ -2,7 +2,7 @@ import { Address } from "./address"; import { IAddress, ITokenTransfer } from "./interface"; import { ArgSerializer } from "./smartcontracts/argSerializer"; import { AddressValue, BigUIntValue, BytesValue, TypedValue, U16Value, U64Value } from "./smartcontracts/typesystem"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { TransactionPayload } from "./transactionPayload"; /** diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index 093417651..f3214b114 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; -import { Token, TokenComputer } from "./tokens"; +import { Token, TokenComputer, TokenTransfer } from "./tokens"; -describe("test token computer", async () => { +describe("test tokens and token computer", async () => { const tokenComputer = new TokenComputer(); it("should test if token is fungible", async () => { @@ -32,3 +32,67 @@ describe("test token computer", async () => { assert.equal(identifier, "FNG-123456"); }); }); + +describe("test token transfer (legacy)", () => { + it("should work with EGLD", () => { + assert.equal(TokenTransfer.egldFromAmount("1").toString(), "1000000000000000000"); + assert.equal(TokenTransfer.egldFromAmount("10").toString(), "10000000000000000000"); + assert.equal(TokenTransfer.egldFromAmount("100").toString(), "100000000000000000000"); + assert.equal(TokenTransfer.egldFromAmount("1000").toString(), "1000000000000000000000"); + assert.equal(TokenTransfer.egldFromAmount("0.1").toString(), "100000000000000000"); + assert.equal(TokenTransfer.egldFromAmount("0.123456789").toString(), "123456789000000000"); + assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789").toString(), "123456789123456789"); + assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789777").toString(), "123456789123456789"); + assert.equal(TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toString(), "123456789123456789"); + + assert.equal(TokenTransfer.egldFromAmount(0.1).toPrettyString(), "0.100000000000000000 EGLD"); + assert.equal(TokenTransfer.egldFromAmount(1).toPrettyString(), "1.000000000000000000 EGLD"); + assert.equal(TokenTransfer.egldFromAmount(10).toPrettyString(), "10.000000000000000000 EGLD"); + assert.equal(TokenTransfer.egldFromAmount(100).toPrettyString(), "100.000000000000000000 EGLD"); + assert.equal(TokenTransfer.egldFromAmount(1000).toPrettyString(), "1000.000000000000000000 EGLD"); + assert.equal(TokenTransfer.egldFromAmount("0.123456789").toPrettyString(), "0.123456789000000000 EGLD"); + assert.equal( + TokenTransfer.egldFromAmount("0.123456789123456789777777888888").toPrettyString(), + "0.123456789123456789 EGLD", + ); + + assert.equal(TokenTransfer.egldFromBigInteger("1").toString(), "1"); + assert.equal(TokenTransfer.egldFromBigInteger("1").toPrettyString(), "0.000000000000000001 EGLD"); + assert.isTrue(TokenTransfer.egldFromAmount("1").isEgld()); + }); + + it("should work with USDC (legacy)", () => { + const identifier = "USDC-c76f1f"; + const numDecimals = 6; + + assert.equal(TokenTransfer.fungibleFromAmount(identifier, "1", numDecimals).toString(), "1000000"); + assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.1", numDecimals).toString(), "100000"); + assert.equal(TokenTransfer.fungibleFromAmount(identifier, "0.123456789", numDecimals).toString(), "123456"); + assert.equal(TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toString(), "1000000"); + assert.equal( + TokenTransfer.fungibleFromBigInteger(identifier, "1000000", numDecimals).toPrettyString(), + "1.000000 USDC-c76f1f", + ); + }); + + it("should work with MetaESDT (legacy)", () => { + const identifier = "MEXFARML-28d646"; + const numDecimals = 18; + const nonce = 12345678; + const transfer = TokenTransfer.metaEsdtFromAmount(identifier, nonce, "0.1", numDecimals); + + assert.equal(transfer.tokenIdentifier, identifier); + assert.equal(transfer.nonce, nonce); + assert.equal(transfer.toString(), "100000000000000000"); + }); + + it("should work with NFTs (legacy)", () => { + const identifier = "TEST-38f249"; + const nonce = 1; + const transfer = TokenTransfer.nonFungible(identifier, nonce); + + assert.equal(transfer.tokenIdentifier, identifier); + assert.equal(transfer.nonce, nonce); + assert.equal(transfer.toPrettyString(), "1 TEST-38f249"); + }); +}); diff --git a/src/tokens.ts b/src/tokens.ts index d3bab272d..d1195c3f7 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -1,4 +1,20 @@ -import { ErrInvalidTokenIdentifier } from "./errors"; +import BigNumber from "bignumber.js"; +import { ErrInvalidArgument, ErrInvalidTokenIdentifier } from "./errors"; + +// Legacy constants: +const EGLDTokenIdentifier = "EGLD"; +const EGLDNumDecimals = 18; + +// Legacy configuration. +// Note: this will actually set the default rounding mode for all BigNumber objects in the environment (in the application / dApp). +BigNumber.set({ ROUNDING_MODE: 1 }); + +interface ILegacyTokenTransferOptions { + tokenIdentifier: string; + nonce: number; + amountAsBigInteger: BigNumber.Value; + numDecimals?: number; +} export class Token { readonly identifier: string; @@ -10,13 +26,192 @@ export class Token { } } -export class NextTokenTransfer { +export class TokenTransfer { readonly token: Token; readonly amount: bigint; - constructor(options: { token: Token; amount: bigint }) { - this.token = options.token; - this.amount = options.amount; + /** + * Legacy field. Use "token.identifier" instead. + */ + readonly tokenIdentifier: string; + + /** + * Legacy field. Use "token.nonce" instead. + */ + readonly nonce: number; + + /** + * Legacy field. Use "amount" instead. + */ + readonly amountAsBigInteger: BigNumber; + + /** + * Legacy field. The number of decimals is not a concern of "sdk-core". + * For formatting and parsing amounts, use "sdk-dapp" or "bignumber.js" directly. + */ + readonly numDecimals: number; + + constructor(options: { token: Token; amount: bigint } | ILegacyTokenTransferOptions) { + if (this.isLegacyTokenTransferOptions(options)) { + const amount = new BigNumber(options.amountAsBigInteger); + if (!amount.isInteger() || amount.isNegative()) { + throw new ErrInvalidArgument(`bad amountAsBigInteger: ${options.amountAsBigInteger}`); + } + + this.tokenIdentifier = options.tokenIdentifier; + this.nonce = options.nonce; + this.amountAsBigInteger = amount; + this.numDecimals = options.numDecimals || 0; + + this.token = new Token({ + identifier: options.tokenIdentifier, + nonce: BigInt(options.nonce), + }); + + this.amount = BigInt(this.amountAsBigInteger.toFixed(0)); + } else { + this.token = options.token; + this.amount = options.amount; + + this.tokenIdentifier = options.token.identifier; + this.nonce = Number(options.token.nonce); + this.amountAsBigInteger = new BigNumber(this.amount.toString()); + this.numDecimals = 0; + } + } + + private isLegacyTokenTransferOptions(options: any): options is ILegacyTokenTransferOptions { + return options.tokenIdentifier !== undefined; + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static egldFromAmount(amount: BigNumber.Value) { + const amountAsBigInteger = new BigNumber(amount).shiftedBy(EGLDNumDecimals).decimalPlaces(0); + return this.egldFromBigInteger(amountAsBigInteger); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static egldFromBigInteger(amountAsBigInteger: BigNumber.Value) { + return new TokenTransfer({ + tokenIdentifier: EGLDTokenIdentifier, + nonce: 0, + amountAsBigInteger, + numDecimals: EGLDNumDecimals, + }); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static fungibleFromAmount(tokenIdentifier: string, amount: BigNumber.Value, numDecimals: number) { + const amountAsBigInteger = new BigNumber(amount).shiftedBy(numDecimals).decimalPlaces(0); + return this.fungibleFromBigInteger(tokenIdentifier, amountAsBigInteger, numDecimals); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static fungibleFromBigInteger( + tokenIdentifier: string, + amountAsBigInteger: BigNumber.Value, + numDecimals: number = 0, + ) { + return new TokenTransfer({ + tokenIdentifier, + nonce: 0, + amountAsBigInteger, + numDecimals, + }); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static nonFungible(tokenIdentifier: string, nonce: number) { + return new TokenTransfer({ + tokenIdentifier, + nonce, + amountAsBigInteger: 1, + numDecimals: 0, + }); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static semiFungible(tokenIdentifier: string, nonce: number, quantity: number) { + return new TokenTransfer({ + tokenIdentifier, + nonce, + amountAsBigInteger: quantity, + numDecimals: 0, + }); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static metaEsdtFromAmount(tokenIdentifier: string, nonce: number, amount: BigNumber.Value, numDecimals: number) { + const amountAsBigInteger = new BigNumber(amount).shiftedBy(numDecimals).decimalPlaces(0); + return this.metaEsdtFromBigInteger(tokenIdentifier, nonce, amountAsBigInteger, numDecimals); + } + + /** + * Legacy function. Use the constructor instead: new TokenTransfer({ token, amount }); + */ + static metaEsdtFromBigInteger( + tokenIdentifier: string, + nonce: number, + amountAsBigInteger: BigNumber.Value, + numDecimals = 0, + ) { + return new TokenTransfer({ + tokenIdentifier, + nonce, + amountAsBigInteger, + numDecimals, + }); + } + + toString() { + return this.amount.toString(); + } + + /** + * Legacy function. Use the "amount" field instead. + */ + valueOf(): BigNumber { + return new BigNumber(this.amount.toString()); + } + + /** + * Legacy function. For formatting and parsing amounts, use "sdk-dapp" or "bignumber.js" directly. + */ + toPrettyString(): string { + return `${this.toAmount()} ${this.tokenIdentifier}`; + } + + private toAmount(): string { + return this.amountAsBigInteger.shiftedBy(-this.numDecimals).toFixed(this.numDecimals); + } + + /** + * Legacy function. Within your code, don't mix native values (EGLD) and custom (ESDT) tokens. + * See "TransferTransactionsFactory.createTransactionForNativeTokenTransfer()" vs. "TransferTransactionsFactory.createTransactionForESDTTokenTransfer()". + */ + isEgld(): boolean { + return this.token.identifier == EGLDTokenIdentifier; + } + + /** + * Legacy function. Use "TokenComputer.isFungible(token)" instead. + */ + isFungible(): boolean { + return this.token.nonce == 0n; } } @@ -99,3 +294,17 @@ export class TokenComputer { function decodeUnsignedNumber(arg: Buffer): number { return arg.readUIntBE(0, arg.length); } + +/** + * @deprecated use {@link TokenTransfer} instead. + */ +export class TokenPayment extends TokenTransfer { + constructor(tokenIdentifier: string, nonce: number, amountAsBigInteger: BigNumber.Value, numDecimals: number) { + super({ + tokenIdentifier, + nonce, + amountAsBigInteger, + numDecimals, + }); + } +} diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index d7aa0c561..502d6be03 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -3,7 +3,7 @@ import { assert } from "chai"; import { Logger } from "./logger"; import { loadTestWallets, TestWallet } from "./testutils"; import { createLocalnetProvider } from "./testutils/networkProviders"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; import { TransactionWatcher } from "./transactionWatcher"; diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 74a281512..37679de7f 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -5,7 +5,7 @@ import { MIN_TRANSACTION_VERSION_THAT_SUPPORTS_OPTIONS } from "./constants"; import { TransactionOptions, TransactionVersion } from "./networkParams"; import { ProtoSerializer } from "./proto"; import { TestWallet, loadTestWallets } from "./testutils"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionComputer } from "./transactionComputer"; import { TransactionPayload } from "./transactionPayload"; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index cc301787b..f7f440f6d 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -6,7 +6,7 @@ import { U32Value } from "../smartcontracts"; import { Code } from "../smartcontracts/code"; import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; import { loadAbiRegistry, loadContractCode } from "../testutils/utils"; -import { NextTokenTransfer, Token, TokenComputer } from "../tokens"; +import { Token, TokenComputer, TokenTransfer } from "../tokens"; import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; @@ -152,7 +152,7 @@ describe("test smart contract transactions factory", function () { const gasLimit = 6000000n; const args = [new U32Value(7)]; const token = new Token({ identifier: "FOO-6ce17b", nonce: 0n }); - const transfer = new NextTokenTransfer({ token, amount: 10n }); + const transfer = new TokenTransfer({ token, amount: 10n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -189,9 +189,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const fooToken = new Token({ identifier: "FOO-6ce17b", nonce: 0n }); - const fooTransfer = new NextTokenTransfer({ token: fooToken, amount: 10n }); + const fooTransfer = new TokenTransfer({ token: fooToken, amount: 10n }); const barToken = new Token({ identifier: "BAR-5bc08f", nonce: 0n }); - const barTransfer = new NextTokenTransfer({ token: barToken, amount: 3140n }); + const barTransfer = new TokenTransfer({ token: barToken, amount: 3140n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -235,7 +235,7 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const token = new Token({ identifier: "NFT-123456", nonce: 1n }); - const transfer = new NextTokenTransfer({ token, amount: 1n }); + const transfer = new TokenTransfer({ token, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, @@ -280,9 +280,9 @@ describe("test smart contract transactions factory", function () { const args = [new U32Value(7)]; const firstToken = new Token({ identifier: "NFT-123456", nonce: 1n }); - const firstTransfer = new NextTokenTransfer({ token: firstToken, amount: 1n }); + const firstTransfer = new TokenTransfer({ token: firstToken, amount: 1n }); const secondToken = new Token({ identifier: "NFT-123456", nonce: 42n }); - const secondTransfer = new NextTokenTransfer({ token: secondToken, amount: 1n }); + const secondTransfer = new TokenTransfer({ token: secondToken, amount: 1n }); const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index c2e4efbd7..6f95273be 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -4,7 +4,7 @@ import { Err, ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; -import { NextTokenTransfer, Token } from "../tokens"; +import { Token, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; @@ -82,7 +82,7 @@ export class SmartContractTransactionsFactory { gasLimit: bigint; args?: any[]; nativeTransferAmount?: bigint; - tokenTransfers?: NextTokenTransfer[]; + tokenTransfers?: TokenTransfer[]; }): Transaction { const args = options.args || []; const tokenTransfer = options.tokenTransfers || []; diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 593f92759..fbbf07f6a 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,5 +1,5 @@ import { IAddress } from "../interface"; -import { NextTokenTransfer, TokenComputer } from "../tokens"; +import { TokenComputer, TokenTransfer } from "../tokens"; import { addressToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { @@ -9,13 +9,13 @@ export class TokenTransfersDataBuilder { this.tokenComputer = new TokenComputer(); } - buildArgsForESDTTransfer(transfer: NextTokenTransfer): string[] { + buildArgsForESDTTransfer(transfer: TokenTransfer): string[] { let args = ["ESDTTransfer"]; args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); return args; } - buildArgsForSingleESDTNFTTransfer(transfer: NextTokenTransfer, receiver: IAddress) { + buildArgsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { let args = ["ESDTNFTTransfer"]; const token = transfer.token; @@ -32,7 +32,7 @@ export class TokenTransfersDataBuilder { return args; } - buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: NextTokenTransfer[]) { + buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index 93f7002f8..ab7f676eb 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { Address } from "../address"; import { ErrBadUsage } from "../errors"; -import { NextTokenTransfer, Token, TokenComputer } from "../tokens"; +import { Token, TokenComputer, TokenTransfer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transferTransactionsFactory"; @@ -62,7 +62,7 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for esdt transfer", async () => { const fooToken = new Token({ identifier: "FOO-123456", nonce: 0n }); - const transfer = new NextTokenTransfer({ token: fooToken, amount: 1000000n }); + const transfer = new TokenTransfer({ token: fooToken, amount: 1000000n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -79,7 +79,7 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for nft transfer", async () => { const nft = new Token({ identifier: "NFT-123456", nonce: 10n }); - const transfer = new NextTokenTransfer({ token: nft, amount: 1n }); + const transfer = new TokenTransfer({ token: nft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, @@ -99,10 +99,10 @@ describe("test transfer transcations factory", function () { it("should create 'Transaction' for multiple nft transfers", async () => { const firstNft = new Token({ identifier: "NFT-123456", nonce: 10n }); - const firstTransfer = new NextTokenTransfer({ token: firstNft, amount: 1n }); + const firstTransfer = new TokenTransfer({ token: firstNft, amount: 1n }); const secondNft = new Token({ identifier: "TEST-987654", nonce: 1n }); - const secondTransfer = new NextTokenTransfer({ token: secondNft, amount: 1n }); + const secondTransfer = new TokenTransfer({ token: secondNft, amount: 1n }); const transaction = transferFactory.createTransactionForESDTTokenTransfer({ sender: alice, diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 5d8973461..f0cc7d93e 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -18,7 +18,7 @@ import { U16Value, U64Value, } from "../smartcontracts"; -import { NextTokenTransfer, Token } from "../tokens"; +import { Token, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { TransactionPayload } from "../transactionPayload"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; @@ -124,7 +124,7 @@ export class TransferTransactionsFactory { createTransactionForESDTTokenTransfer(options: { sender: IAddress; receiver: IAddress; - tokenTransfers: NextTokenTransfer[]; + tokenTransfers: TokenTransfer[]; }): Transaction { this.ensureMembersAreDefined(); @@ -339,7 +339,7 @@ export class TransferTransactionsFactory { private createSingleESDTTransferTransaction(options: { sender: IAddress; receiver: IAddress; - tokenTransfers: NextTokenTransfer[]; + tokenTransfers: TokenTransfer[]; }): Transaction { this.ensureMembersAreDefined(); diff --git a/src/transferTransactionsFactory.spec.ts b/src/transferTransactionsFactory.spec.ts index abc64867e..66b91fe16 100644 --- a/src/transferTransactionsFactory.spec.ts +++ b/src/transferTransactionsFactory.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { Address } from "./address"; import { GasEstimator } from "./gasEstimator"; -import { TokenTransfer } from "./tokenTransfer"; +import { TokenTransfer } from "./tokens"; import { TransactionPayload } from "./transactionPayload"; import { TransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; From 9773a3a4f1f0bd57ef67fb5e39305fca42f1ce8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sun, 24 Mar 2024 23:46:13 +0200 Subject: [PATCH 223/275] Fix after self review. --- src/tokens.ts | 4 ++++ src/transactionsOutcomeParsers/index.ts | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tokens.ts b/src/tokens.ts index d1195c3f7..07e082b2a 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -53,6 +53,7 @@ export class TokenTransfer { constructor(options: { token: Token; amount: bigint } | ILegacyTokenTransferOptions) { if (this.isLegacyTokenTransferOptions(options)) { + // Handle legacy fields. const amount = new BigNumber(options.amountAsBigInteger); if (!amount.isInteger() || amount.isNegative()) { throw new ErrInvalidArgument(`bad amountAsBigInteger: ${options.amountAsBigInteger}`); @@ -63,6 +64,7 @@ export class TokenTransfer { this.amountAsBigInteger = amount; this.numDecimals = options.numDecimals || 0; + // Handle new fields. this.token = new Token({ identifier: options.tokenIdentifier, nonce: BigInt(options.nonce), @@ -70,9 +72,11 @@ export class TokenTransfer { this.amount = BigInt(this.amountAsBigInteger.toFixed(0)); } else { + // Handle new fields. this.token = options.token; this.amount = options.amount; + // Handle legacy fields. this.tokenIdentifier = options.token.identifier; this.nonce = Number(options.token.nonce); this.amountAsBigInteger = new BigNumber(this.amount.toString()); diff --git a/src/transactionsOutcomeParsers/index.ts b/src/transactionsOutcomeParsers/index.ts index e95e9836b..b50f8ba9c 100644 --- a/src/transactionsOutcomeParsers/index.ts +++ b/src/transactionsOutcomeParsers/index.ts @@ -1,3 +1,5 @@ +export * from "./delegationTransactionsOutcomeParser"; export * from "./resources"; +export * from "./smartContractTransactionsOutcomeParser"; export * from "./tokenManagementTransactionsOutcomeParser"; -export * from "./delegationTransactionsOutcomeParser"; +export * from "./transactionEventsParser"; From fd3d90b836998f4176fbb4070188ed0b328c44ae Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 25 Mar 2024 10:15:10 +0200 Subject: [PATCH 224/275] instantiate version and options using Number --- src/transaction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transaction.ts b/src/transaction.ts index a4417e661..cd687ae9e 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -133,8 +133,8 @@ export class Transaction { this.gasLimit = BigInt(options.gasLimit.valueOf()); this.data = options.data?.valueOf() || new Uint8Array(); this.chainID = options.chainID.valueOf(); - this.version = options.version?.valueOf() || TRANSACTION_VERSION_DEFAULT; - this.options = options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT; + this.version = Number(options.version?.valueOf() || TRANSACTION_VERSION_DEFAULT); + this.options = Number(options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT); this.guardian = options.guardian ? this.addressAsBech32(options.guardian) : ""; this.signature = options.signature || Buffer.from([]); From a87c47f6ac4d77c0860c6083e422fa907513d25a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 10:20:04 +0200 Subject: [PATCH 225/275] Minor refactoring. --- .../transactionEventsParser.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts index 6887b11af..326d65cfe 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -7,38 +7,38 @@ interface IAbi { } export class TransactionEventsParser { - private readonly abi: IAbi; private readonly legacyResultsParser: ResultsParser; + private readonly abi: IAbi; + private readonly firstTopicIsIdentifier: boolean; - constructor(options: { abi: IAbi }) { - this.abi = options.abi; + constructor(options: { abi: IAbi; firstTopicIsIdentifier?: boolean }) { this.legacyResultsParser = new ResultsParser(); + this.abi = options.abi; + + // By default, we consider that the first topic is the event identifier. + // This is true for log entries emitted by smart contracts: + // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L283 + this.firstTopicIsIdentifier = + options.firstTopicIsIdentifier === undefined ? true : options.firstTopicIsIdentifier; } - parseEvents(options: { events: TransactionEvent[]; firstTopicIsIdentifier?: boolean }): any[] { - const firstTopicIsIdentifier = options.firstTopicIsIdentifier; + parseEvents(options: { events: TransactionEvent[] }): any[] { const results = []; for (const event of options.events) { - const parsedEvent = this.parseEvent({ event, firstTopicIsIdentifier }); + const parsedEvent = this.parseEvent({ event }); results.push(parsedEvent); } return results; } - parseEvent(options: { event: TransactionEvent; firstTopicIsIdentifier?: boolean }): any { - // By default, we consider that the first topic is the event identifier. - // This is true for log entries emitted by smart contracts: - // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L283 - const firstTopicIsIdentifier = - options.firstTopicIsIdentifier === undefined ? true : options.firstTopicIsIdentifier; - + parseEvent(options: { event: TransactionEvent }): any { const topics = options.event.topics.map((topic) => Buffer.from(topic)); const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); const eventDefinition = this.abi.getEvent(options.event.identifier); - if (firstTopicIsIdentifier) { + if (this.firstTopicIsIdentifier) { // Discard the first topic (not useful). topics.shift(); } From 17b3cc1e7dd4b63b3c8ab1d5ab4fe7817aa5abd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 11:43:05 +0200 Subject: [PATCH 226/275] Fix after review. --- src/converters/transactionsConverter.ts | 2 +- src/smartcontracts/resultsParser.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index e095063f1..046740716 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -120,7 +120,7 @@ export class TransactionsConverter { const legacyData = eventOnNetwork.dataPayload?.valueOf() || Buffer.from([]); const dataItems = eventOnNetwork.additionalData?.map((data) => Buffer.from(data.valueOf())) || []; - if (dataItems.length == 0) { + if (dataItems.length === 0) { if (legacyData.length) { dataItems.push(Buffer.from(legacyData)); } diff --git a/src/smartcontracts/resultsParser.ts b/src/smartcontracts/resultsParser.ts index 3519528ca..b0323c9b6 100644 --- a/src/smartcontracts/resultsParser.ts +++ b/src/smartcontracts/resultsParser.ts @@ -381,7 +381,7 @@ export class ResultsParser { const legacyData = transactionEvent.dataPayload?.valueOf() || Buffer.from([]); const dataItems = transactionEvent.additionalData?.map((data) => Buffer.from(data.valueOf())) || []; - if (dataItems.length == 0) { + if (dataItems.length === 0) { if (legacyData.length) { dataItems.push(Buffer.from(legacyData)); } From 650d98918ebe9d2ecb1f865f2fac4a86ac635215 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 25 Mar 2024 12:38:19 +0200 Subject: [PATCH 227/275] remove check for hash signing --- src/transaction.spec.ts | 4 +--- src/transactionComputer.ts | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 74a281512..38b4ecb45 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -620,9 +620,7 @@ describe("test transaction", async () => { options: 1, }); - transaction.signature = await wallets.alice.signer.sign( - Buffer.from(transactionComputer.computeBytesForSigning(transaction)), - ); + transaction.signature = await wallets.alice.signer.sign(transactionComputer.computeHashForSigning(transaction)); assert.equal( "f0c81f2393b1ec5972c813f817bae8daa00ade91c6f75ea604ab6a4d2797aca4378d783023ff98f1a02717fe4f24240cdfba0b674ee9abb18042203d713bc70a", diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 359712f77..31707aed1 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -50,10 +50,6 @@ export class TransactionComputer { computeBytesForSigning(transaction: ITransaction): Uint8Array { this.ensureValidTransactionFields(transaction); - if (transaction.version >= 2 && this.hasOptionsSetForHashSigning(transaction)) { - return this.computeHashForSigning(transaction); - } - const plainTransaction = this.toPlainObjectForSigning(transaction); const serialized = JSON.stringify(plainTransaction); return new Uint8Array(Buffer.from(serialized)); From 0f26e7b12774f00c2edd2f749baaa890fcee9bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 13:05:34 +0200 Subject: [PATCH 228/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c8e294b00..19074dde8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.8", + "version": "13.0.0-beta.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.8", + "version": "13.0.0-beta.9", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index ab363b343..a07213e9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.8", + "version": "13.0.0-beta.9", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From d3665d3d87cdb8adb9b214f2e05e1a02835ebb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 13:36:40 +0200 Subject: [PATCH 229/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19074dde8..8320ae500 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.9", + "version": "13.0.0-beta.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.9", + "version": "13.0.0-beta.10", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index a07213e9a..8e77858e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.9", + "version": "13.0.0-beta.10", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 4dd272760096f8369a6b44952cfd96f5f41b70fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 14:42:16 +0200 Subject: [PATCH 230/275] Fix exports. --- package-lock.json | 4 ++-- package.json | 2 +- src/index.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8320ae500..010daa4e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.10", + "version": "13.0.0-beta.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.10", + "version": "13.0.0-beta.11", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 8e77858e8..c775bedbd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.10", + "version": "13.0.0-beta.11", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/index.ts b/src/index.ts index 0ce32cab4..385c250a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,4 +19,6 @@ export * from "./transaction"; export * from "./transactionComputer"; export * from "./transactionPayload"; export * from "./transactionWatcher"; +export * from "./transactionsFactories"; +export * from "./transactionsOutcomeParsers"; export * from "./utils"; From 4c738625ba670de917db20c22bc3b6c89267a026 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 25 Mar 2024 15:19:55 +0200 Subject: [PATCH 231/275] fix localnet tests --- src/transaction.local.net.spec.ts | 50 ++++++++++++++++++------------- src/transactionWatcher.ts | 4 ++- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 502d6be03..62c2860d6 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -23,18 +23,16 @@ describe("test transaction", function () { this.timeout(70000); let provider = createLocalnetProvider(); - let watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { - return await provider.getTransaction(hash, true); + let watcher = new TransactionWatcher( + { + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }, - }); + { timeoutMilliseconds: 100000 }, + ); let network = await provider.getNetworkConfig(); - await alice.sync(provider); - - await bob.sync(provider); - let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); - let transactionOne = new Transaction({ sender: alice.address, receiver: bob.address, @@ -51,6 +49,10 @@ describe("test transaction", function () { chainID: network.ChainID, }); + await alice.sync(provider); + await bob.sync(provider); + let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); + transactionOne.setNonce(alice.account.nonce); alice.account.incrementNonce(); transactionTwo.setNonce(alice.account.nonce); @@ -74,18 +76,17 @@ describe("test transaction", function () { this.timeout(70000); let provider = createLocalnetProvider(); - let watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { - return await provider.getTransaction(hash, true); + let watcher = new TransactionWatcher( + { + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }, - }); + { timeoutMilliseconds: 100000 }, + ); let network = await provider.getNetworkConfig(); - await alice.sync(provider); - await bob.sync(provider); - let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); - let transactionOne = new Transaction({ sender: alice.address, receiver: bob.address, @@ -94,6 +95,10 @@ describe("test transaction", function () { chainID: network.ChainID, }); + await alice.sync(provider); + await bob.sync(provider); + let initialBalanceOfBob = new BigNumber(bob.account.balance.toString()); + transactionOne.setNonce(alice.account.nonce); await signTransaction({ transaction: transactionOne, wallet: alice }); await provider.sendTransaction(transactionOne); @@ -144,11 +149,14 @@ describe("test transaction", function () { this.timeout(70000); const provider = createLocalnetProvider(); - const watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { - return await provider.getTransaction(hash, true); + const watcher = new TransactionWatcher( + { + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }, - }); + { timeoutMilliseconds: 100000 }, + ); const network = await provider.getNetworkConfig(); diff --git a/src/transactionWatcher.ts b/src/transactionWatcher.ts index 7acd56a3f..ae077b38b 100644 --- a/src/transactionWatcher.ts +++ b/src/transactionWatcher.ts @@ -154,7 +154,9 @@ export class TransactionWatcher { typeof transactionOrTxHash === "string" ? transactionOrTxHash : transactionOrTxHash.getHash().hex(); if (hash.length !== HEX_TRANSACTION_HASH_LENGTH) { - throw new Err("Invalid transaction hash length. The length of a hex encoded hash should be 64."); + throw new Err( + `Invalid transaction hash length. The length of a hex encoded hash should be ${HEX_TRANSACTION_HASH_LENGTH}.`, + ); } return hash; From 386fda17c9a5930221731b1f002ffcc172e9ef6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 20:00:47 +0200 Subject: [PATCH 232/275] Fix regressions in Interaction (legacy). --- src/interface.ts | 3 + src/smartcontracts/interaction.spec.ts | 41 +++- src/smartcontracts/interaction.ts | 181 ++++-------------- .../smartContractTransactionsFactory.spec.ts | 2 +- .../tokenTransfersDataBuilder.ts | 14 +- src/utils.codec.ts | 5 + 6 files changed, 95 insertions(+), 151 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index fab671c24..97c86a54f 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -73,6 +73,9 @@ export interface ITransactionPayload { valueOf(): Buffer; } +/** + * Legacy interface. The class `TokenTransfer` can be used instead, where necessary. + */ export interface ITokenTransfer { readonly tokenIdentifier: string; readonly nonce: number; diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index b005ddf10..642cb1e30 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -10,7 +10,8 @@ import { TestWallet } from "../testutils"; import { ContractController } from "../testutils/contractController"; -import { TokenTransfer } from "../tokens"; +import { Token, TokenTransfer } from "../tokens"; +import { Transaction } from "../transaction"; import { ContractFunction } from "./function"; import { Interaction } from "./interaction"; import { ReturnCode } from "./returnCode"; @@ -148,7 +149,36 @@ describe("test smart contract interactor", function () { assert.equal(transaction.getSender().bech32(), alice.bech32()); assert.equal(transaction.getReceiver().bech32(), alice.bech32()); - assert.equal(transaction.getData().toString(), `MultiESDTNFTTransfer@${hexContractAddress}@02@${hexStrămoși}@01@01@${hexStrămoși}@2a@01@${hexDummyFunction}`); + }); + + it("should create transaction, with ABI, with transfer & execute", async function () { + const abiRegistry = await loadAbiRegistry("src/testdata/answer.abi.json"); + const contract = new SmartContract({ address: dummyAddress, abi: abiRegistry }); + const alice = new Address("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const token = new Token({ identifier: "FOO-abcdef", nonce: 0n }); + + const transaction = contract.methods + .getUltimateAnswer() + .withChainID("T") + .withSender(alice) + .withGasLimit(543210) + .withSingleESDTTransfer(new TokenTransfer({ token, amount: 100n })) + .withNonce(42) + .buildTransaction(); + + assert.deepEqual( + transaction, + new Transaction({ + chainID: "T", + sender: alice.toBech32(), + receiver: dummyAddress.toBech32(), + data: Buffer.from("ESDTTransfer@464f4f2d616263646566@64@676574556c74696d617465416e73776572"), + gasLimit: 543210n, + value: 0n, + version: 1, + nonce: 42n, + }), + ); }); it("should interact with 'answer'", async function () { @@ -158,10 +188,9 @@ describe("test smart contract interactor", function () { let contract = new SmartContract({ address: dummyAddress, abi: abiRegistry }); let controller = new ContractController(provider); - let interaction = contract.methods - .getUltimateAnswer() - .withGasLimit(543210) - .withChainID("T"); + let interaction = ( + contract.methods.getUltimateAnswer().withGasLimit(543210).withChainID("T").withVersion(2) + ); assert.equal(contract.getAddress(), dummyAddress); assert.deepEqual(interaction.getFunction(), new ContractFunction("getUltimateAnswer")); diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index 9cf2b7b76..d1d10894d 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -1,14 +1,15 @@ import { Account } from "../account"; import { Address } from "../address"; import { Compatibility } from "../compatibility"; -import { ESDTNFT_TRANSFER_FUNCTION_NAME, ESDT_TRANSFER_FUNCTION_NAME, MULTI_ESDTNFT_TRANSFER_FUNCTION_NAME } from "../constants"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, ITokenTransfer, ITransactionValue } from "../interface"; +import { TokenComputer, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; +import { SmartContractTransactionsFactory, TransactionsFactoryConfig } from "../transactionsFactories"; import { ContractFunction } from "./function"; import { InteractionChecker } from "./interactionChecker"; import { CallArguments } from "./interface"; import { Query } from "./query"; -import { AddressValue, BigUIntValue, BytesValue, EndpointDefinition, TypedValue, U64Value, U8Value } from "./typesystem"; +import { EndpointDefinition, TypedValue } from "./typesystem"; /** * Internal interface: the smart contract, as seen from the perspective of an {@link Interaction}. @@ -20,8 +21,10 @@ interface ISmartContractWithinInteraction { } /** + * Legacy component. Use "SmartContractTransactionsFactory" (for transactions) or "SmartContractQueriesController" (for queries), instead. + * * Interactions can be seen as mutable transaction & query builders. - * + * * Aside from building transactions and queries, the interactors are also responsible for interpreting * the execution outcome for the objects they've built. */ @@ -39,10 +42,11 @@ export class Interaction { private explicitReceiver?: IAddress; private sender: IAddress = Address.empty(); - private isWithSingleESDTTransfer: boolean = false; - private isWithSingleESDTNFTTransfer: boolean = false; - private isWithMultiESDTNFTTransfer: boolean = false; - private tokenTransfers: TokenTransfersWithinInteraction; + // When using the Interaction API, we use the legacy transaction version by default, + // in order to have as little impact as possible on a quick upgrade from v12 to v13. + private version: number = 1; + + private tokenTransfers: TokenTransfer[]; constructor( contract: ISmartContractWithinInteraction, @@ -52,7 +56,7 @@ export class Interaction { this.contract = contract; this.function = func; this.args = args; - this.tokenTransfers = new TokenTransfersWithinInteraction([], this); + this.tokenTransfers = []; } getContractAddress(): IAddress { @@ -76,7 +80,7 @@ export class Interaction { } getTokenTransfers(): ITokenTransfer[] { - return this.tokenTransfers.getTransfers(); + return this.tokenTransfers; } getGasLimit(): IGasLimit { @@ -90,39 +94,29 @@ export class Interaction { buildTransaction(): Transaction { Compatibility.guardAddressIsSetAndNonZero(this.sender, "'sender' of interaction", "use interaction.withSender()"); - let receiver = this.explicitReceiver || this.contract.getAddress(); - let func: ContractFunction = this.function; - let args = this.args; - - if (this.isWithSingleESDTTransfer) { - func = new ContractFunction(ESDT_TRANSFER_FUNCTION_NAME); - args = this.tokenTransfers.buildArgsForSingleESDTTransfer(); - } else if (this.isWithSingleESDTNFTTransfer) { - // For NFT, SFT and MetaESDT, transaction.sender == transaction.receiver. - receiver = this.sender; - func = new ContractFunction(ESDTNFT_TRANSFER_FUNCTION_NAME); - args = this.tokenTransfers.buildArgsForSingleESDTNFTTransfer(); - } else if (this.isWithMultiESDTNFTTransfer) { - // For NFT, SFT and MetaESDT, transaction.sender == transaction.receiver. - receiver = this.sender; - func = new ContractFunction(MULTI_ESDTNFT_TRANSFER_FUNCTION_NAME); - args = this.tokenTransfers.buildArgsForMultiESDTNFTTransfer(); - } + const factoryConfig = new TransactionsFactoryConfig({ chainID: this.chainID.valueOf() }); + const factory = new SmartContractTransactionsFactory({ + config: factoryConfig, + tokenComputer: new TokenComputer(), + }); - let transaction = this.contract.call({ - func: func, - // GasLimit will be set using "withGasLimit()". - gasLimit: this.gasLimit, - gasPrice: this.gasPrice, - args: args, - // Value will be set using "withValue()". - value: this.value, - receiver: receiver, - chainID: this.chainID, - caller: this.sender + const transaction = factory.createTransactionForExecute({ + sender: this.sender, + contract: this.contract.getAddress(), + functionName: this.function.valueOf(), + gasLimit: BigInt(this.gasLimit.valueOf()), + args: this.args, + nativeTransferAmount: BigInt(this.value.toString()), + tokenTransfers: this.tokenTransfers, }); - transaction.setNonce(this.nonce); + transaction.chainID = this.chainID.valueOf(); + transaction.nonce = BigInt(this.nonce.valueOf()); + transaction.version = this.version; + + if (this.gasPrice) { + transaction.gasPrice = BigInt(this.gasPrice.valueOf()); + } return transaction; } @@ -134,7 +128,7 @@ export class Interaction { args: this.args, // Value will be set using "withValue()". value: this.value, - caller: this.querent + caller: this.querent, }); } @@ -144,24 +138,17 @@ export class Interaction { } withSingleESDTTransfer(transfer: ITokenTransfer): Interaction { - this.isWithSingleESDTTransfer = true; - this.tokenTransfers = new TokenTransfersWithinInteraction([transfer], this); + this.tokenTransfers = [transfer].map((transfer) => new TokenTransfer(transfer)); return this; } - withSingleESDTNFTTransfer(transfer: ITokenTransfer): Interaction; - withSingleESDTNFTTransfer(transfer: ITokenTransfer): Interaction { - this.isWithSingleESDTNFTTransfer = true; - this.tokenTransfers = new TokenTransfersWithinInteraction([transfer], this); + this.tokenTransfers = [transfer].map((transfer) => new TokenTransfer(transfer)); return this; } - withMultiESDTNFTTransfer(transfers: ITokenTransfer[]): Interaction; - withMultiESDTNFTTransfer(transfers: ITokenTransfer[]): Interaction { - this.isWithMultiESDTNFTTransfer = true; - this.tokenTransfers = new TokenTransfersWithinInteraction(transfers, this); + this.tokenTransfers = transfers.map((transfer) => new TokenTransfer(transfer)); return this; } @@ -194,6 +181,11 @@ export class Interaction { return this; } + withVersion(version: number): Interaction { + this.version = version; + return this; + } + /** * Sets the "caller" field on contract queries. */ @@ -215,92 +207,3 @@ export class Interaction { return this; } } - -class TokenTransfersWithinInteraction { - private readonly transfers: ITokenTransfer[]; - private readonly interaction: Interaction; - - constructor(transfers: ITokenTransfer[], interaction: Interaction) { - this.transfers = transfers; - this.interaction = interaction; - } - - getTransfers() { - return this.transfers; - } - - buildArgsForSingleESDTTransfer(): TypedValue[] { - let singleTransfer = this.transfers[0]; - - return [ - this.getTypedTokenIdentifier(singleTransfer), - this.getTypedTokenQuantity(singleTransfer), - this.getTypedInteractionFunction(), - ...this.getInteractionArguments() - ]; - } - - buildArgsForSingleESDTNFTTransfer(): TypedValue[] { - let singleTransfer = this.transfers[0]; - - return [ - this.getTypedTokenIdentifier(singleTransfer), - this.getTypedTokenNonce(singleTransfer), - this.getTypedTokenQuantity(singleTransfer), - this.getTypedTokensReceiver(), - this.getTypedInteractionFunction(), - ...this.getInteractionArguments() - ]; - } - - buildArgsForMultiESDTNFTTransfer(): TypedValue[] { - let result: TypedValue[] = []; - - result.push(this.getTypedTokensReceiver()); - result.push(this.getTypedNumberOfTransfers()); - - for (const transfer of this.transfers) { - result.push(this.getTypedTokenIdentifier(transfer)); - result.push(this.getTypedTokenNonce(transfer)); - result.push(this.getTypedTokenQuantity(transfer)); - } - - result.push(this.getTypedInteractionFunction()); - result.push(...this.getInteractionArguments()); - - return result; - } - - private getTypedNumberOfTransfers(): TypedValue { - return new U8Value(this.transfers.length); - } - - private getTypedTokenIdentifier(transfer: ITokenTransfer): TypedValue { - // Important: for NFTs, this has to be the "collection" name, actually. - // We will reconsider adding the field "collection" on "Token" upon merging "ApiProvider" and "ProxyProvider". - return BytesValue.fromUTF8(transfer.tokenIdentifier); - } - - private getTypedTokenNonce(transfer: ITokenTransfer): TypedValue { - // The token nonce (creation nonce) - return new U64Value(transfer.nonce); - } - - private getTypedTokenQuantity(transfer: ITokenTransfer): TypedValue { - // For NFTs, this will be 1. - return new BigUIntValue(transfer.amountAsBigInteger); - } - - private getTypedTokensReceiver(): TypedValue { - // The actual receiver of the token(s): the contract - return new AddressValue(this.interaction.getContractAddress()); - } - - private getTypedInteractionFunction(): TypedValue { - return BytesValue.fromUTF8(this.interaction.getFunction().valueOf()) - } - - private getInteractionArguments(): TypedValue[] { - return this.interaction.getArguments(); - } -} diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index f7f440f6d..a0d5e16af 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -217,7 +217,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual( transaction.data, Buffer.from( - "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@00@0a@4241522d356263303866@00@0c44@616464@07", + "MultiESDTNFTTransfer@00000000000000000500ed8e25a94efa837aae0e593112cfbb01b448755069e1@02@464f4f2d366365313762@@0a@4241522d356263303866@@0c44@616464@07", ), ); diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index fbbf07f6a..c342b0cdd 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,6 +1,6 @@ import { IAddress } from "../interface"; import { TokenComputer, TokenTransfer } from "../tokens"; -import { addressToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; +import { addressToHex, numberToPaddedHex, numberToPaddedHexWithZeroAsEmptyString, utf8ToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { private tokenComputer: TokenComputer; @@ -11,7 +11,7 @@ export class TokenTransfersDataBuilder { buildArgsForESDTTransfer(transfer: TokenTransfer): string[] { let args = ["ESDTTransfer"]; - args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHex(transfer.amount)]); + args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHexWithZeroAsEmptyString(transfer.amount)]); return args; } @@ -24,8 +24,8 @@ export class TokenTransfersDataBuilder { args.push( ...[ utf8ToHex(identifier), - numberToPaddedHex(token.nonce), - numberToPaddedHex(transfer.amount), + numberToPaddedHexWithZeroAsEmptyString(token.nonce), + numberToPaddedHexWithZeroAsEmptyString(transfer.amount), addressToHex(receiver), ], ); @@ -38,7 +38,11 @@ export class TokenTransfersDataBuilder { for (let transfer of transfers) { const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); args.push( - ...[utf8ToHex(identifier), numberToPaddedHex(transfer.token.nonce), numberToPaddedHex(transfer.amount)], + ...[ + utf8ToHex(identifier), + numberToPaddedHexWithZeroAsEmptyString(transfer.token.nonce), + numberToPaddedHexWithZeroAsEmptyString(transfer.amount), + ], ); } diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 0e03b658b..51a88012c 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -16,6 +16,11 @@ export function numberToPaddedHex(value: bigint | number | BigNumber.Value) { return zeroPadStringIfOddLength(hex); } +export function numberToPaddedHexWithZeroAsEmptyString(value: bigint | number | BigNumber.Value) { + const paddedHex = numberToPaddedHex(value); + return paddedHex == "00" ? "" : paddedHex; +} + export function isPaddedHex(input: string) { input = input || ""; let decodedThenEncoded = Buffer.from(input, "hex").toString("hex"); From dfd288c61c1978ee99c4bb0525c809be8c581856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 20:10:02 +0200 Subject: [PATCH 233/275] Bump version. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 010daa4e8..f2bb62e5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.11", + "version": "13.0.0-beta.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.11", + "version": "13.0.0-beta.12", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index c775bedbd..9077eb6d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.11", + "version": "13.0.0-beta.12", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From aac81b419f39663731aa8220c4b218c195e0e4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 20:46:24 +0200 Subject: [PATCH 234/275] Undo change. --- src/smartcontracts/interaction.spec.ts | 4 ++-- src/smartcontracts/interaction.ts | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/smartcontracts/interaction.spec.ts b/src/smartcontracts/interaction.spec.ts index 642cb1e30..0d3d73297 100644 --- a/src/smartcontracts/interaction.spec.ts +++ b/src/smartcontracts/interaction.spec.ts @@ -175,7 +175,7 @@ describe("test smart contract interactor", function () { data: Buffer.from("ESDTTransfer@464f4f2d616263646566@64@676574556c74696d617465416e73776572"), gasLimit: 543210n, value: 0n, - version: 1, + version: 2, nonce: 42n, }), ); @@ -189,7 +189,7 @@ describe("test smart contract interactor", function () { let controller = new ContractController(provider); let interaction = ( - contract.methods.getUltimateAnswer().withGasLimit(543210).withChainID("T").withVersion(2) + contract.methods.getUltimateAnswer().withGasLimit(543210).withChainID("T") ); assert.equal(contract.getAddress(), dummyAddress); diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index d1d10894d..6eb1245fe 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -1,6 +1,7 @@ import { Account } from "../account"; import { Address } from "../address"; import { Compatibility } from "../compatibility"; +import { TRANSACTION_VERSION_DEFAULT } from "../constants"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, ITokenTransfer, ITransactionValue } from "../interface"; import { TokenComputer, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; @@ -41,10 +42,7 @@ export class Interaction { private querent: IAddress = Address.empty(); private explicitReceiver?: IAddress; private sender: IAddress = Address.empty(); - - // When using the Interaction API, we use the legacy transaction version by default, - // in order to have as little impact as possible on a quick upgrade from v12 to v13. - private version: number = 1; + private version: number = TRANSACTION_VERSION_DEFAULT; private tokenTransfers: TokenTransfer[]; From 51b9a7aaa5885fd06cbc93a406ecf87bb977bc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 20:51:01 +0200 Subject: [PATCH 235/275] Refactor / rename. --- .../smartContractTransactionsFactory.ts | 6 +++--- .../tokenTransfersDataBuilder.ts | 6 +++--- .../transferTransactionsFactory.ts | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 6f95273be..d7a9d6d78 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -100,13 +100,13 @@ export class SmartContractTransactionsFactory { const transfer = tokenTransfer[0]; if (this.tokenComputer.isFungible(transfer.token)) { - dataParts = this.dataArgsBuilder.buildArgsForESDTTransfer(transfer); + dataParts = this.dataArgsBuilder.buildDataPartsForESDTTransfer(transfer); } else { - dataParts = this.dataArgsBuilder.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + dataParts = this.dataArgsBuilder.buildDataPartsForSingleESDTNFTTransfer(transfer, receiver); receiver = options.sender; } } else if (numberOfTokens > 1) { - dataParts = this.dataArgsBuilder.buildArgsForMultiESDTNFTTransfer(receiver, tokenTransfer); + dataParts = this.dataArgsBuilder.buildDataPartsForMultiESDTNFTTransfer(receiver, tokenTransfer); receiver = options.sender; } diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index c342b0cdd..083695025 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -9,13 +9,13 @@ export class TokenTransfersDataBuilder { this.tokenComputer = new TokenComputer(); } - buildArgsForESDTTransfer(transfer: TokenTransfer): string[] { + buildDataPartsForESDTTransfer(transfer: TokenTransfer): string[] { let args = ["ESDTTransfer"]; args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHexWithZeroAsEmptyString(transfer.amount)]); return args; } - buildArgsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { + buildDataPartsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { let args = ["ESDTNFTTransfer"]; const token = transfer.token; @@ -32,7 +32,7 @@ export class TokenTransfersDataBuilder { return args; } - buildArgsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { + buildDataPartsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; for (let transfer of transfers) { diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index f0cc7d93e..a981fcd70 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -52,7 +52,7 @@ interface IGasEstimator { */ export class TransferTransactionsFactory { private readonly config?: IConfig; - private readonly dataArgsBuilder?: TokenTransfersDataBuilder; + private readonly tokenTransfersDataBuilder?: TokenTransfersDataBuilder; private readonly tokenComputer?: ITokenComputer; private readonly gasEstimator?: IGasEstimator; @@ -68,7 +68,7 @@ export class TransferTransactionsFactory { } else { this.config = options.config; this.tokenComputer = options.tokenComputer; - this.dataArgsBuilder = new TokenTransfersDataBuilder(); + this.tokenTransfersDataBuilder = new TokenTransfersDataBuilder(); } } @@ -91,7 +91,7 @@ export class TransferTransactionsFactory { throw new Err("'config' is not defined"); } - if (this.dataArgsBuilder === undefined) { + if (this.tokenTransfersDataBuilder === undefined) { throw new Err("`dataArgsBuilder is not defined`"); } @@ -138,7 +138,7 @@ export class TransferTransactionsFactory { return this.createSingleESDTTransferTransaction(options); } - const transferArgs = this.dataArgsBuilder!.buildArgsForMultiESDTNFTTransfer( + const dataParts = this.tokenTransfersDataBuilder!.buildDataPartsForMultiESDTNFTTransfer( options.receiver, options.tokenTransfers, ); @@ -151,7 +151,7 @@ export class TransferTransactionsFactory { config: this.config!, sender: options.sender, receiver: options.sender, - dataParts: transferArgs, + dataParts: dataParts, gasLimit: extraGasForTransfer, addDataMovementGas: true, }).build(); @@ -343,16 +343,16 @@ export class TransferTransactionsFactory { }): Transaction { this.ensureMembersAreDefined(); - let transferArgs: string[] = []; + let dataParts: string[] = []; const transfer = options.tokenTransfers[0]; let extraGasForTransfer = 0n; let receiver = options.receiver; if (this.tokenComputer!.isFungible(transfer.token)) { - transferArgs = this.dataArgsBuilder!.buildArgsForESDTTransfer(transfer); + dataParts = this.tokenTransfersDataBuilder!.buildDataPartsForESDTTransfer(transfer); extraGasForTransfer = this.config!.gasLimitESDTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_TRANSFER); } else { - transferArgs = this.dataArgsBuilder!.buildArgsForSingleESDTNFTTransfer(transfer, receiver); + dataParts = this.tokenTransfersDataBuilder!.buildDataPartsForSingleESDTNFTTransfer(transfer, receiver); extraGasForTransfer = this.config!.gasLimitESDTNFTTransfer + BigInt(ADDITIONAL_GAS_FOR_ESDT_NFT_TRANSFER); receiver = options.sender; } @@ -361,7 +361,7 @@ export class TransferTransactionsFactory { config: this.config!, sender: options.sender, receiver: receiver, - dataParts: transferArgs, + dataParts: dataParts, gasLimit: extraGasForTransfer, addDataMovementGas: true, }).build(); From 64abb79b17af46759157123e1367b07e8574b68f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 21:09:48 +0200 Subject: [PATCH 236/275] In TokenTransferDataBuilders, use the argsSerializer. --- src/smartcontracts/typesystem/numerical.ts | 40 ++++++++------- .../tokenTransfersDataBuilder.ts | 49 ++++++++++--------- src/utils.codec.ts | 5 -- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/smartcontracts/typesystem/numerical.ts b/src/smartcontracts/typesystem/numerical.ts index 0530468fd..440600284 100644 --- a/src/smartcontracts/typesystem/numerical.ts +++ b/src/smartcontracts/typesystem/numerical.ts @@ -156,9 +156,13 @@ export class NumericalValue extends PrimitiveValue { readonly sizeInBytes: number | undefined; readonly withSign: boolean; - constructor(type: NumericalType, value: BigNumber.Value) { + constructor(type: NumericalType, value: BigNumber.Value | bigint) { super(type); + if (typeof value === "bigint") { + value = value.toString(); + } + this.value = new BigNumber(value); this.sizeInBytes = type.sizeInBytes; this.withSign = type.withSign; @@ -178,7 +182,7 @@ export class NumericalValue extends PrimitiveValue { /** * Returns whether two objects have the same value. - * + * * @param other another NumericalValue */ equals(other: NumericalValue): boolean { @@ -197,8 +201,8 @@ export class NumericalValue extends PrimitiveValue { export class U8Value extends NumericalValue { static ClassName = "U8Value"; - constructor(value: BigNumber.Value) { - super(new U8Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new U8Type(), value); } getClassName(): string { @@ -209,8 +213,8 @@ export class U8Value extends NumericalValue { export class I8Value extends NumericalValue { static ClassName = "I8Value"; - constructor(value: BigNumber.Value) { - super(new I8Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new I8Type(), value); } getClassName(): string { @@ -221,8 +225,8 @@ export class I8Value extends NumericalValue { export class U16Value extends NumericalValue { static ClassName = "U16Value"; - constructor(value: BigNumber.Value) { - super(new U16Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new U16Type(), value); } getClassName(): string { @@ -233,8 +237,8 @@ export class U16Value extends NumericalValue { export class I16Value extends NumericalValue { static ClassName = "I16Value"; - constructor(value: BigNumber.Value) { - super(new I16Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new I16Type(), value); } getClassName(): string { @@ -245,8 +249,8 @@ export class I16Value extends NumericalValue { export class U32Value extends NumericalValue { static ClassName = "U32Value"; - constructor(value: BigNumber.Value) { - super(new U32Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new U32Type(), value); } getClassName(): string { @@ -257,8 +261,8 @@ export class U32Value extends NumericalValue { export class I32Value extends NumericalValue { static ClassName = "I32Value"; - constructor(value: BigNumber.Value) { - super(new I32Type(), new BigNumber(value)); + constructor(value: BigNumber.Value | bigint) { + super(new I32Type(), value); } getClassName(): string { @@ -269,7 +273,7 @@ export class I32Value extends NumericalValue { export class U64Value extends NumericalValue { static ClassName = "U64Value"; - constructor(value: BigNumber.Value) { + constructor(value: BigNumber.Value | bigint) { super(new U64Type(), value); } @@ -281,7 +285,7 @@ export class U64Value extends NumericalValue { export class I64Value extends NumericalValue { static ClassName = "I64Value"; - constructor(value: BigNumber.Value) { + constructor(value: BigNumber.Value | bigint) { super(new I64Type(), value); } @@ -293,7 +297,7 @@ export class I64Value extends NumericalValue { export class BigUIntValue extends NumericalValue { static ClassName = "BigUIntValue"; - constructor(value: BigNumber.Value) { + constructor(value: BigNumber.Value | bigint) { super(new BigUIntType(), value); } @@ -305,7 +309,7 @@ export class BigUIntValue extends NumericalValue { export class BigIntValue extends NumericalValue { static ClassName = "BigIntValue"; - constructor(value: BigNumber.Value) { + constructor(value: BigNumber.Value | bigint) { super(new BigIntType(), value); } diff --git a/src/transactionsFactories/tokenTransfersDataBuilder.ts b/src/transactionsFactories/tokenTransfersDataBuilder.ts index 083695025..45cd92162 100644 --- a/src/transactionsFactories/tokenTransfersDataBuilder.ts +++ b/src/transactionsFactories/tokenTransfersDataBuilder.ts @@ -1,51 +1,56 @@ import { IAddress } from "../interface"; +import { ArgSerializer } from "../smartcontracts/argSerializer"; +import { AddressValue, BigUIntValue, TokenIdentifierValue, TypedValue, U32Value } from "../smartcontracts/typesystem"; import { TokenComputer, TokenTransfer } from "../tokens"; -import { addressToHex, numberToPaddedHex, numberToPaddedHexWithZeroAsEmptyString, utf8ToHex } from "../utils.codec"; export class TokenTransfersDataBuilder { private tokenComputer: TokenComputer; + private argsSerializer: ArgSerializer; constructor() { this.tokenComputer = new TokenComputer(); + this.argsSerializer = new ArgSerializer(); } buildDataPartsForESDTTransfer(transfer: TokenTransfer): string[] { - let args = ["ESDTTransfer"]; - args.push(...[utf8ToHex(transfer.token.identifier), numberToPaddedHexWithZeroAsEmptyString(transfer.amount)]); - return args; + const args = this.argsSerializer.valuesToStrings([ + new TokenIdentifierValue(transfer.token.identifier), + new BigUIntValue(transfer.amount), + ]); + + return ["ESDTTransfer", ...args]; } buildDataPartsForSingleESDTNFTTransfer(transfer: TokenTransfer, receiver: IAddress) { - let args = ["ESDTNFTTransfer"]; - const token = transfer.token; const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(token.identifier); - args.push( - ...[ - utf8ToHex(identifier), - numberToPaddedHexWithZeroAsEmptyString(token.nonce), - numberToPaddedHexWithZeroAsEmptyString(transfer.amount), - addressToHex(receiver), - ], - ); - return args; + const args = this.argsSerializer.valuesToStrings([ + new TokenIdentifierValue(identifier), + new BigUIntValue(token.nonce), + new BigUIntValue(transfer.amount), + new AddressValue(receiver), + ]); + + return ["ESDTNFTTransfer", ...args]; } buildDataPartsForMultiESDTNFTTransfer(receiver: IAddress, transfers: TokenTransfer[]) { - let args = ["MultiESDTNFTTransfer", addressToHex(receiver), numberToPaddedHex(transfers.length)]; + const argsTyped: TypedValue[] = [new AddressValue(receiver), new U32Value(transfers.length)]; - for (let transfer of transfers) { + for (const transfer of transfers) { const identifier = this.tokenComputer.extractIdentifierFromExtendedIdentifier(transfer.token.identifier); - args.push( + + argsTyped.push( ...[ - utf8ToHex(identifier), - numberToPaddedHexWithZeroAsEmptyString(transfer.token.nonce), - numberToPaddedHexWithZeroAsEmptyString(transfer.amount), + new TokenIdentifierValue(identifier), + new BigUIntValue(transfer.token.nonce), + new BigUIntValue(transfer.amount), ], ); } - return args; + const args = this.argsSerializer.valuesToStrings(argsTyped); + return ["MultiESDTNFTTransfer", ...args]; } } diff --git a/src/utils.codec.ts b/src/utils.codec.ts index 51a88012c..0e03b658b 100644 --- a/src/utils.codec.ts +++ b/src/utils.codec.ts @@ -16,11 +16,6 @@ export function numberToPaddedHex(value: bigint | number | BigNumber.Value) { return zeroPadStringIfOddLength(hex); } -export function numberToPaddedHexWithZeroAsEmptyString(value: bigint | number | BigNumber.Value) { - const paddedHex = numberToPaddedHex(value); - return paddedHex == "00" ? "" : paddedHex; -} - export function isPaddedHex(input: string) { input = input || ""; let decodedThenEncoded = Buffer.from(input, "hex").toString("hex"); From 7fcad8f0a605c427d4586d11d7756e738b62b8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 25 Mar 2024 21:29:38 +0200 Subject: [PATCH 237/275] Extra unit tests. --- src/smartcontracts/codec/binary.spec.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/smartcontracts/codec/binary.spec.ts b/src/smartcontracts/codec/binary.spec.ts index 9042ce67c..95d2304da 100644 --- a/src/smartcontracts/codec/binary.spec.ts +++ b/src/smartcontracts/codec/binary.spec.ts @@ -1,7 +1,7 @@ import * as errors from "../../errors"; import { assert } from "chai"; import { BinaryCodec, BinaryCodecConstraints } from "./binary"; -import { AddressType, AddressValue, BigIntType, BigUIntType, BigUIntValue, BooleanType, BooleanValue, I16Type, I32Type, I64Type, I8Type, NumericalType, NumericalValue, Struct, Field, StructType, TypedValue, U16Type, U32Type, U32Value, U64Type, U64Value, U8Type, U8Value, List, ListType, EnumType, EnumVariantDefinition, EnumValue, ArrayVec, ArrayVecType, U16Value, TokenIdentifierType, TokenIdentifierValue, StringValue, StringType } from "../typesystem"; +import { AddressType, AddressValue, BigIntType, BigUIntType, BigUIntValue, BooleanType, BooleanValue, I16Type, I32Type, I64Type, I8Type, NumericalType, NumericalValue, Struct, Field, StructType, TypedValue, U16Type, U32Type, U32Value, U64Type, U64Value, U8Type, U8Value, List, ListType, EnumType, EnumVariantDefinition, EnumValue, ArrayVec, ArrayVecType, U16Value, TokenIdentifierType, TokenIdentifierValue, StringValue, StringType, BigIntValue, I64Value, I32Value, I16Value, I8Value } from "../typesystem"; import { isMsbOne } from "./utils"; import { Address } from "../../address"; import { BytesType, BytesValue } from "../typesystem/bytes"; @@ -85,6 +85,20 @@ describe("test binary codec (basic)", () => { } }); + it("should create numeric values, from both bigint and BigNumber.Value", async () => { + assert.deepEqual(new BigUIntValue("0xabcdefabcdefabcdef"), new BigUIntValue(BigInt("0xabcdefabcdefabcdef"))); + assert.deepEqual(new U64Value("0xabcdef"), new U64Value(BigInt(0xabcdef))); + assert.deepEqual(new U32Value("0xabcdef"), new U32Value(BigInt(0xabcdef))); + assert.deepEqual(new U16Value("0xabcdef"), new U16Value(BigInt(0xabcdef))); + assert.deepEqual(new U8Value("0xabcdef"), new U8Value(BigInt(0xabcdef))); + + assert.deepEqual(new BigIntValue(BigInt("0xabcdefabcdefabcdef")), new BigIntValue(BigInt("0xabcdefabcdefabcdef"))); + assert.deepEqual(new I64Value("0xabcdef"), new I64Value(BigInt(0xabcdef))); + assert.deepEqual(new I32Value("0xabcdef"), new I32Value(BigInt(0xabcdef))); + assert.deepEqual(new I16Value("0xabcdef"), new I16Value(BigInt(0xabcdef))); + assert.deepEqual(new I8Value("0xabcdef"), new I8Value(BigInt(0xabcdef))); + }); + it("should create bytes and strings, encode and decode", async () => { let bytesValue = BytesValue.fromHex("74657374"); let stringValue = StringValue.fromHex("74657374"); From fb979bfc7ed96d65f1c7a3675628e6da73ea279e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 26 Mar 2024 16:13:49 +0200 Subject: [PATCH 238/275] revert interaction error to warning & use arg serializer in transactions factories --- src/compatibility.ts | 5 +- .../tokenOperationsFactory.test.net.spec.ts | 2 +- src/transaction.local.net.spec.ts | 3 +- .../delegationTransactionsFactory.ts | 49 +++- .../smartContractTransactionsFactory.ts | 32 ++- ...anagementTransactionIntentsFactory.spec.ts | 2 +- .../tokenManagementTransactionsFactory.ts | 255 ++++++++++++------ .../transferTransactionsFactory.spec.ts | 5 +- .../transferTransactionsFactory.ts | 18 +- 9 files changed, 244 insertions(+), 127 deletions(-) diff --git a/src/compatibility.ts b/src/compatibility.ts index b214c4f29..9caf1977a 100644 --- a/src/compatibility.ts +++ b/src/compatibility.ts @@ -1,5 +1,4 @@ import { Address } from "./address"; -import { Err } from "./errors"; import { IAddress } from "./interface"; /** @@ -11,11 +10,11 @@ export class Compatibility { */ static guardAddressIsSetAndNonZero(address: IAddress | undefined, context: string, resolution: string) { if (!address || address.bech32() == "") { - throw new Err( + console.warn( `${context}: address should be set; ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, ); } else if (address.bech32() == Address.Zero().bech32()) { - throw new Err( + console.warn( `${context}: address should not be the 'zero' address (also known as the 'contracts deployment address'); ${resolution}. In the future, this will throw an exception instead of emitting a WARN.`, ); } diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts index 0e2e51135..2ae574fa8 100644 --- a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts +++ b/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts @@ -3,7 +3,7 @@ import { GasEstimator } from "../gasEstimator"; import { INetworkConfig, ITransactionOnNetwork } from "../interfaceOfNetwork"; import { TestWallet, loadTestWallets } from "../testutils"; import { INetworkProvider, createTestnetProvider } from "../testutils/networkProviders"; -import { TokenTransfer } from "../tokenTransfer"; +import { TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { TransactionWatcher } from "../transactionWatcher"; import { TransferTransactionsFactory } from "../transactionsFactories/transferTransactionsFactory"; diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index 502d6be03..97887ecf6 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -9,7 +9,6 @@ import { TransactionPayload } from "./transactionPayload"; import { TransactionWatcher } from "./transactionWatcher"; import { TransactionsFactoryConfig } from "./transactionsFactories/transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transactionsFactories/transferTransactionsFactory"; -import { TokenComputer } from "./tokens"; import { TransactionComputer } from "./transactionComputer"; describe("test transaction", function () { @@ -153,7 +152,7 @@ describe("test transaction", function () { const network = await provider.getNetworkConfig(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new TransferTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new TransferTransactionsFactory({ config: config }); await alice.sync(provider); await bob.sync(provider); diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index da902ee32..018b0fdf9 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -2,8 +2,8 @@ import { Address } from "../address"; import { DELEGATION_MANAGER_SC_ADDRESS } from "../constants"; import { Err } from "../errors"; import { IAddress } from "../interface"; +import { ArgSerializer, BigUIntValue, BytesValue, StringValue } from "../smartcontracts"; import { Transaction } from "../transaction"; -import { byteArrayToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; import { TransactionBuilder } from "./transactionBuilder"; interface Config { @@ -28,9 +28,11 @@ interface IValidatorPublicKey { */ export class DelegationTransactionsFactory { private readonly config: Config; + private readonly argSerializer: ArgSerializer; constructor(options: { config: Config }) { this.config = options.config; + this.argSerializer = new ArgSerializer(); } createTransactionForNewDelegationContract(options: { @@ -41,8 +43,10 @@ export class DelegationTransactionsFactory { }): Transaction { const dataParts = [ "createNewDelegationContract", - numberToPaddedHex(options.totalDelegationCap.toString()), - numberToPaddedHex(options.serviceFee.toString()), + ...this.argSerializer.valuesToStrings([ + new BigUIntValue(options.totalDelegationCap), + new BigUIntValue(options.serviceFee), + ]), ]; const executionGasLimit = @@ -73,7 +77,12 @@ export class DelegationTransactionsFactory { const dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts.push(...[options.publicKeys[i].hex(), byteArrayToHex(options.signedMessages[i])]); + dataParts.push( + ...[ + options.publicKeys[i].hex(), + this.argSerializer.valuesToStrings([new BytesValue(Buffer.from(options.signedMessages[i]))])[0], + ], + ); } return new TransactionBuilder({ @@ -216,7 +225,10 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; serviceFee: bigint; }): Transaction { - const dataParts = ["changeServiceFee", numberToPaddedHex(options.serviceFee)]; + const dataParts = [ + "changeServiceFee", + this.argSerializer.valuesToStrings([new BigUIntValue(options.serviceFee)])[0], + ]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -235,7 +247,10 @@ export class DelegationTransactionsFactory { delegationContract: IAddress; delegationCap: bigint; }): Transaction { - const dataParts = ["modifyTotalDelegationCap", numberToPaddedHex(options.delegationCap)]; + const dataParts = [ + "modifyTotalDelegationCap", + this.argSerializer.valuesToStrings([new BigUIntValue(options.delegationCap)])[0], + ]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -253,7 +268,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; }): Transaction { - const dataParts = ["setAutomaticActivation", utf8ToHex("true")]; + const dataParts = ["setAutomaticActivation", this.argSerializer.valuesToStrings([new StringValue("true")])[0]]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -271,7 +286,7 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; }): Transaction { - const dataParts = ["setAutomaticActivation", utf8ToHex("false")]; + const dataParts = ["setAutomaticActivation", this.argSerializer.valuesToStrings([new StringValue("false")])[0]]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -289,7 +304,10 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; }): Transaction { - const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("true")]; + const dataParts = [ + "setCheckCapOnReDelegateRewards", + this.argSerializer.valuesToStrings([new StringValue("true")])[0], + ]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -307,7 +325,10 @@ export class DelegationTransactionsFactory { sender: IAddress; delegationContract: IAddress; }): Transaction { - const dataParts = ["setCheckCapOnReDelegateRewards", utf8ToHex("false")]; + const dataParts = [ + "setCheckCapOnReDelegateRewards", + this.argSerializer.valuesToStrings([new StringValue("false")])[0], + ]; const gasLimit = this.config.gasLimitDelegationOperations + this.config.additionalGasLimitForDelegationOperations; @@ -330,9 +351,11 @@ export class DelegationTransactionsFactory { }): Transaction { const dataParts = [ "setMetaData", - utf8ToHex(options.name), - utf8ToHex(options.website), - utf8ToHex(options.identifier), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.name), + new StringValue(options.website), + new StringValue(options.identifier), + ]), ]; const gasLimit = diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d7a9d6d78..3c22bcc64 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -2,7 +2,14 @@ import { Address } from "../address"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { Err, ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; -import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; +import { + ArgSerializer, + BytesValue, + CodeMetadata, + ContractFunction, + EndpointDefinition, + StringValue, +} from "../smartcontracts"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Token, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; @@ -34,12 +41,14 @@ export class SmartContractTransactionsFactory { private readonly abi?: IAbi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; + private readonly argSerializer: ArgSerializer; constructor(options: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { this.config = options.config; this.abi = options.abi; this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); + this.argSerializer = new ArgSerializer(); } createTransactionForDeploy(options: { @@ -60,7 +69,14 @@ export class SmartContractTransactionsFactory { const isPayableBySmartContract = options.isPayableBySmartContract ?? true; const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; + + let parts = [ + ...this.argSerializer.valuesToStrings([ + new BytesValue(Buffer.from(options.bytecode)), + new BytesValue(Buffer.from(VM_TYPE_WASM_VM)), + ]), + metadata.toString(), + ]; const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); @@ -110,7 +126,11 @@ export class SmartContractTransactionsFactory { receiver = options.sender; } - dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); + dataParts.push( + dataParts.length + ? this.argSerializer.valuesToStrings([new StringValue(options.functionName)])[0] + : options.functionName, + ); dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.functionName))); return new TransactionBuilder({ @@ -146,7 +166,11 @@ export class SmartContractTransactionsFactory { const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; + let parts = [ + "upgradeContract", + this.argSerializer.valuesToStrings([new BytesValue(Buffer.from(options.bytecode))])[0], + metadata.toString(), + ]; const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); diff --git a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts index 678faee41..aa5b72636 100644 --- a/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts +++ b/src/transactionsFactories/tokenManagementTransactionIntentsFactory.spec.ts @@ -49,7 +49,7 @@ describe("test token management transactions factory", () => { assert.deepEqual( transaction.data, Buffer.from( - "issue@4652414e4b@4652414e4b@64@00@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", + "issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365", ), ); assert.equal(transaction.sender, frank.address.toString()); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 4460e2872..9219c754b 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -2,8 +2,8 @@ import { Address } from "../address"; import { ESDT_CONTRACT_ADDRESS } from "../constants"; import { IAddress } from "../interface"; import { Logger } from "../logger"; +import { AddressValue, ArgSerializer, BigUIntValue, BytesValue, StringValue } from "../smartcontracts"; import { Transaction } from "../transaction"; -import { addressToHex, byteArrayToHex, numberToPaddedHex, utf8ToHex } from "../utils.codec"; import { TransactionBuilder } from "./transactionBuilder"; interface Config { @@ -33,13 +33,15 @@ type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; */ export class TokenManagementTransactionsFactory { private readonly config: Config; + private readonly argSerializer: ArgSerializer; private readonly trueAsHex: string; private readonly falseAsHex: string; constructor(options: { config: Config }) { this.config = options.config; - this.trueAsHex = utf8ToHex("true"); - this.falseAsHex = utf8ToHex("false"); + this.argSerializer = new ArgSerializer(); + this.trueAsHex = this.argSerializer.valuesToStrings([new StringValue("true")])[0]; + this.falseAsHex = this.argSerializer.valuesToStrings([new StringValue("false")])[0]; } createTransactionForIssuingFungible(options: { @@ -59,21 +61,25 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "issue", - utf8ToHex(options.tokenName), - utf8ToHex(options.tokenTicker), - numberToPaddedHex(options.initialSupply), - numberToPaddedHex(options.numDecimals), - utf8ToHex("canFreeze"), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + ]), + ...this.argSerializer.valuesToStrings([ + new BigUIntValue(options.initialSupply), + new BigUIntValue(options.numDecimals), + ]), + this.argSerializer.valuesToStrings([new StringValue("canFreeze")])[0], options.canFreeze ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canWipe"), + this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], options.canWipe ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canPause"), + this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], options.canPause ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canChangeOwner"), + this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canUpgrade"), + this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], options.canUpgrade ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canAddSpecialRoles"), + this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; @@ -104,21 +110,23 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "issueSemiFungible", - utf8ToHex(options.tokenName), - utf8ToHex(options.tokenTicker), - utf8ToHex("canFreeze"), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new StringValue("canFreeze"), + ]), options.canFreeze ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canWipe"), + this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], options.canWipe ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canPause"), + this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], options.canPause ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canTransferNFTCreateRole"), + this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canChangeOwner"), + this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canUpgrade"), + this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], options.canUpgrade ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canAddSpecialRoles"), + this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; @@ -149,21 +157,23 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "issueNonFungible", - utf8ToHex(options.tokenName), - utf8ToHex(options.tokenTicker), - utf8ToHex("canFreeze"), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new StringValue("canFreeze"), + ]), options.canFreeze ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canWipe"), + this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], options.canWipe ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canPause"), + this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], options.canPause ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canTransferNFTCreateRole"), + this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canChangeOwner"), + this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canUpgrade"), + this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], options.canUpgrade ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canAddSpecialRoles"), + this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; @@ -195,22 +205,24 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "registerMetaESDT", - utf8ToHex(options.tokenName), - utf8ToHex(options.tokenTicker), - numberToPaddedHex(options.numDecimals), - utf8ToHex("canFreeze"), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new BigUIntValue(options.numDecimals), + new StringValue("canFreeze"), + ]), options.canFreeze ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canWipe"), + this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], options.canWipe ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canPause"), + this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], options.canPause ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canTransferNFTCreateRole"), + this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canChangeOwner"), + this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canUpgrade"), + this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], options.canUpgrade ? this.trueAsHex : this.falseAsHex, - utf8ToHex("canAddSpecialRoles"), + this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, ]; @@ -236,10 +248,12 @@ export class TokenManagementTransactionsFactory { const dataParts = [ "registerAndSetAllRoles", - utf8ToHex(options.tokenName), - utf8ToHex(options.tokenTicker), - utf8ToHex(options.tokenType), - numberToPaddedHex(options.numDecimals), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new StringValue(options.tokenType), + new BigUIntValue(options.numDecimals), + ]), ]; return new TransactionBuilder({ @@ -254,7 +268,10 @@ export class TokenManagementTransactionsFactory { } createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["setBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const dataParts = [ + "setBurnRoleGlobally", + this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ]; return new TransactionBuilder({ config: this.config, @@ -267,7 +284,10 @@ export class TokenManagementTransactionsFactory { } createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["unsetBurnRoleGlobally", utf8ToHex(options.tokenIdentifier)]; + const dataParts = [ + "unsetBurnRoleGlobally", + this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ]; return new TransactionBuilder({ config: this.config, @@ -288,10 +308,16 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "setSpecialRole", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user), - ...(options.addRoleLocalMint ? [utf8ToHex("ESDTRoleLocalMint")] : []), - ...(options.addRoleLocalBurn ? [utf8ToHex("ESDTRoleLocalBurn")] : []), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ...(options.addRoleLocalMint + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleLocalMint")]) + : []), + ...(options.addRoleLocalBurn + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleLocalBurn")]) + : []), ]; return new TransactionBuilder({ @@ -315,12 +341,20 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "setSpecialRole", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user), - ...(options.addRoleNFTCreate ? [utf8ToHex("ESDTRoleNFTCreate")] : []), - ...(options.addRoleNFTBurn ? [utf8ToHex("ESDTRoleNFTBurn")] : []), - ...(options.addRoleNFTAddQuantity ? [utf8ToHex("ESDTRoleNFTAddQuantity")] : []), - ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ...(options.addRoleNFTCreate + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTCreate")]) + : []), + ...(options.addRoleNFTBurn ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTBurn")]) : []), + ...(options.addRoleNFTAddQuantity + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTAddQuantity")]) + : []), + ...(options.addRoleESDTTransferRole + ? this.argSerializer.valuesToStrings([new StringValue("ESDTTransferRole")]) + : []), ]; return new TransactionBuilder({ @@ -357,13 +391,23 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "setSpecialRole", - utf8ToHex(options.tokenIdentifier), - addressToHex(options.user), - ...(options.addRoleNFTCreate ? [utf8ToHex("ESDTRoleNFTCreate")] : []), - ...(options.addRoleNFTBurn ? [utf8ToHex("ESDTRoleNFTBurn")] : []), - ...(options.addRoleNFTUpdateAttributes ? [utf8ToHex("ESDTRoleNFTUpdateAttributes")] : []), - ...(options.addRoleNFTAddURI ? [utf8ToHex("ESDTRoleNFTAddURI")] : []), - ...(options.addRoleESDTTransferRole ? [utf8ToHex("ESDTTransferRole")] : []), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ...(options.addRoleNFTCreate + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTCreate")]) + : []), + ...(options.addRoleNFTBurn ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTBurn")]) : []), + ...(options.addRoleNFTUpdateAttributes + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTUpdateAttributes")]) + : []), + ...(options.addRoleNFTAddURI + ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTAddURI")]) + : []), + ...(options.addRoleESDTTransferRole + ? this.argSerializer.valuesToStrings([new StringValue("ESDTTransferRole")]) + : []), ]; return new TransactionBuilder({ @@ -388,13 +432,15 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTNFTCreate", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.initialQuantity), - utf8ToHex(options.name), - numberToPaddedHex(options.royalties), - utf8ToHex(options.hash), - byteArrayToHex(options.attributes), - ...options.uris.map(utf8ToHex), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.initialQuantity), + new StringValue(options.name), + new BigUIntValue(options.royalties), + new StringValue(options.hash), + new BytesValue(Buffer.from(options.attributes)), + ...options.uris.map((uri) => new StringValue(uri)), + ]), ]; // Note that the following is an approximation (a reasonable one): @@ -412,7 +458,7 @@ export class TokenManagementTransactionsFactory { } createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["pause", utf8ToHex(options.tokenIdentifier)]; + const dataParts = ["pause", this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0]]; return new TransactionBuilder({ config: this.config, @@ -425,7 +471,10 @@ export class TokenManagementTransactionsFactory { } createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["unPause", utf8ToHex(options.tokenIdentifier)]; + const dataParts = [ + "unPause", + this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ]; return new TransactionBuilder({ config: this.config, @@ -438,7 +487,13 @@ export class TokenManagementTransactionsFactory { } createTransactionForFreezing(options: { sender: IAddress; user: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["freeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts = [ + "freeze", + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ]; return new TransactionBuilder({ config: this.config, @@ -455,7 +510,13 @@ export class TokenManagementTransactionsFactory { user: IAddress; tokenIdentifier: string; }): Transaction { - const dataParts = ["UnFreeze", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts = [ + "UnFreeze", + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ]; return new TransactionBuilder({ config: this.config, @@ -468,7 +529,13 @@ export class TokenManagementTransactionsFactory { } createTransactionForWiping(options: { sender: IAddress; user: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["wipe", utf8ToHex(options.tokenIdentifier), addressToHex(options.user)]; + const dataParts = [ + "wipe", + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new AddressValue(options.user), + ]), + ]; return new TransactionBuilder({ config: this.config, @@ -487,8 +554,10 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTLocalMint", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.supplyToMint), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.supplyToMint), + ]), ]; return new TransactionBuilder({ @@ -508,8 +577,10 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTLocalBurn", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.supplyToBurn), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.supplyToBurn), + ]), ]; return new TransactionBuilder({ @@ -530,9 +601,11 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTNFTUpdateAttributes", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.tokenNonce), - byteArrayToHex(options.attributes), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.tokenNonce), + new BytesValue(Buffer.from(options.attributes)), + ]), ]; return new TransactionBuilder({ @@ -553,9 +626,11 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTNFTAddQuantity", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.tokenNonce), - numberToPaddedHex(options.quantityToAdd), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.tokenNonce), + new BigUIntValue(options.quantityToAdd), + ]), ]; return new TransactionBuilder({ @@ -576,9 +651,11 @@ export class TokenManagementTransactionsFactory { }): Transaction { const dataParts = [ "ESDTNFTBurn", - utf8ToHex(options.tokenIdentifier), - numberToPaddedHex(options.tokenNonce), - numberToPaddedHex(options.quantityToBurn), + ...this.argSerializer.valuesToStrings([ + new StringValue(options.tokenIdentifier), + new BigUIntValue(options.tokenNonce), + new BigUIntValue(options.quantityToBurn), + ]), ]; return new TransactionBuilder({ diff --git a/src/transactionsFactories/transferTransactionsFactory.spec.ts b/src/transactionsFactories/transferTransactionsFactory.spec.ts index ab7f676eb..7251b9c42 100644 --- a/src/transactionsFactories/transferTransactionsFactory.spec.ts +++ b/src/transactionsFactories/transferTransactionsFactory.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { Address } from "../address"; import { ErrBadUsage } from "../errors"; -import { Token, TokenComputer, TokenTransfer } from "../tokens"; +import { Token, TokenTransfer } from "../tokens"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; import { TransferTransactionsFactory } from "./transferTransactionsFactory"; @@ -9,7 +9,6 @@ describe("test transfer transcations factory", function () { const config = new TransactionsFactoryConfig({ chainID: "D" }); const transferFactory = new TransferTransactionsFactory({ config: config, - tokenComputer: new TokenComputer(), }); const alice = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -50,7 +49,7 @@ describe("test transfer transcations factory", function () { sender: alice, receiver: bob, nativeAmount: 1000000000000000000n, - data: "test data", + data: Buffer.from("test data"), }); assert.equal(transaction.sender, alice.bech32()); diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index a981fcd70..350cd444d 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -18,7 +18,7 @@ import { U16Value, U64Value, } from "../smartcontracts"; -import { Token, TokenTransfer } from "../tokens"; +import { TokenComputer, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { TransactionPayload } from "../transactionPayload"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; @@ -36,10 +36,6 @@ interface IConfig { gasLimitMultiESDTNFTTransfer: bigint; } -interface ITokenComputer { - isFungible(token: Token): boolean; -} - interface IGasEstimator { forEGLDTransfer(dataLength: number): number; forESDTTransfer(dataLength: number): number; @@ -53,7 +49,7 @@ interface IGasEstimator { export class TransferTransactionsFactory { private readonly config?: IConfig; private readonly tokenTransfersDataBuilder?: TokenTransfersDataBuilder; - private readonly tokenComputer?: ITokenComputer; + private readonly tokenComputer?: TokenComputer; private readonly gasEstimator?: IGasEstimator; /** @@ -62,12 +58,12 @@ export class TransferTransactionsFactory { * The legacy version contains methods like `createEGLDTransfer`, `createESDTTransfer`, `createESDTNFTTransfer` and `createMultiESDTNFTTransfer`. * This was done in order to minimize breaking changes in client code. */ - constructor(options: IGasEstimator | { config: IConfig; tokenComputer: ITokenComputer }) { + constructor(options: IGasEstimator | { config: IConfig }) { if (this.isGasEstimator(options)) { this.gasEstimator = options; } else { this.config = options.config; - this.tokenComputer = options.tokenComputer; + this.tokenComputer = new TokenComputer(); this.tokenTransfersDataBuilder = new TokenTransfersDataBuilder(); } } @@ -104,17 +100,17 @@ export class TransferTransactionsFactory { sender: IAddress; receiver: IAddress; nativeAmount: bigint; - data?: string; + data?: Uint8Array; }): Transaction { this.ensureMembersAreDefined(); - const data = options.data || ""; + const data = options.data || new Uint8Array(); return new TransactionBuilder({ config: this.config!, sender: options.sender, receiver: options.receiver, - dataParts: [data], + dataParts: [Buffer.from(data).toString()], gasLimit: 0n, addDataMovementGas: true, amount: options.nativeAmount, From 4af4ce11f6ef9a25119d7e89eaee030218da1913 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 26 Mar 2024 16:18:16 +0200 Subject: [PATCH 239/275] bump version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f2bb62e5f..af1070cee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.12", + "version": "13.0.0-beta.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.12", + "version": "13.0.0-beta.13", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 9077eb6d7..ee253e162 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.12", + "version": "13.0.0-beta.13", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", From 45c036b7af0fd6e4a6cb9b816e21e0e68cba6e6e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 26 Mar 2024 16:28:00 +0200 Subject: [PATCH 240/275] mark nonce as optional when instantiating a Token --- src/tokens.spec.ts | 2 +- src/tokens.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tokens.spec.ts b/src/tokens.spec.ts index f3214b114..0228a2f7c 100644 --- a/src/tokens.spec.ts +++ b/src/tokens.spec.ts @@ -5,7 +5,7 @@ describe("test tokens and token computer", async () => { const tokenComputer = new TokenComputer(); it("should test if token is fungible", async () => { - const fungibleToken = new Token({ identifier: "TEST-123456", nonce: 0n }); + const fungibleToken = new Token({ identifier: "TEST-123456" }); const nonFungibleToken = new Token({ identifier: "NFT-987654", nonce: 7n }); assert.equal(tokenComputer.isFungible(fungibleToken), true); diff --git a/src/tokens.ts b/src/tokens.ts index 07e082b2a..f6b29bc91 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -20,9 +20,9 @@ export class Token { readonly identifier: string; readonly nonce: bigint; - constructor(options: { identifier: string; nonce: bigint }) { + constructor(options: { identifier: string; nonce?: bigint }) { this.identifier = options.identifier; - this.nonce = options.nonce; + this.nonce = options.nonce || 0n; } } From c50abf94e1a11832ba3406e8d1509e6bf40b6a01 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 26 Mar 2024 18:49:11 +0200 Subject: [PATCH 241/275] fixes after review --- .../delegationTransactionsFactory.ts | 12 +- .../smartContractTransactionsFactory.ts | 32 +-- .../tokenManagementTransactionsFactory.ts | 243 ++++++++---------- .../transferTransactionsFactory.ts | 2 +- 4 files changed, 117 insertions(+), 172 deletions(-) diff --git a/src/transactionsFactories/delegationTransactionsFactory.ts b/src/transactionsFactories/delegationTransactionsFactory.ts index 018b0fdf9..bc1369b52 100644 --- a/src/transactionsFactories/delegationTransactionsFactory.ts +++ b/src/transactionsFactories/delegationTransactionsFactory.ts @@ -73,16 +73,16 @@ export class DelegationTransactionsFactory { throw new Err("The number of public keys should match the number of signed messages"); } + const signedMessagesAsTypedValues = options.signedMessages.map( + (message) => new BytesValue(Buffer.from(message)), + ); + const messagesAsStrings = this.argSerializer.valuesToStrings(signedMessagesAsTypedValues); + const numNodes = options.publicKeys.length; const dataParts = ["addNodes"]; for (let i = 0; i < numNodes; i++) { - dataParts.push( - ...[ - options.publicKeys[i].hex(), - this.argSerializer.valuesToStrings([new BytesValue(Buffer.from(options.signedMessages[i]))])[0], - ], - ); + dataParts.push(...[options.publicKeys[i].hex(), messagesAsStrings[i]]); } return new TransactionBuilder({ diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index 3c22bcc64..d7a9d6d78 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -2,14 +2,7 @@ import { Address } from "../address"; import { CONTRACT_DEPLOY_ADDRESS, VM_TYPE_WASM_VM } from "../constants"; import { Err, ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; -import { - ArgSerializer, - BytesValue, - CodeMetadata, - ContractFunction, - EndpointDefinition, - StringValue, -} from "../smartcontracts"; +import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; import { Token, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; @@ -41,14 +34,12 @@ export class SmartContractTransactionsFactory { private readonly abi?: IAbi; private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - private readonly argSerializer: ArgSerializer; constructor(options: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { this.config = options.config; this.abi = options.abi; this.tokenComputer = options.tokenComputer; this.dataArgsBuilder = new TokenTransfersDataBuilder(); - this.argSerializer = new ArgSerializer(); } createTransactionForDeploy(options: { @@ -69,14 +60,7 @@ export class SmartContractTransactionsFactory { const isPayableBySmartContract = options.isPayableBySmartContract ?? true; const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - - let parts = [ - ...this.argSerializer.valuesToStrings([ - new BytesValue(Buffer.from(options.bytecode)), - new BytesValue(Buffer.from(VM_TYPE_WASM_VM)), - ]), - metadata.toString(), - ]; + let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); @@ -126,11 +110,7 @@ export class SmartContractTransactionsFactory { receiver = options.sender; } - dataParts.push( - dataParts.length - ? this.argSerializer.valuesToStrings([new StringValue(options.functionName)])[0] - : options.functionName, - ); + dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.functionName))); return new TransactionBuilder({ @@ -166,11 +146,7 @@ export class SmartContractTransactionsFactory { const args = options.args || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); - let parts = [ - "upgradeContract", - this.argSerializer.valuesToStrings([new BytesValue(Buffer.from(options.bytecode))])[0], - metadata.toString(), - ]; + let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); parts = parts.concat(preparedArgs); diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 9219c754b..5679b307b 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -34,14 +34,14 @@ type RegisterAndSetAllRolesTokenType = "NFT" | "SFT" | "META" | "FNG"; export class TokenManagementTransactionsFactory { private readonly config: Config; private readonly argSerializer: ArgSerializer; - private readonly trueAsHex: string; - private readonly falseAsHex: string; + private readonly trueAsString: string; + private readonly falseAsString: string; constructor(options: { config: Config }) { this.config = options.config; this.argSerializer = new ArgSerializer(); - this.trueAsHex = this.argSerializer.valuesToStrings([new StringValue("true")])[0]; - this.falseAsHex = this.argSerializer.valuesToStrings([new StringValue("false")])[0]; + this.trueAsString = "true"; + this.falseAsString = "false"; } createTransactionForIssuingFungible(options: { @@ -59,30 +59,27 @@ export class TokenManagementTransactionsFactory { }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ - "issue", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenName), - new StringValue(options.tokenTicker), - ]), - ...this.argSerializer.valuesToStrings([ - new BigUIntValue(options.initialSupply), - new BigUIntValue(options.numDecimals), - ]), - this.argSerializer.valuesToStrings([new StringValue("canFreeze")])[0], - options.canFreeze ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], - options.canWipe ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], - options.canPause ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], - options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], - options.canUpgrade ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], - options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, + const args = [ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new BigUIntValue(options.initialSupply), + new BigUIntValue(options.numDecimals), + new StringValue("canFreeze"), + new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue("canWipe"), + new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue("canPause"), + new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue("canChangeOwner"), + new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue("canUpgrade"), + new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue("canAddSpecialRoles"), + new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), ]; + const dataParts = ["issue", ...this.argSerializer.valuesToStrings(args)]; + return new TransactionBuilder({ config: this.config, sender: options.sender, @@ -108,28 +105,27 @@ export class TokenManagementTransactionsFactory { }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ - "issueSemiFungible", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenName), - new StringValue(options.tokenTicker), - new StringValue("canFreeze"), - ]), - options.canFreeze ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], - options.canWipe ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], - options.canPause ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], - options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], - options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], - options.canUpgrade ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], - options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, + const args = [ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new StringValue("canFreeze"), + new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue("canWipe"), + new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue("canPause"), + new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue("canTransferNFTCreateRole"), + new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue("canChangeOwner"), + new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue("canUpgrade"), + new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue("canAddSpecialRoles"), + new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), ]; + const dataParts = ["issueSemiFungible", ...this.argSerializer.valuesToStrings(args)]; + return new TransactionBuilder({ config: this.config, sender: options.sender, @@ -155,28 +151,27 @@ export class TokenManagementTransactionsFactory { }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ - "issueNonFungible", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenName), - new StringValue(options.tokenTicker), - new StringValue("canFreeze"), - ]), - options.canFreeze ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], - options.canWipe ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], - options.canPause ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], - options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], - options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], - options.canUpgrade ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], - options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, + const args = [ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new StringValue("canFreeze"), + new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue("canWipe"), + new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue("canPause"), + new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue("canTransferNFTCreateRole"), + new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue("canChangeOwner"), + new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue("canUpgrade"), + new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue("canAddSpecialRoles"), + new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), ]; + const dataParts = ["issueNonFungible", ...this.argSerializer.valuesToStrings(args)]; + return new TransactionBuilder({ config: this.config, sender: options.sender, @@ -203,29 +198,28 @@ export class TokenManagementTransactionsFactory { }): Transaction { this.notifyAboutUnsettingBurnRoleGlobally(); - const dataParts = [ - "registerMetaESDT", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenName), - new StringValue(options.tokenTicker), - new BigUIntValue(options.numDecimals), - new StringValue("canFreeze"), - ]), - options.canFreeze ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canWipe")])[0], - options.canWipe ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canPause")])[0], - options.canPause ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canTransferNFTCreateRole")])[0], - options.canTransferNFTCreateRole ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canChangeOwner")])[0], - options.canChangeOwner ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canUpgrade")])[0], - options.canUpgrade ? this.trueAsHex : this.falseAsHex, - this.argSerializer.valuesToStrings([new StringValue("canAddSpecialRoles")])[0], - options.canAddSpecialRoles ? this.trueAsHex : this.falseAsHex, + const args = [ + new StringValue(options.tokenName), + new StringValue(options.tokenTicker), + new BigUIntValue(options.numDecimals), + new StringValue("canFreeze"), + new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue("canWipe"), + new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue("canPause"), + new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue("canTransferNFTCreateRole"), + new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue("canChangeOwner"), + new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue("canUpgrade"), + new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue("canAddSpecialRoles"), + new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), ]; + const dataParts = ["registerMetaESDT", ...this.argSerializer.valuesToStrings(args)]; + return new TransactionBuilder({ config: this.config, sender: options.sender, @@ -306,19 +300,12 @@ export class TokenManagementTransactionsFactory { addRoleLocalMint: boolean; addRoleLocalBurn: boolean; }): Transaction { - const dataParts = [ - "setSpecialRole", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenIdentifier), - new AddressValue(options.user), - ]), - ...(options.addRoleLocalMint - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleLocalMint")]) - : []), - ...(options.addRoleLocalBurn - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleLocalBurn")]) - : []), - ]; + const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; + + options.addRoleLocalMint ? args.push(new StringValue("ESDTRoleLocalMint")) : args.push(...[]); + options.addRoleLocalBurn ? args.push(new StringValue("ESDTRoleLocalBurn")) : args.push(...[]); + + const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; return new TransactionBuilder({ config: this.config, @@ -339,23 +326,14 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddQuantity: boolean; addRoleESDTTransferRole: boolean; }): Transaction { - const dataParts = [ - "setSpecialRole", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenIdentifier), - new AddressValue(options.user), - ]), - ...(options.addRoleNFTCreate - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTCreate")]) - : []), - ...(options.addRoleNFTBurn ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTBurn")]) : []), - ...(options.addRoleNFTAddQuantity - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTAddQuantity")]) - : []), - ...(options.addRoleESDTTransferRole - ? this.argSerializer.valuesToStrings([new StringValue("ESDTTransferRole")]) - : []), - ]; + const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; + + options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : args.push(...[]); + options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : args.push(...[]); + options.addRoleNFTAddQuantity ? args.push(new StringValue("ESDTRoleNFTAddQuantity")) : args.push(...[]); + options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : args.push(...[]); + + const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; return new TransactionBuilder({ config: this.config, @@ -389,26 +367,17 @@ export class TokenManagementTransactionsFactory { addRoleNFTAddURI: boolean; addRoleESDTTransferRole: boolean; }): Transaction { - const dataParts = [ - "setSpecialRole", - ...this.argSerializer.valuesToStrings([ - new StringValue(options.tokenIdentifier), - new AddressValue(options.user), - ]), - ...(options.addRoleNFTCreate - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTCreate")]) - : []), - ...(options.addRoleNFTBurn ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTBurn")]) : []), - ...(options.addRoleNFTUpdateAttributes - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTUpdateAttributes")]) - : []), - ...(options.addRoleNFTAddURI - ? this.argSerializer.valuesToStrings([new StringValue("ESDTRoleNFTAddURI")]) - : []), - ...(options.addRoleESDTTransferRole - ? this.argSerializer.valuesToStrings([new StringValue("ESDTTransferRole")]) - : []), - ]; + const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; + + options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : args.push(...[]); + options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : args.push(...[]); + options.addRoleNFTUpdateAttributes + ? args.push(new StringValue("ESDTRoleNFTUpdateAttributes")) + : args.push(...[]); + options.addRoleNFTAddURI ? args.push(new StringValue("ESDTRoleNFTAddURI")) : args.push(...[]); + options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : args.push(...[]); + + const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; return new TransactionBuilder({ config: this.config, diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 350cd444d..8148549a9 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -110,7 +110,7 @@ export class TransferTransactionsFactory { config: this.config!, sender: options.sender, receiver: options.receiver, - dataParts: [Buffer.from(data).toString()], + dataParts: [Buffer.from(data).toString("utf8")], gasLimit: 0n, addDataMovementGas: true, amount: options.nativeAmount, From 7122d21947e1ffa39b19802323b10889acd53b25 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 27 Mar 2024 13:47:51 +0200 Subject: [PATCH 242/275] fixes after re-review --- .../tokenManagementTransactionsFactory.ts | 94 ++++++++++--------- .../transactionBuilder.ts | 3 + .../transferTransactionsFactory.ts | 21 +++-- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/transactionsFactories/tokenManagementTransactionsFactory.ts b/src/transactionsFactories/tokenManagementTransactionsFactory.ts index 5679b307b..86662c00e 100644 --- a/src/transactionsFactories/tokenManagementTransactionsFactory.ts +++ b/src/transactionsFactories/tokenManagementTransactionsFactory.ts @@ -65,17 +65,17 @@ export class TokenManagementTransactionsFactory { new BigUIntValue(options.initialSupply), new BigUIntValue(options.numDecimals), new StringValue("canFreeze"), - new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canFreeze)), new StringValue("canWipe"), - new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canWipe)), new StringValue("canPause"), - new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canPause)), new StringValue("canChangeOwner"), - new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canChangeOwner)), new StringValue("canUpgrade"), - new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canUpgrade)), new StringValue("canAddSpecialRoles"), - new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canAddSpecialRoles)), ]; const dataParts = ["issue", ...this.argSerializer.valuesToStrings(args)]; @@ -109,19 +109,19 @@ export class TokenManagementTransactionsFactory { new StringValue(options.tokenName), new StringValue(options.tokenTicker), new StringValue("canFreeze"), - new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canFreeze)), new StringValue("canWipe"), - new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canWipe)), new StringValue("canPause"), - new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canPause)), new StringValue("canTransferNFTCreateRole"), - new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canTransferNFTCreateRole)), new StringValue("canChangeOwner"), - new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canChangeOwner)), new StringValue("canUpgrade"), - new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canUpgrade)), new StringValue("canAddSpecialRoles"), - new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canAddSpecialRoles)), ]; const dataParts = ["issueSemiFungible", ...this.argSerializer.valuesToStrings(args)]; @@ -155,19 +155,19 @@ export class TokenManagementTransactionsFactory { new StringValue(options.tokenName), new StringValue(options.tokenTicker), new StringValue("canFreeze"), - new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canFreeze)), new StringValue("canWipe"), - new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canWipe)), new StringValue("canPause"), - new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canPause)), new StringValue("canTransferNFTCreateRole"), - new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canTransferNFTCreateRole)), new StringValue("canChangeOwner"), - new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canChangeOwner)), new StringValue("canUpgrade"), - new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canUpgrade)), new StringValue("canAddSpecialRoles"), - new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canAddSpecialRoles)), ]; const dataParts = ["issueNonFungible", ...this.argSerializer.valuesToStrings(args)]; @@ -203,19 +203,19 @@ export class TokenManagementTransactionsFactory { new StringValue(options.tokenTicker), new BigUIntValue(options.numDecimals), new StringValue("canFreeze"), - new StringValue(options.canFreeze ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canFreeze)), new StringValue("canWipe"), - new StringValue(options.canWipe ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canWipe)), new StringValue("canPause"), - new StringValue(options.canPause ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canPause)), new StringValue("canTransferNFTCreateRole"), - new StringValue(options.canTransferNFTCreateRole ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canTransferNFTCreateRole)), new StringValue("canChangeOwner"), - new StringValue(options.canChangeOwner ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canChangeOwner)), new StringValue("canUpgrade"), - new StringValue(options.canUpgrade ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canUpgrade)), new StringValue("canAddSpecialRoles"), - new StringValue(options.canAddSpecialRoles ? this.trueAsString : this.falseAsString), + new StringValue(this.boolToString(options.canAddSpecialRoles)), ]; const dataParts = ["registerMetaESDT", ...this.argSerializer.valuesToStrings(args)]; @@ -264,7 +264,7 @@ export class TokenManagementTransactionsFactory { createTransactionForSettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = [ "setBurnRoleGlobally", - this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ...this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)]), ]; return new TransactionBuilder({ @@ -280,7 +280,7 @@ export class TokenManagementTransactionsFactory { createTransactionForUnsettingBurnRoleGlobally(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = [ "unsetBurnRoleGlobally", - this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ...this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)]), ]; return new TransactionBuilder({ @@ -302,8 +302,8 @@ export class TokenManagementTransactionsFactory { }): Transaction { const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; - options.addRoleLocalMint ? args.push(new StringValue("ESDTRoleLocalMint")) : args.push(...[]); - options.addRoleLocalBurn ? args.push(new StringValue("ESDTRoleLocalBurn")) : args.push(...[]); + options.addRoleLocalMint ? args.push(new StringValue("ESDTRoleLocalMint")) : 0; + options.addRoleLocalBurn ? args.push(new StringValue("ESDTRoleLocalBurn")) : 0; const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; @@ -328,10 +328,10 @@ export class TokenManagementTransactionsFactory { }): Transaction { const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; - options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : args.push(...[]); - options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : args.push(...[]); - options.addRoleNFTAddQuantity ? args.push(new StringValue("ESDTRoleNFTAddQuantity")) : args.push(...[]); - options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : args.push(...[]); + options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : 0; + options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : 0; + options.addRoleNFTAddQuantity ? args.push(new StringValue("ESDTRoleNFTAddQuantity")) : 0; + options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : 0; const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; @@ -369,13 +369,11 @@ export class TokenManagementTransactionsFactory { }): Transaction { const args = [new StringValue(options.tokenIdentifier), new AddressValue(options.user)]; - options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : args.push(...[]); - options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : args.push(...[]); - options.addRoleNFTUpdateAttributes - ? args.push(new StringValue("ESDTRoleNFTUpdateAttributes")) - : args.push(...[]); - options.addRoleNFTAddURI ? args.push(new StringValue("ESDTRoleNFTAddURI")) : args.push(...[]); - options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : args.push(...[]); + options.addRoleNFTCreate ? args.push(new StringValue("ESDTRoleNFTCreate")) : 0; + options.addRoleNFTBurn ? args.push(new StringValue("ESDTRoleNFTBurn")) : 0; + options.addRoleNFTUpdateAttributes ? args.push(new StringValue("ESDTRoleNFTUpdateAttributes")) : 0; + options.addRoleNFTAddURI ? args.push(new StringValue("ESDTRoleNFTAddURI")) : 0; + options.addRoleESDTTransferRole ? args.push(new StringValue("ESDTTransferRole")) : 0; const dataParts = ["setSpecialRole", ...this.argSerializer.valuesToStrings(args)]; @@ -427,7 +425,7 @@ export class TokenManagementTransactionsFactory { } createTransactionForPausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { - const dataParts = ["pause", this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0]]; + const dataParts = ["pause", ...this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])]; return new TransactionBuilder({ config: this.config, @@ -442,7 +440,7 @@ export class TokenManagementTransactionsFactory { createTransactionForUnpausing(options: { sender: IAddress; tokenIdentifier: string }): Transaction { const dataParts = [ "unPause", - this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)])[0], + ...this.argSerializer.valuesToStrings([new StringValue(options.tokenIdentifier)]), ]; return new TransactionBuilder({ @@ -645,4 +643,12 @@ IMPORTANT! You are about to issue (register) a new token. This will set the role "ESDTRoleBurnForAll" (globally). Once the token is registered, you can unset this role by calling "unsetBurnRoleGlobally" (in a separate transaction).`); } + + private boolToString(value: boolean): string { + if (value) { + return this.trueAsString; + } + + return this.falseAsString; + } } diff --git a/src/transactionsFactories/transactionBuilder.ts b/src/transactionsFactories/transactionBuilder.ts index 910bfb2aa..6c163e816 100644 --- a/src/transactionsFactories/transactionBuilder.ts +++ b/src/transactionsFactories/transactionBuilder.ts @@ -9,6 +9,9 @@ interface Config { gasLimitPerByte: bigint; } +/** + * @internal + */ export class TransactionBuilder { private config: Config; private sender: IAddress; diff --git a/src/transactionsFactories/transferTransactionsFactory.ts b/src/transactionsFactories/transferTransactionsFactory.ts index 8148549a9..4a431bea7 100644 --- a/src/transactionsFactories/transferTransactionsFactory.ts +++ b/src/transactionsFactories/transferTransactionsFactory.ts @@ -106,15 +106,14 @@ export class TransferTransactionsFactory { const data = options.data || new Uint8Array(); - return new TransactionBuilder({ - config: this.config!, - sender: options.sender, - receiver: options.receiver, - dataParts: [Buffer.from(data).toString("utf8")], - gasLimit: 0n, - addDataMovementGas: true, - amount: options.nativeAmount, - }).build(); + return new Transaction({ + sender: options.sender.bech32(), + receiver: options.receiver.bech32(), + chainID: this.config!.chainID, + gasLimit: this.computeGasForMoveBalance(this.config!, data), + data: data, + value: options.nativeAmount, + }); } createTransactionForESDTTokenTransfer(options: { @@ -362,4 +361,8 @@ export class TransferTransactionsFactory { addDataMovementGas: true, }).build(); } + + private computeGasForMoveBalance(config: IConfig, data: Uint8Array): bigint { + return config.minGasLimit + config.gasLimitPerByte * BigInt(data.length); + } } From 3d45e2178f33caee957f35f6abddcb9752327a77 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 27 Mar 2024 16:33:59 +0200 Subject: [PATCH 243/275] remove dependency from smart contract transactions factory --- src/smartcontracts/interaction.ts | 15 +++--- .../smartContract.local.net.spec.ts | 53 ++++++++++--------- src/smartcontracts/smartContract.ts | 4 -- .../smartContractTransactionsFactory.spec.ts | 4 +- .../smartContractTransactionsFactory.ts | 10 ++-- 5 files changed, 38 insertions(+), 48 deletions(-) diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index 6eb1245fe..19a22ca5e 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -3,7 +3,7 @@ import { Address } from "../address"; import { Compatibility } from "../compatibility"; import { TRANSACTION_VERSION_DEFAULT } from "../constants"; import { IAddress, IChainID, IGasLimit, IGasPrice, INonce, ITokenTransfer, ITransactionValue } from "../interface"; -import { TokenComputer, TokenTransfer } from "../tokens"; +import { TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { SmartContractTransactionsFactory, TransactionsFactoryConfig } from "../transactionsFactories"; import { ContractFunction } from "./function"; @@ -46,11 +46,7 @@ export class Interaction { private tokenTransfers: TokenTransfer[]; - constructor( - contract: ISmartContractWithinInteraction, - func: ContractFunction, - args: TypedValue[] - ) { + constructor(contract: ISmartContractWithinInteraction, func: ContractFunction, args: TypedValue[]) { this.contract = contract; this.function = func; this.args = args; @@ -90,12 +86,15 @@ export class Interaction { } buildTransaction(): Transaction { - Compatibility.guardAddressIsSetAndNonZero(this.sender, "'sender' of interaction", "use interaction.withSender()"); + Compatibility.guardAddressIsSetAndNonZero( + this.sender, + "'sender' of interaction", + "use interaction.withSender()", + ); const factoryConfig = new TransactionsFactoryConfig({ chainID: this.chainID.valueOf() }); const factory = new SmartContractTransactionsFactory({ config: factoryConfig, - tokenComputer: new TokenComputer(), }); const transaction = factory.createTransactionForExecute({ diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index 2951df137..d03c260ed 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -12,7 +12,6 @@ import { AddressValue, BigUIntValue, OptionalValue, OptionValue, TokenIdentifier import { BytesValue } from "./typesystem/bytes"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; -import { TokenComputer } from "../tokens"; import { promises } from "fs"; import { TransactionComputer } from "../transactionComputer"; @@ -26,7 +25,9 @@ describe("test on local testnet", function () { ({ alice, bob, carol } = await loadTestWallets()); watcher = new TransactionWatcher({ - getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true) } + getTransaction: async (hash: string) => { + return await provider.getTransaction(hash, true); + }, }); }); @@ -48,7 +49,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // ++ @@ -56,7 +57,7 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 3000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrement.setNonce(alice.account.nonce); transactionIncrement.applySignature(await alice.signer.sign(transactionIncrement.serializeForSigning())); @@ -68,7 +69,7 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 100000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); simulateOne.setSender(alice.address); @@ -76,7 +77,7 @@ describe("test on local testnet", function () { func: new ContractFunction("foobar"), gasLimit: 500000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); simulateTwo.setSender(alice.address); @@ -123,7 +124,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/counter.wasm", gasLimit: 3000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // ++ @@ -131,10 +132,12 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 2000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrementFirst.setNonce(alice.account.nonce); - transactionIncrementFirst.applySignature(await alice.signer.sign(transactionIncrementFirst.serializeForSigning())); + transactionIncrementFirst.applySignature( + await alice.signer.sign(transactionIncrementFirst.serializeForSigning()), + ); alice.account.incrementNonce(); @@ -143,10 +146,12 @@ describe("test on local testnet", function () { func: new ContractFunction("increment"), gasLimit: 2000000, chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); transactionIncrementSecond.setNonce(alice.account.nonce); - transactionIncrementSecond.applySignature(await alice.signer.sign(transactionIncrementSecond.serializeForSigning())); + transactionIncrementSecond.applySignature( + await alice.signer.sign(transactionIncrementSecond.serializeForSigning()), + ); alice.account.incrementNonce(); @@ -183,7 +188,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/erc20.wasm", gasLimit: 50000000, initArguments: [new U32Value(10000)], - chainID: network.ChainID + chainID: network.ChainID, }); // Minting @@ -192,7 +197,7 @@ describe("test on local testnet", function () { gasLimit: 9000000, args: [new AddressValue(bob.address), new U32Value(1000)], chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); let transactionMintCarol = contract.call({ @@ -200,7 +205,7 @@ describe("test on local testnet", function () { gasLimit: 9000000, args: [new AddressValue(carol.address), new U32Value(1500)], chainID: network.ChainID, - caller: alice.address + caller: alice.address, }); // Apply nonces and sign the remaining transactions @@ -228,7 +233,7 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(alice.address)] + args: [new AddressValue(alice.address)], }); queryResponse = await provider.queryContract(query); @@ -236,7 +241,7 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(bob.address)] + args: [new AddressValue(bob.address)], }); queryResponse = await provider.queryContract(query); @@ -244,7 +249,7 @@ describe("test on local testnet", function () { query = contract.createQuery({ func: new ContractFunction("balanceOf"), - args: [new AddressValue(carol.address)] + args: [new AddressValue(carol.address)], }); queryResponse = await provider.queryContract(query); @@ -269,7 +274,7 @@ describe("test on local testnet", function () { codePath: "src/testdata/lottery-esdt.wasm", gasLimit: 50000000, initArguments: [], - chainID: network.ChainID + chainID: network.ChainID, }); // Start @@ -285,7 +290,7 @@ describe("test on local testnet", function () { OptionValue.newProvided(new U32Value(1)), OptionValue.newMissing(), OptionValue.newMissing(), - OptionalValue.newMissing() + OptionalValue.newMissing(), ], chainID: network.ChainID, caller: alice.address, @@ -314,18 +319,14 @@ describe("test on local testnet", function () { // Query state, do some assertions let query = contract.createQuery({ func: new ContractFunction("status"), - args: [ - BytesValue.fromUTF8("lucky") - ] + args: [BytesValue.fromUTF8("lucky")], }); let queryResponse = await provider.queryContract(query); assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 1); query = contract.createQuery({ func: new ContractFunction("status"), - args: [ - BytesValue.fromUTF8("missingLottery") - ] + args: [BytesValue.fromUTF8("missingLottery")], }); queryResponse = await provider.queryContract(query); assert.equal(decodeUnsignedNumber(queryResponse.getReturnDataParts()[0]), 0); @@ -342,7 +343,7 @@ describe("test on local testnet", function () { const transactionComputer = new TransactionComputer(); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new SmartContractTransactionsFactory({ config: config }); let bytecode = await promises.readFile("src/testdata/counter.wasm"); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index a43c60042..1189f2684 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -4,7 +4,6 @@ import { Compatibility } from "../compatibility"; import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; import { ErrContractHasNoAddress } from "../errors"; import { IAddress, INonce } from "../interface"; -import { TokenComputer } from "../tokens"; import { Transaction } from "../transaction"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; @@ -121,7 +120,6 @@ export class SmartContract implements ISmartContract { const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, - tokenComputer: new TokenComputer() }); const bytecode = Buffer.from(code.toString(), 'hex'); @@ -180,7 +178,6 @@ export class SmartContract implements ISmartContract { const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, - tokenComputer: new TokenComputer() }); const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); @@ -217,7 +214,6 @@ export class SmartContract implements ISmartContract { const factory = new SmartContractTransactionsFactory({ config: config, abi: this.abi, - tokenComputer: new TokenComputer() }); args = args || []; diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index a0d5e16af..fb853125c 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -6,7 +6,7 @@ import { U32Value } from "../smartcontracts"; import { Code } from "../smartcontracts/code"; import { AbiRegistry } from "../smartcontracts/typesystem/abiRegistry"; import { loadAbiRegistry, loadContractCode } from "../testutils/utils"; -import { Token, TokenComputer, TokenTransfer } from "../tokens"; +import { Token, TokenTransfer } from "../tokens"; import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; @@ -20,7 +20,6 @@ describe("test smart contract transactions factory", function () { before(async function () { smartContractFactory = new SmartContractTransactionsFactory({ config: config, - tokenComputer: new TokenComputer(), }); adderByteCode = await loadContractCode("src/testdata/adder.wasm"); @@ -29,7 +28,6 @@ describe("test smart contract transactions factory", function () { abiAwareFactory = new SmartContractTransactionsFactory({ config: config, abi: abiRegistry, - tokenComputer: new TokenComputer(), }); }); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index d7a9d6d78..ca0894e2e 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -4,7 +4,7 @@ import { Err, ErrBadUsage } from "../errors"; import { IAddress } from "../interface"; import { ArgSerializer, CodeMetadata, ContractFunction, EndpointDefinition } from "../smartcontracts"; import { NativeSerializer } from "../smartcontracts/nativeSerializer"; -import { Token, TokenTransfer } from "../tokens"; +import { TokenComputer, TokenTransfer } from "../tokens"; import { Transaction } from "../transaction"; import { byteArrayToHex, utf8ToHex } from "../utils.codec"; import { TokenTransfersDataBuilder } from "./tokenTransfersDataBuilder"; @@ -22,10 +22,6 @@ interface IAbi { getEndpoint(name: string | ContractFunction): EndpointDefinition; } -interface TokenComputer { - isFungible(token: Token): boolean; -} - /** * Use this class to create transactions to deploy, call or upgrade a smart contract. */ @@ -35,10 +31,10 @@ export class SmartContractTransactionsFactory { private readonly tokenComputer: TokenComputer; private readonly dataArgsBuilder: TokenTransfersDataBuilder; - constructor(options: { config: Config; abi?: IAbi; tokenComputer: TokenComputer }) { + constructor(options: { config: Config; abi?: IAbi }) { this.config = options.config; this.abi = options.abi; - this.tokenComputer = options.tokenComputer; + this.tokenComputer = new TokenComputer(); this.dataArgsBuilder = new TokenTransfersDataBuilder(); } From 98cd6a35aacda1edaf5300adf1132da7e69deb7f Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 28 Mar 2024 11:52:06 +0200 Subject: [PATCH 244/275] implement address computer --- src/address.spec.ts | 31 +++++++- src/address.ts | 76 +++++++++++++++++++ src/constants.ts | 3 + src/smartcontracts/smartContract.ts | 3 +- .../transactionPayloadBuilders.ts | 3 +- 5 files changed, 111 insertions(+), 5 deletions(-) diff --git a/src/address.spec.ts b/src/address.spec.ts index 48313ab04..ff1da62dc 100644 --- a/src/address.spec.ts +++ b/src/address.spec.ts @@ -1,5 +1,5 @@ import { assert } from "chai"; -import { Address } from "./address"; +import { Address, AddressComputer } from "./address"; import * as errors from "./errors"; describe("test address", () => { @@ -67,4 +67,33 @@ describe("test address", () => { Address.fromBech32("erd1qqqqqqqqqqqqqpgqxwakt2g7u9atsnr03gqcgmhcv38pt7mkd94q6shuwt").isSmartContract(), ); }); + + it("should contract address", () => { + const addressComputer = new AddressComputer(); + const deployer = Address.fromBech32("erd1j0hxzs7dcyxw08c4k2nv9tfcaxmqy8rj59meq505w92064x0h40qcxh3ap"); + + let contractAddress = addressComputer.computeContractAddress(deployer, 0n); + assert.equal(contractAddress.toHex(), "00000000000000000500bb652200ed1f994200ab6699462cab4b1af7b11ebd5e"); + assert.equal(contractAddress.toBech32(), "erd1qqqqqqqqqqqqqpgqhdjjyq8dr7v5yq9tv6v5vt9tfvd00vg7h40q6779zn"); + + contractAddress = addressComputer.computeContractAddress(deployer, 1n); + assert.equal(contractAddress.toHex(), "000000000000000005006e4f90488e27342f9a46e1809452c85ee7186566bd5e"); + assert.equal(contractAddress.toBech32(), "erd1qqqqqqqqqqqqqpgqde8eqjywyu6zlxjxuxqfg5kgtmn3setxh40qen8egy"); + }); + + it("should get address shard", () => { + const addressComputer = new AddressComputer(); + + let address = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + let shard = addressComputer.getShardOfAddress(address); + assert.equal(shard, 1); + + address = Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"); + shard = addressComputer.getShardOfAddress(address); + assert.equal(shard, 0); + + address = Address.fromBech32("erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8"); + shard = addressComputer.getShardOfAddress(address); + assert.equal(shard, 2); + }); }); diff --git a/src/address.ts b/src/address.ts index a5b3fda5d..49e358e92 100644 --- a/src/address.ts +++ b/src/address.ts @@ -1,5 +1,9 @@ import * as bech32 from "bech32"; import * as errors from "./errors"; +import { CURRENT_NUMBER_OF_SHARDS_WITHOUT_META, METACHAIN_ID, WasmVirtualMachine } from "./constants"; +import BigNumber from "bignumber.js"; +import { bigIntToBuffer } from "./tokenOperations/codec"; +const createKeccakHash = require("keccak"); /** * The human-readable-part of the bech32 addresses. @@ -13,6 +17,11 @@ const PUBKEY_LENGTH = 32; const SMART_CONTRACT_HEX_PUBKEY_PREFIX = "0".repeat(16); +interface IAddress { + getPublicKey(): Buffer; + getHrp(): string; +} + /** * An Address, as an immutable object. */ @@ -259,3 +268,70 @@ export class Address { return this.toHex().startsWith(SMART_CONTRACT_HEX_PUBKEY_PREFIX); } } + +export class AddressComputer { + private readonly numberOfShardsWithoutMeta: number; + + constructor(numberOfShardsWithoutMeta?: number) { + this.numberOfShardsWithoutMeta = numberOfShardsWithoutMeta || CURRENT_NUMBER_OF_SHARDS_WITHOUT_META; + } + + computeContractAddress(deployer: IAddress, deploymentNonce: bigint): Address { + let initialPadding = Buffer.alloc(8, 0); + let ownerPubkey = deployer.getPublicKey(); + let shardSelector = ownerPubkey.slice(30); + let ownerNonceBytes = Buffer.alloc(8); + + const bigNonce = new BigNumber(deploymentNonce.toString()); + const bigNonceBuffer = bigIntToBuffer(bigNonce); + ownerNonceBytes.write(bigNonceBuffer.reverse().toString("hex"), "hex"); + + let bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); + let hash = createKeccakHash("keccak256").update(bytesToHash).digest(); + let vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); + let addressBytes = Buffer.concat([initialPadding, vmTypeBytes, hash.slice(10, 30), shardSelector]); + + let address = new Address(addressBytes); + return address; + } + + getShardOfAddress(address: IAddress): number { + return this.getShardOfPubkey(address.getPublicKey(), this.numberOfShardsWithoutMeta); + } + + private getShardOfPubkey(pubkey: Uint8Array, numberOfShards: number): number { + const maskHigh: number = parseInt("11", 2); + const maskLow: number = parseInt("01", 2); + + const lastByteOfPubkey: number = pubkey[31]; + + if (this.isPubkeyOfMetachain(pubkey)) { + return METACHAIN_ID; + } + + let shard: number = lastByteOfPubkey & maskHigh; + if (shard > numberOfShards - 1) { + shard = lastByteOfPubkey & maskLow; + } + + return shard; + } + + private isPubkeyOfMetachain(pubkey: Uint8Array): boolean { + const metachainPrefix = Buffer.from([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + const pubkeyPrefix = Buffer.from(pubkey).slice(0, metachainPrefix.length); + + if (metachainPrefix.equals(pubkeyPrefix)) { + return true; + } + + const zeroAddress = Buffer.alloc(32); + if (zeroAddress.equals(Buffer.from(pubkey))) { + return true; + } + + return false; + } +} diff --git a/src/constants.ts b/src/constants.ts index 826563261..ac9a02cae 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -19,3 +19,6 @@ export const DEFAULT_MESSAGE_VERSION = 1; export const MESSAGE_PREFIX = "\x17Elrond Signed Message:\n"; export const HEX_TRANSACTION_HASH_LENGTH = 64; export const BECH32_ADDRESS_LENGTH = 62; +export const CURRENT_NUMBER_OF_SHARDS_WITHOUT_META = 3; +export const WasmVirtualMachine = "0500"; +export const METACHAIN_ID = 4294967295; diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 1189f2684..c1fb2c8f6 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -1,7 +1,7 @@ import BigNumber from "bignumber.js"; import { Address } from "../address"; import { Compatibility } from "../compatibility"; -import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; +import { TRANSACTION_MIN_GAS_PRICE, WasmVirtualMachine } from "../constants"; import { ErrContractHasNoAddress } from "../errors"; import { IAddress, INonce } from "../interface"; import { Transaction } from "../transaction"; @@ -15,7 +15,6 @@ import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; -import { WasmVirtualMachine } from "./transactionPayloadBuilders"; import { EndpointDefinition, TypedValue } from "./typesystem"; const createKeccakHash = require("keccak"); diff --git a/src/smartcontracts/transactionPayloadBuilders.ts b/src/smartcontracts/transactionPayloadBuilders.ts index 4234381f6..215b9e729 100644 --- a/src/smartcontracts/transactionPayloadBuilders.ts +++ b/src/smartcontracts/transactionPayloadBuilders.ts @@ -1,11 +1,10 @@ +import { WasmVirtualMachine } from "../constants"; import { TransactionPayload } from "../transactionPayload"; import { guardValueIsSet } from "../utils"; import { ArgSerializer } from "./argSerializer"; import { ICode, ICodeMetadata, IContractFunction } from "./interface"; import { TypedValue } from "./typesystem"; -export const WasmVirtualMachine = "0500"; - /** * @deprecated Use {@link SmartContractTransactionsFactory} instead. * From f9eae9fd3d9fcc62acc15bf71cb2adc265b97c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 13:20:34 +0200 Subject: [PATCH 245/275] Sketch parsing of deploy transaction. --- .../smartContractTransactionsOutcomeParser.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index eede9d6f3..97e57311c 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -1,6 +1,7 @@ +import { Address } from "../address"; import { Err } from "../errors"; import { EndpointDefinition, ResultsParser, ReturnCode, Type, UntypedOutcomeBundle } from "../smartcontracts"; -import { TransactionOutcome } from "./resources"; +import { TransactionEvent, TransactionOutcome, findEventsByIdentifier } from "./resources"; interface IAbi { getEndpoint(name: string): EndpointDefinition; @@ -35,6 +36,34 @@ export class SmartContractTransactionsOutcomeParser { this.legacyResultsParser = options?.legacyResultsParser || new ResultsParser(); } + parseDeploy(options: { transactionOutcome: TransactionOutcome }): { + values: any[]; + returnCode: string; + returnMessage: string; + addresses: string[]; + } { + const directCallOutcome = options.transactionOutcome.directSmartContractCallOutcome; + const events = findEventsByIdentifier(options.transactionOutcome, "SCDeploy"); + const addresses = events.map((event) => this.extractContractAddress(event)); + + return { + values: directCallOutcome.returnDataParts, + returnCode: directCallOutcome.returnCode, + returnMessage: directCallOutcome.returnMessage, + addresses: addresses, + }; + } + + private extractContractAddress(event: TransactionEvent): string { + const firstTopic = event.topics[0]; + + if (!firstTopic?.length) { + return ""; + } + + return Address.fromBuffer(Buffer.from(firstTopic)).toBech32(); + } + parseExecute(options: { transactionOutcome: TransactionOutcome; function?: string }): { values: any[]; returnCode: string; From 316e439fd578b1e92af4f6b16eea30e23bd3b329 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 28 Mar 2024 13:20:49 +0200 Subject: [PATCH 246/275] fixes after review --- src/address.ts | 19 +++++++++--------- src/smartcontracts/smartContract.ts | 31 +++++------------------------ 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/src/address.ts b/src/address.ts index 49e358e92..051e8b00b 100644 --- a/src/address.ts +++ b/src/address.ts @@ -277,22 +277,21 @@ export class AddressComputer { } computeContractAddress(deployer: IAddress, deploymentNonce: bigint): Address { - let initialPadding = Buffer.alloc(8, 0); - let ownerPubkey = deployer.getPublicKey(); - let shardSelector = ownerPubkey.slice(30); - let ownerNonceBytes = Buffer.alloc(8); + const initialPadding = Buffer.alloc(8, 0); + const ownerPubkey = deployer.getPublicKey(); + const shardSelector = ownerPubkey.slice(30); + const ownerNonceBytes = Buffer.alloc(8); const bigNonce = new BigNumber(deploymentNonce.toString()); const bigNonceBuffer = bigIntToBuffer(bigNonce); ownerNonceBytes.write(bigNonceBuffer.reverse().toString("hex"), "hex"); - let bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); - let hash = createKeccakHash("keccak256").update(bytesToHash).digest(); - let vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); - let addressBytes = Buffer.concat([initialPadding, vmTypeBytes, hash.slice(10, 30), shardSelector]); + const bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); + const hash = createKeccakHash("keccak256").update(bytesToHash).digest(); + const vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); + const addressBytes = Buffer.concat([initialPadding, vmTypeBytes, hash.slice(10, 30), shardSelector]); - let address = new Address(addressBytes); - return address; + return new Address(addressBytes); } getShardOfAddress(address: IAddress): number { diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index c1fb2c8f6..8f6bdf620 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -1,7 +1,6 @@ -import BigNumber from "bignumber.js"; -import { Address } from "../address"; +import { Address, AddressComputer } from "../address"; import { Compatibility } from "../compatibility"; -import { TRANSACTION_MIN_GAS_PRICE, WasmVirtualMachine } from "../constants"; +import { TRANSACTION_MIN_GAS_PRICE } from "../constants"; import { ErrContractHasNoAddress } from "../errors"; import { IAddress, INonce } from "../interface"; import { Transaction } from "../transaction"; @@ -9,14 +8,12 @@ import { SmartContractTransactionsFactory } from "../transactionsFactories/smart import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { guardValueIsSet } from "../utils"; import { CodeMetadata } from "./codeMetadata"; -import { bigIntToBuffer } from "./codec/utils"; import { ContractFunction } from "./function"; import { Interaction } from "./interaction"; import { CallArguments, DeployArguments, ICodeMetadata, ISmartContract, QueryArguments, UpgradeArguments } from "./interface"; import { NativeSerializer } from "./nativeSerializer"; import { Query } from "./query"; import { EndpointDefinition, TypedValue } from "./typesystem"; -const createKeccakHash = require("keccak"); interface IAbi { constructorDefinition: EndpointDefinition; @@ -259,26 +256,8 @@ export class SmartContract implements ISmartContract { * @param nonce The owner nonce used for the deployment transaction */ static computeAddress(owner: IAddress, nonce: INonce): IAddress { - let initialPadding = Buffer.alloc(8, 0); - let ownerPubkey = new Address(owner.bech32()).pubkey(); - let shardSelector = ownerPubkey.slice(30); - let ownerNonceBytes = Buffer.alloc(8); - - const bigNonce = new BigNumber(nonce.valueOf().toString(10)); - const bigNonceBuffer = bigIntToBuffer(bigNonce); - ownerNonceBytes.write(bigNonceBuffer.reverse().toString('hex'), 'hex'); - - let bytesToHash = Buffer.concat([ownerPubkey, ownerNonceBytes]); - let hash = createKeccakHash("keccak256").update(bytesToHash).digest(); - let vmTypeBytes = Buffer.from(WasmVirtualMachine, "hex"); - let addressBytes = Buffer.concat([ - initialPadding, - vmTypeBytes, - hash.slice(10, 30), - shardSelector - ]); - - let address = new Address(addressBytes); - return address; + const deployer = new Address(owner.bech32()); + const addressComputer = new AddressComputer(); + return addressComputer.computeContractAddress(deployer, BigInt(nonce.valueOf())); } } From 215ea7acea1bad0c218bb1637ac6525577a11f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 13:21:21 +0200 Subject: [PATCH 247/275] Remove arbitrary constraint in "findEventsByIdentifier". --- src/transactionsOutcomeParsers/resources.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 60ae05bc1..93a4d1e5f 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -1,5 +1,3 @@ -import { ErrParseTransactionOutcome } from "../errors"; - export class TransactionEvent { address: string; identifier: string; @@ -82,13 +80,7 @@ export function findEventsByPredicate( } export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, identifier: string): TransactionEvent[] { - const events = findEventsByPredicate(transactionOutcome, (event) => event.identifier == identifier); - - if (events.length == 0) { - throw new ErrParseTransactionOutcome(`cannot find event of type ${identifier}`); - } - - return events; + return findEventsByPredicate(transactionOutcome, (event) => event.identifier == identifier); } export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { From be4ecc302d13acdf380a9084768a53a13d9d15fa Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 28 Mar 2024 13:27:31 +0200 Subject: [PATCH 248/275] use new approach to instantiate address --- src/smartcontracts/smartContract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 8f6bdf620..85d83b849 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -256,7 +256,7 @@ export class SmartContract implements ISmartContract { * @param nonce The owner nonce used for the deployment transaction */ static computeAddress(owner: IAddress, nonce: INonce): IAddress { - const deployer = new Address(owner.bech32()); + const deployer = Address.fromBech32(owner.bech32()); const addressComputer = new AddressComputer(); return addressComputer.computeContractAddress(deployer, BigInt(nonce.valueOf())); } From 4c601f17fb459646444f8f1f591abab5f15b03c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 14:05:15 +0200 Subject: [PATCH 249/275] Parse deploy events. --- ...tContractTransactionsOutcomeParser.spec.ts | 42 ++++++++++++++++++- .../smartContractTransactionsOutcomeParser.ts | 36 +++++++++++----- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index 92491168a..bedf61576 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -1,12 +1,52 @@ import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@multiversx/sdk-network-providers"; import BigNumber from "bignumber.js"; import { assert } from "chai"; +import { Address } from "../address"; import { TransactionsConverter } from "../converters/transactionsConverter"; import { loadAbiRegistry } from "../testutils"; -import { SmartContractCallOutcome, TransactionOutcome } from "./resources"; +import { SmartContractCallOutcome, TransactionEvent, TransactionLogs, TransactionOutcome } from "./resources"; import { SmartContractTransactionsOutcomeParser } from "./smartContractTransactionsOutcomeParser"; describe("test smart contract transactions outcome parser", () => { + it("parses deploy outcome (minimalistic)", async function () { + const parser = new SmartContractTransactionsOutcomeParser(); + + const parsed = parser.parseDeploy({ + transactionOutcome: new TransactionOutcome({ + directSmartContractCallOutcome: new SmartContractCallOutcome({ + returnCode: "ok", + returnMessage: "ok", + }), + logs: new TransactionLogs({ + events: [ + new TransactionEvent({ + identifier: "SCDeploy", + topics: [ + Address.fromBech32( + "erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj", + ).getPublicKey(), + Address.fromBech32( + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + ).getPublicKey(), + Buffer.from("abba", "hex"), + ], + }), + ], + }), + }), + }); + + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + assert.deepEqual(parsed.contracts, [ + { + address: "erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj", + ownerAddress: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + codeHash: Buffer.from("abba", "hex"), + }, + ]); + }); + it("parses execute outcome, without ABI (minimalistic)", function () { const parser = new SmartContractTransactionsOutcomeParser(); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 97e57311c..72f612d43 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -37,31 +37,45 @@ export class SmartContractTransactionsOutcomeParser { } parseDeploy(options: { transactionOutcome: TransactionOutcome }): { - values: any[]; returnCode: string; returnMessage: string; - addresses: string[]; + contracts: { + address: string; + ownerAddress: string; + codeHash: Uint8Array; + }[]; } { const directCallOutcome = options.transactionOutcome.directSmartContractCallOutcome; const events = findEventsByIdentifier(options.transactionOutcome, "SCDeploy"); - const addresses = events.map((event) => this.extractContractAddress(event)); + const contracts = events.map((event) => this.parseScDeployEvent(event)); return { - values: directCallOutcome.returnDataParts, returnCode: directCallOutcome.returnCode, returnMessage: directCallOutcome.returnMessage, - addresses: addresses, + contracts: contracts, }; } - private extractContractAddress(event: TransactionEvent): string { - const firstTopic = event.topics[0]; + private parseScDeployEvent(event: TransactionEvent): { + address: string; + ownerAddress: string; + codeHash: Uint8Array; + } { + const topicForAddress = event.topics[0]; + const topicForOwnerAddress = event.topics[1]; + const topicForCodeHash = event.topics[2]; - if (!firstTopic?.length) { - return ""; - } + const address = topicForAddress?.length ? Address.fromBuffer(Buffer.from(topicForAddress)).toBech32() : ""; + const ownerAddress = topicForOwnerAddress?.length + ? Address.fromBuffer(Buffer.from(topicForOwnerAddress)).toBech32() + : ""; + const codeHash = topicForCodeHash; - return Address.fromBuffer(Buffer.from(firstTopic)).toBech32(); + return { + address, + ownerAddress, + codeHash, + }; } parseExecute(options: { transactionOutcome: TransactionOutcome; function?: string }): { From 6bac43654902e1618d3c967060daabb50e5c1f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 14:39:04 +0200 Subject: [PATCH 250/275] Extra tests. --- ...tContractTransactionsOutcomeParser.spec.ts | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index bedf61576..46d7085c3 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -1,4 +1,11 @@ -import { ContractResultItem, ContractResults, TransactionOnNetwork } from "@multiversx/sdk-network-providers"; +import { + ContractResultItem, + ContractResults, + TransactionEventTopic, + TransactionOnNetwork, + TransactionEvent as TransactionOnNetworkEvent, + TransactionLogs as TransactionOnNetworkLogs, +} from "@multiversx/sdk-network-providers"; import BigNumber from "bignumber.js"; import { assert } from "chai"; import { Address } from "../address"; @@ -9,6 +16,10 @@ import { SmartContractTransactionsOutcomeParser } from "./smartContractTransacti describe("test smart contract transactions outcome parser", () => { it("parses deploy outcome (minimalistic)", async function () { + const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj"); + const codeHash = Buffer.from("abba", "hex"); + const parser = new SmartContractTransactionsOutcomeParser(); const parsed = parser.parseDeploy({ @@ -21,15 +32,7 @@ describe("test smart contract transactions outcome parser", () => { events: [ new TransactionEvent({ identifier: "SCDeploy", - topics: [ - Address.fromBech32( - "erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj", - ).getPublicKey(), - Address.fromBech32( - "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - ).getPublicKey(), - Buffer.from("abba", "hex"), - ], + topics: [contract.getPublicKey(), deployer.getPublicKey(), codeHash], }), ], }), @@ -40,9 +43,47 @@ describe("test smart contract transactions outcome parser", () => { assert.equal(parsed.returnMessage, "ok"); assert.deepEqual(parsed.contracts, [ { - address: "erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj", - ownerAddress: "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - codeHash: Buffer.from("abba", "hex"), + address: contract.toBech32(), + ownerAddress: deployer.toBech32(), + codeHash: codeHash, + }, + ]); + }); + + it("parses deploy outcome", async function () { + const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj"); + const codeHash = Buffer.from("abba", "hex"); + + const parser = new SmartContractTransactionsOutcomeParser(); + const transactionsConverter = new TransactionsConverter(); + + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + logs: new TransactionOnNetworkLogs({ + events: [ + new TransactionOnNetworkEvent({ + identifier: "SCDeploy", + topics: [ + new TransactionEventTopic(deployer.getPublicKey().toString("base64")), + new TransactionEventTopic(contract.getPublicKey().toString("base64")), + new TransactionEventTopic(codeHash.toString("base64")), + ], + }), + ], + }), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const parsed = parser.parseDeploy({ transactionOutcome }); + + assert.equal(parsed.returnCode, "ok"); + assert.equal(parsed.returnMessage, "ok"); + assert.deepEqual(parsed.contracts, [ + { + address: contract.toBech32(), + ownerAddress: deployer.toBech32(), + codeHash: codeHash, }, ]); }); From d97cce82bd7bd77bf6642d44eae60275f7fefafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 14:45:10 +0200 Subject: [PATCH 251/275] Fix tests. --- .../smartContractTransactionsOutcomeParser.spec.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index 46d7085c3..eeed8ddee 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -16,8 +16,8 @@ import { SmartContractTransactionsOutcomeParser } from "./smartContractTransacti describe("test smart contract transactions outcome parser", () => { it("parses deploy outcome (minimalistic)", async function () { - const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj"); + const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const codeHash = Buffer.from("abba", "hex"); const parser = new SmartContractTransactionsOutcomeParser(); @@ -51,8 +51,8 @@ describe("test smart contract transactions outcome parser", () => { }); it("parses deploy outcome", async function () { - const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const contract = Address.fromBech32("erd1qqqqqqqqqqqqqpgqqacl85rd0gl2q8wggl8pwcyzcr4fflc5d8ssve45cj"); + const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const codeHash = Buffer.from("abba", "hex"); const parser = new SmartContractTransactionsOutcomeParser(); @@ -65,13 +65,19 @@ describe("test smart contract transactions outcome parser", () => { new TransactionOnNetworkEvent({ identifier: "SCDeploy", topics: [ - new TransactionEventTopic(deployer.getPublicKey().toString("base64")), new TransactionEventTopic(contract.getPublicKey().toString("base64")), + new TransactionEventTopic(deployer.getPublicKey().toString("base64")), new TransactionEventTopic(codeHash.toString("base64")), ], }), ], }), + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b", + }), + ]), }); const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); From 4d6aa6ef3ecd609a79e254b5c00d7383f13c4731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 14:45:40 +0200 Subject: [PATCH 252/275] Address constructor: accept Uint8Array, as well. --- src/address.spec.ts | 11 +++++++---- src/address.ts | 10 +++++----- .../smartContractTransactionsOutcomeParser.ts | 6 ++---- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/address.spec.ts b/src/address.spec.ts index ff1da62dc..7acbd9994 100644 --- a/src/address.spec.ts +++ b/src/address.spec.ts @@ -9,11 +9,14 @@ describe("test address", () => { let bobHex = "8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8"; it("should create address", async () => { - let alice = new Address(aliceBech32); - let bob = new Address(bobBech32); + assert.equal(new Address(aliceBech32).toHex(), aliceHex); + assert.equal(new Address(bobBech32).toHex(), bobHex); + + assert.equal(new Address(Buffer.from(aliceHex, "hex")).toHex(), aliceHex); + assert.equal(new Address(Buffer.from(bobHex, "hex")).toHex(), bobHex); - assert.equal(alice.hex(), aliceHex); - assert.equal(bob.hex(), bobHex); + assert.equal(new Address(new Uint8Array(Buffer.from(aliceHex, "hex"))).toHex(), aliceHex); + assert.equal(new Address(new Uint8Array(Buffer.from(bobHex, "hex"))).toHex(), bobHex); }); it("should create empty address", async () => { diff --git a/src/address.ts b/src/address.ts index 051e8b00b..e694c001b 100644 --- a/src/address.ts +++ b/src/address.ts @@ -1,7 +1,7 @@ import * as bech32 from "bech32"; -import * as errors from "./errors"; -import { CURRENT_NUMBER_OF_SHARDS_WITHOUT_META, METACHAIN_ID, WasmVirtualMachine } from "./constants"; import BigNumber from "bignumber.js"; +import { CURRENT_NUMBER_OF_SHARDS_WITHOUT_META, METACHAIN_ID, WasmVirtualMachine } from "./constants"; +import * as errors from "./errors"; import { bigIntToBuffer } from "./tokenOperations/codec"; const createKeccakHash = require("keccak"); @@ -32,15 +32,15 @@ export class Address { /** * Creates an address object, given a raw string (whether a hex pubkey or a Bech32 address), a sequence of bytes, or another Address object. */ - public constructor(value: Address | Buffer | string) { + public constructor(value: Address | Buffer | Uint8Array | string) { if (!value) { return; } if (value instanceof Address) { return Address.fromAddress(value); } - if (value instanceof Buffer) { - return Address.fromBuffer(value); + if (ArrayBuffer.isView(value)) { + return Address.fromBuffer(Buffer.from(value)); } if (typeof value === "string") { return Address.fromString(value); diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts index 72f612d43..7c240504c 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.ts @@ -65,10 +65,8 @@ export class SmartContractTransactionsOutcomeParser { const topicForOwnerAddress = event.topics[1]; const topicForCodeHash = event.topics[2]; - const address = topicForAddress?.length ? Address.fromBuffer(Buffer.from(topicForAddress)).toBech32() : ""; - const ownerAddress = topicForOwnerAddress?.length - ? Address.fromBuffer(Buffer.from(topicForOwnerAddress)).toBech32() - : ""; + const address = topicForAddress?.length ? new Address(topicForAddress).toBech32() : ""; + const ownerAddress = topicForOwnerAddress?.length ? new Address(topicForOwnerAddress).toBech32() : ""; const codeHash = topicForCodeHash; return { From 7980fec45cd7696775384199b6c500b5c5dd845b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 15:59:32 +0200 Subject: [PATCH 253/275] Additional tests. --- src/converters/transactionsConverter.ts | 2 +- ...tContractTransactionsOutcomeParser.spec.ts | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/converters/transactionsConverter.ts b/src/converters/transactionsConverter.ts index 046740716..2f0df2813 100644 --- a/src/converters/transactionsConverter.ts +++ b/src/converters/transactionsConverter.ts @@ -117,7 +117,7 @@ export class TransactionsConverter { // Before Sirius, there was no "additionalData" field on transaction logs. // After Sirius, the "additionalData" field includes the payload of the legacy "data" field, as well (as its first element): // https://github.com/multiversx/mx-chain-go/blob/v1.6.18/process/transactionLog/process.go#L159 - const legacyData = eventOnNetwork.dataPayload?.valueOf() || Buffer.from([]); + const legacyData = eventOnNetwork.dataPayload?.valueOf() || Buffer.from(eventOnNetwork.data || ""); const dataItems = eventOnNetwork.additionalData?.map((data) => Buffer.from(data.valueOf())) || []; if (dataItems.length === 0) { diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index eeed8ddee..8a187af4e 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -94,6 +94,36 @@ describe("test smart contract transactions outcome parser", () => { ]); }); + it.only("parses deploy outcome (with error)", async function () { + const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + + const parser = new SmartContractTransactionsOutcomeParser(); + const transactionsConverter = new TransactionsConverter(); + + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + logs: new TransactionOnNetworkLogs({ + events: [ + new TransactionOnNetworkEvent({ + identifier: "signalError", + topics: [ + new TransactionEventTopic(deployer.getPublicKey().toString("base64")), + new TransactionEventTopic(Buffer.from("wrong number of arguments").toString("base64")), + ], + data: "@75736572206572726f72", + }), + ], + }), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const parsed = parser.parseDeploy({ transactionOutcome }); + + assert.equal(parsed.returnCode, "user error"); + assert.equal(parsed.returnMessage, "wrong number of arguments"); + assert.deepEqual(parsed.contracts, []); + }); + it("parses execute outcome, without ABI (minimalistic)", function () { const parser = new SmartContractTransactionsOutcomeParser(); From 0932d36ac5f89b25f86c4dd0ed88c558f1f69ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Thu, 28 Mar 2024 16:00:59 +0200 Subject: [PATCH 254/275] Undo "it.only()". --- .../smartContractTransactionsOutcomeParser.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts index 8a187af4e..5bbcbdd52 100644 --- a/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts +++ b/src/transactionsOutcomeParsers/smartContractTransactionsOutcomeParser.spec.ts @@ -94,7 +94,7 @@ describe("test smart contract transactions outcome parser", () => { ]); }); - it.only("parses deploy outcome (with error)", async function () { + it("parses deploy outcome (with error)", async function () { const deployer = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const parser = new SmartContractTransactionsOutcomeParser(); From 1ba2a1d13700c30ea8921470b09743983628df7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 30 Mar 2024 20:03:58 +0200 Subject: [PATCH 255/275] Additional exports. --- package-lock.json | 4 ++-- package.json | 2 +- src/index.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index af1070cee..5e0fa2fe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.13", + "version": "13.0.0-beta.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.13", + "version": "13.0.0-beta.14", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index ee253e162..1c0908597 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.13", + "version": "13.0.0-beta.14", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/index.ts b/src/index.ts index 385c250a8..74fc1a8fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,10 @@ require("./globals"); export * from "./account"; +export * from "./adapters"; export * from "./address"; export * from "./asyncTimer"; +export * from "./converters"; export * from "./errors"; export * from "./gasEstimator"; export * from "./interface"; From 24055859b832db94388d7e78897eba6d9a3da8ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 30 Mar 2024 20:07:50 +0200 Subject: [PATCH 256/275] Re-generate docs (as for v12). --- .github/workflows/update-docs.yml | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/update-docs.yml diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml new file mode 100644 index 000000000..3613a44cc --- /dev/null +++ b/.github/workflows/update-docs.yml @@ -0,0 +1,50 @@ +name: Update docs + +on: + workflow_dispatch: + release: + types: [released] + pull_request: + branches: [ main, development, feat/* ] + +permissions: + contents: write + +jobs: + update-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + with: + ref: "gh-pages" + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: "docs" + + - uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + run: | + npm install -g typedoc + + - name: Re-generate docs + run: | + MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") + DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} + + mkdir -p $DOCS_OUTPUT_FOLDER + + npm ci + typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion + + cd ${GITHUB_WORKSPACE}/docs + + # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token + git config user.name github-actions + git config user.email github-actions@github.com + git commit -am "Re-generated docs." --allow-empty + git push \ No newline at end of file From 58bd52b665922cb6100f900bc78bba5415fbeb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 30 Mar 2024 20:25:25 +0200 Subject: [PATCH 257/275] Attempt to fix exports. --- .github/workflows/update-docs.yml | 87 ++++++++++++++++--------------- src/converters/index.ts | 2 +- src/index.ts | 1 + 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 3613a44cc..882ab0c8b 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -1,50 +1,51 @@ name: Update docs on: - workflow_dispatch: - release: - types: [released] - pull_request: - branches: [ main, development, feat/* ] + workflow_dispatch: + release: + types: [released] + pull_request: + branches: [main, development, feat/*] permissions: - contents: write + contents: write jobs: - update-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/checkout@v4 - with: - ref: "gh-pages" - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: "docs" - - - uses: actions/setup-node@v4 - with: - node-version: 18 - registry-url: https://registry.npmjs.org/ - - - name: Install dependencies - run: | - npm install -g typedoc - - - name: Re-generate docs - run: | - MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") - DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} - - mkdir -p $DOCS_OUTPUT_FOLDER - - npm ci - typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion - - cd ${GITHUB_WORKSPACE}/docs - - # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token - git config user.name github-actions - git config user.email github-actions@github.com - git commit -am "Re-generated docs." --allow-empty - git push \ No newline at end of file + update-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + with: + ref: "gh-pages" + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: "docs" + + - uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + run: | + npm install -g typedoc + + - name: Re-generate docs + run: | + MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") + DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} + + rm -rf $DOCS_OUTPUT_FOLDER + mkdir -p $DOCS_OUTPUT_FOLDER + + npm ci + typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion + + cd ${GITHUB_WORKSPACE}/docs + + # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token + git config user.name github-actions + git config user.email github-actions@github.com + git commit -am "Re-generated docs." --allow-empty + git push diff --git a/src/converters/index.ts b/src/converters/index.ts index f0f6ba906..f43e67fcc 100644 --- a/src/converters/index.ts +++ b/src/converters/index.ts @@ -1 +1 @@ -export { TransactionsConverter } from "./transactionsConverter"; +export * from "./transactionsConverter"; diff --git a/src/index.ts b/src/index.ts index 74fc1a8fe..36dc54937 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export * from "./gasEstimator"; export * from "./interface"; export * from "./interfaceOfNetwork"; export * from "./logger"; +export * from "./message"; export * from "./networkParams"; export * from "./relayedTransactionV1Builder"; export * from "./relayedTransactionV2Builder"; From 8d8206b9f50a88fe2ca10a70c8d439f25f40acf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 30 Mar 2024 20:40:55 +0200 Subject: [PATCH 258/275] Fix workflow. --- .github/workflows/update-docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 882ab0c8b..17205f1c1 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -47,5 +47,6 @@ jobs: # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token git config user.name github-actions git config user.email github-actions@github.com - git commit -am "Re-generated docs." --allow-empty + git add . + git commit -m "Re-generated docs." --allow-empty git push From 36ed4fb5f12c6bffc49311469089b9114dad822b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 1 Apr 2024 11:11:57 +0300 Subject: [PATCH 259/275] Fix indent. --- .editorconfig | 3 ++ .github/workflows/update-docs.yml | 83 ++++++++++++++++--------------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/.editorconfig b/.editorconfig index 25437d3b4..c2b51d9ab 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,6 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 + +[*.yml] +indent_size = 2 diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 17205f1c1..47cd2bd88 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -1,52 +1,53 @@ name: Update docs on: - workflow_dispatch: + workflow_dispatch: release: - types: [released] - pull_request: + types: [released] + pull_request: branches: [main, development, feat/*] permissions: - contents: write - -jobs: + contents: write + + jobs: update-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/checkout@v4 - with: - ref: "gh-pages" - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: "docs" - - - uses: actions/setup-node@v4 - with: - node-version: 18 - registry-url: https://registry.npmjs.org/ - + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + with: + ref: "gh-pages" + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: "docs" + + - uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + - name: Install dependencies - run: | - npm install -g typedoc - + run: | + npm install -g typedoc + - name: Re-generate docs run: | - MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") - DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} - - rm -rf $DOCS_OUTPUT_FOLDER - mkdir -p $DOCS_OUTPUT_FOLDER - - npm ci - typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion - - cd ${GITHUB_WORKSPACE}/docs - - # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token - git config user.name github-actions - git config user.email github-actions@github.com - git add . - git commit -m "Re-generated docs." --allow-empty - git push + MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") + DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} + + rm -rf $DOCS_OUTPUT_FOLDER + mkdir -p $DOCS_OUTPUT_FOLDER + + npm ci + typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion + + cd ${GITHUB_WORKSPACE}/docs + + # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token + git config user.name github-actions + git config user.email github-actions@github.com + git add . + git commit -m "Re-generated docs." --allow-empty + git push + \ No newline at end of file From ceb860c77b33a28ff1d563b3e545813b92fcb3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 1 Apr 2024 12:46:03 +0300 Subject: [PATCH 260/275] Undo formatting. --- .github/workflows/update-docs.yml | 84 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index c4e8ed9a5..ac3f00dab 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -1,49 +1,49 @@ name: Update docs on: - workflow_dispatch: - release: - types: [released] + workflow_dispatch: + release: + types: [released] permissions: - contents: write + contents: write jobs: - update-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/checkout@v4 - with: - ref: "gh-pages" - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: "docs" - - - uses: actions/setup-node@v4 - with: - node-version: 18 - registry-url: https://registry.npmjs.org/ - - - name: Install dependencies - run: | - npm install -g typedoc - - - name: Re-generate docs - run: | - MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") - DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} - - mkdir -p $DOCS_OUTPUT_FOLDER - - npm ci - typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion - - cd ${GITHUB_WORKSPACE}/docs - - # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token - git config user.name github-actions - git config user.email github-actions@github.com - git add . - git commit -m "Re-generated docs." --allow-empty - git push + update-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + with: + ref: "gh-pages" + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: "docs" + + - uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + run: | + npm install -g typedoc + + - name: Re-generate docs + run: | + MAJOR_VERSION=v$(node -p "require('./package.json').version.split('.')[0]") + DOCS_OUTPUT_FOLDER=${GITHUB_WORKSPACE}/docs/${MAJOR_VERSION} + + mkdir -p $DOCS_OUTPUT_FOLDER + + npm ci + typedoc --out $DOCS_OUTPUT_FOLDER src/index.ts --includeVersion + + cd ${GITHUB_WORKSPACE}/docs + + # See: https://github.com/actions/checkout/blob/main/README.md#push-a-commit-using-the-built-in-token + git config user.name github-actions + git config user.email github-actions@github.com + git add . + git commit -m "Re-generated docs." --allow-empty + git push From 60f2279c9fb976aae05b476db7385209a9350b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 1 Apr 2024 12:46:15 +0300 Subject: [PATCH 261/275] Undo formatting. --- .editorconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index c2b51d9ab..eeb94cd48 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,5 +10,3 @@ insert_final_newline = true indent_style = space indent_size = 4 -[*.yml] -indent_size = 2 From e76ff2b14a17e6318093e43ecb7357f4fa214091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Mon, 1 Apr 2024 12:46:45 +0300 Subject: [PATCH 262/275] Undo formatting. --- .editorconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index eeb94cd48..25437d3b4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,4 +9,3 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 - From 841d0effaaf542dfb3544cda2d8a6879c486004f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 2 Apr 2024 13:46:54 +0300 Subject: [PATCH 263/275] Export SmartContractQueriesController. --- package-lock.json | 4 ++-- package.json | 2 +- src/index.ts | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e0fa2fe3..4f81b5c8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.14", + "version": "13.0.0-beta.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.14", + "version": "13.0.0-beta.15", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 1c0908597..753538a95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.14", + "version": "13.0.0-beta.15", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/index.ts b/src/index.ts index 51d34f22b..bfc9a49c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,7 @@ export * from "./networkParams"; export * from "./relayedTransactionV1Builder"; export * from "./relayedTransactionV2Builder"; export * from "./signableMessage"; +export * from "./smartContractQueriesController"; export * from "./smartcontracts"; export * from "./tokenOperations"; export * from "./tokens"; From c326211513c40abe541ddc5cc235487d9305ff20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 2 Apr 2024 16:25:49 +0300 Subject: [PATCH 264/275] Rename parameters wrt. specs: function, arguments. --- package-lock.json | 4 +- package.json | 2 +- src/smartContractQueriesController.spec.ts | 2 +- src/smartcontracts/interaction.ts | 4 +- .../smartContract.local.net.spec.ts | 2 +- src/smartcontracts/smartContract.ts | 26 ++++----- .../smartContractTransactionsFactory.spec.ts | 58 +++++++++---------- .../smartContractTransactionsFactory.ts | 18 +++--- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4f81b5c8b..bf54b9f9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.15", + "version": "13.0.0-beta.16", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.15", + "version": "13.0.0-beta.16", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 753538a95..6a1534a4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.15", + "version": "13.0.0-beta.16", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index b1e6861c2..5030c3637 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -1,12 +1,12 @@ import { ContractQueryResponse } from "@multiversx/sdk-network-providers"; import BigNumber from "bignumber.js"; import { assert } from "chai"; +import { QueryRunnerAdapter } from "./adapters/queryRunnerAdapter"; import { SmartContractQueriesController } from "./smartContractQueriesController"; import { SmartContractQueryResponse } from "./smartContractQuery"; import { AbiRegistry, BigUIntValue, BooleanValue, BytesValue, Tuple, U16Value, U64Value } from "./smartcontracts"; import { bigIntToBuffer } from "./smartcontracts/codec/utils"; import { MockNetworkProvider, loadAbiRegistry } from "./testutils"; -import { QueryRunnerAdapter } from "./adapters/queryRunnerAdapter"; describe("test smart contract queries controller", () => { describe("createQuery", () => { diff --git a/src/smartcontracts/interaction.ts b/src/smartcontracts/interaction.ts index 19a22ca5e..2568dc7dc 100644 --- a/src/smartcontracts/interaction.ts +++ b/src/smartcontracts/interaction.ts @@ -100,9 +100,9 @@ export class Interaction { const transaction = factory.createTransactionForExecute({ sender: this.sender, contract: this.contract.getAddress(), - functionName: this.function.valueOf(), + function: this.function.valueOf(), gasLimit: BigInt(this.gasLimit.valueOf()), - args: this.args, + arguments: this.args, nativeTransferAmount: BigInt(this.value.toString()), tokenTransfers: this.tokenTransfers, }); diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index d03c260ed..30f3521c8 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -367,7 +367,7 @@ describe("test on local testnet", function () { const smartContractCallTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 2000000n, }); smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); diff --git a/src/smartcontracts/smartContract.ts b/src/smartcontracts/smartContract.ts index 85d83b849..de24dde2c 100644 --- a/src/smartcontracts/smartContract.ts +++ b/src/smartcontracts/smartContract.ts @@ -118,23 +118,23 @@ export class SmartContract implements ISmartContract { abi: this.abi, }); - const bytecode = Buffer.from(code.toString(), 'hex'); + const bytecode = Buffer.from(code.toString(), "hex"); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); const transaction = factory.createTransactionForDeploy({ sender: deployer, bytecode: bytecode, gasLimit: BigInt(gasLimit.valueOf()), - args: initArguments, + arguments: initArguments, isUpgradeable: metadataAsJson.upgradeable, isReadable: metadataAsJson.readable, isPayable: metadataAsJson.payable, - isPayableBySmartContract: metadataAsJson.payableBySc + isPayableBySmartContract: metadataAsJson.payableBySc, }); transaction.setChainID(chainID); transaction.setValue(value ?? 0); - transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE); return transaction; } @@ -176,7 +176,7 @@ export class SmartContract implements ISmartContract { abi: this.abi, }); - const bytecode = Uint8Array.from(Buffer.from(code.toString(), 'hex')); + const bytecode = Uint8Array.from(Buffer.from(code.toString(), "hex")); const metadataAsJson = this.getMetadataPropertiesAsObject(codeMetadata); const transaction = factory.createTransactionForUpgrade({ @@ -184,16 +184,16 @@ export class SmartContract implements ISmartContract { contract: this.getAddress(), bytecode: bytecode, gasLimit: BigInt(gasLimit.valueOf()), - args: initArguments, + arguments: initArguments, isUpgradeable: metadataAsJson.upgradeable, isReadable: metadataAsJson.readable, isPayable: metadataAsJson.payable, - isPayableBySmartContract: metadataAsJson.payableBySc - }) + isPayableBySmartContract: metadataAsJson.payableBySc, + }); transaction.setChainID(chainID); transaction.setValue(value ?? 0); - transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE); return transaction; } @@ -218,14 +218,14 @@ export class SmartContract implements ISmartContract { const transaction = factory.createTransactionForExecute({ sender: caller, contract: receiver ? receiver : this.getAddress(), - functionName: func.toString(), + function: func.toString(), gasLimit: BigInt(gasLimit.valueOf()), - args: args - }) + arguments: args, + }); transaction.setChainID(chainID); transaction.setValue(value); - transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE) + transaction.setGasPrice(gasPrice ?? TRANSACTION_MIN_GAS_PRICE); return transaction; } diff --git a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts index fb853125c..5b1f771bf 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.spec.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.spec.ts @@ -42,7 +42,7 @@ describe("test smart contract transactions factory", function () { sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args, + arguments: args, }), Err, "Can't convert args to TypedValues", @@ -58,14 +58,14 @@ describe("test smart contract transactions factory", function () { sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args, + arguments: args, }); const transactionAbiAware = abiAwareFactory.createTransactionForDeploy({ sender: sender, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args, + arguments: args, }); assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -87,17 +87,17 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, }); assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); @@ -119,18 +119,18 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: [new U32Value(7)], + arguments: [new U32Value(7)], nativeTransferAmount: egldAmount, }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: [7], + arguments: [7], nativeTransferAmount: egldAmount, }); @@ -155,18 +155,18 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [transfer], }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [transfer], }); @@ -194,18 +194,18 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [fooTransfer, barTransfer], }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [fooTransfer, barTransfer], }); @@ -238,18 +238,18 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [transfer], }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [transfer], }); @@ -285,18 +285,18 @@ describe("test smart contract transactions factory", function () { const transaction = smartContractFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [firstTransfer, secondTransfer], }); const transactionAbiAware = abiAwareFactory.createTransactionForExecute({ sender: sender, contract: contract, - functionName: func, + function: func, gasLimit: gasLimit, - args: args, + arguments: args, tokenTransfers: [firstTransfer, secondTransfer], }); @@ -328,7 +328,7 @@ describe("test smart contract transactions factory", function () { contract: contract, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args, + arguments: args, }); const transactionAbiAware = abiAwareFactory.createTransactionForUpgrade({ @@ -336,7 +336,7 @@ describe("test smart contract transactions factory", function () { contract: contract, bytecode: adderByteCode.valueOf(), gasLimit: gasLimit, - args: args, + arguments: args, }); assert.equal(transaction.sender, "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); diff --git a/src/transactionsFactories/smartContractTransactionsFactory.ts b/src/transactionsFactories/smartContractTransactionsFactory.ts index ca0894e2e..832d8ae3a 100644 --- a/src/transactionsFactories/smartContractTransactionsFactory.ts +++ b/src/transactionsFactories/smartContractTransactionsFactory.ts @@ -42,7 +42,7 @@ export class SmartContractTransactionsFactory { sender: IAddress; bytecode: Uint8Array; gasLimit: bigint; - args?: any[]; + arguments?: any[]; nativeTransferAmount?: bigint; isUpgradeable?: boolean; isReadable?: boolean; @@ -54,7 +54,7 @@ export class SmartContractTransactionsFactory { const isReadable = options.isReadable ?? true; const isPayable = options.isPayable ?? false; const isPayableBySmartContract = options.isPayableBySmartContract ?? true; - const args = options.args || []; + const args = options.arguments || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = [byteArrayToHex(options.bytecode), byteArrayToHex(VM_TYPE_WASM_VM), metadata.toString()]; const preparedArgs = this.argsToDataParts(args, this.abi?.constructorDefinition); @@ -74,13 +74,13 @@ export class SmartContractTransactionsFactory { createTransactionForExecute(options: { sender: IAddress; contract: IAddress; - functionName: string; + function: string; gasLimit: bigint; - args?: any[]; + arguments?: any[]; nativeTransferAmount?: bigint; tokenTransfers?: TokenTransfer[]; }): Transaction { - const args = options.args || []; + const args = options.arguments || []; const tokenTransfer = options.tokenTransfers || []; const nativeTransferAmount = options.nativeTransferAmount ?? 0n; const numberOfTokens = tokenTransfer.length; @@ -106,8 +106,8 @@ export class SmartContractTransactionsFactory { receiver = options.sender; } - dataParts.push(dataParts.length ? utf8ToHex(options.functionName) : options.functionName); - dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.functionName))); + dataParts.push(dataParts.length ? utf8ToHex(options.function) : options.function); + dataParts = dataParts.concat(this.argsToDataParts(args, this.abi?.getEndpoint(options.function))); return new TransactionBuilder({ config: this.config, @@ -125,7 +125,7 @@ export class SmartContractTransactionsFactory { contract: IAddress; bytecode: Uint8Array; gasLimit: bigint; - args?: any[]; + arguments?: any[]; nativeTransferAmount?: bigint; isUpgradeable?: boolean; isReadable?: boolean; @@ -139,7 +139,7 @@ export class SmartContractTransactionsFactory { const isPayable = options.isPayable ?? false; const isPayableBySmartContract = options.isPayableBySmartContract ?? true; - const args = options.args || []; + const args = options.arguments || []; const metadata = new CodeMetadata(isUpgradeable, isReadable, isPayable, isPayableBySmartContract); let parts = ["upgradeContract", byteArrayToHex(options.bytecode), metadata.toString()]; From 5820ce4ef18edc3bf9d8ea9069877bd68bd4eeab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 2 Apr 2024 16:42:31 +0300 Subject: [PATCH 265/275] Adjust output of queries controller. --- src/smartContractQueriesController.spec.ts | 5 ++--- src/smartContractQueriesController.ts | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/smartContractQueriesController.spec.ts b/src/smartContractQueriesController.spec.ts index 5030c3637..c65309833 100644 --- a/src/smartContractQueriesController.spec.ts +++ b/src/smartContractQueriesController.spec.ts @@ -232,10 +232,9 @@ describe("test smart contract queries controller", () => { ], }); - const parsed = controller.parseQueryResponse(response); - const plainData = parsed[0].valueOf(); + const [parsed] = controller.parseQueryResponse(response); - assert.deepEqual(plainData, { + assert.deepEqual(parsed, { token_identifier: "lucky-token", ticket_price: new BigNumber("1"), tickets_left: new BigNumber(0), diff --git a/src/smartContractQueriesController.ts b/src/smartContractQueriesController.ts index b676b09c4..233d83371 100644 --- a/src/smartContractQueriesController.ts +++ b/src/smartContractQueriesController.ts @@ -100,6 +100,7 @@ export class SmartContractQueriesController { const functionName = response.function; const endpoint = this.abi.getEndpoint(functionName); const legacyBundle = this.legacyResultsParser.parseQueryResponse(legacyQueryResponse, endpoint); - return legacyBundle.values; + const nativeValues = legacyBundle.values.map((value) => value.valueOf()); + return nativeValues; } } From 11755422e326de524eacceb6ec9c2f32f2415757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 17:43:33 +0300 Subject: [PATCH 266/275] Fix decision on event identifier to be used for parsing. --- .../transactionEventsParser.spec.ts | 7 ++++--- .../transactionEventsParser.ts | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts index f709cc9bb..d31e2ee81 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts @@ -102,17 +102,18 @@ describe("test transaction events parser", () => { events: [ new TransactionEvent({ identifier: "foobar", + topics: [Buffer.from("doFoobar")], }), ], }); - }, "Invariant failed: [event [foobar] not found]"); + }, "Invariant failed: [event [doFoobar] not found]"); }); it("parses event (with multi-values)", async function () { const abi = AbiRegistry.create({ events: [ { - identifier: "foobar", + identifier: "doFoobar", inputs: [ { name: "a", @@ -139,7 +140,7 @@ describe("test transaction events parser", () => { event: new TransactionEvent({ identifier: "foobar", topics: [ - Buffer.from("foobar"), + Buffer.from("doFoobar"), Buffer.from([42]), Buffer.from("test"), Buffer.from([43]), diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts index 326d65cfe..4288d8812 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -17,9 +17,9 @@ export class TransactionEventsParser { // By default, we consider that the first topic is the event identifier. // This is true for log entries emitted by smart contracts: + // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L270 // https://github.com/multiversx/mx-chain-vm-go/blob/v1.5.27/vmhost/contexts/output.go#L283 - this.firstTopicIsIdentifier = - options.firstTopicIsIdentifier === undefined ? true : options.firstTopicIsIdentifier; + this.firstTopicIsIdentifier = options.firstTopicIsIdentifier ?? true; } parseEvents(options: { events: TransactionEvent[] }): any[] { @@ -35,14 +35,15 @@ export class TransactionEventsParser { parseEvent(options: { event: TransactionEvent }): any { const topics = options.event.topics.map((topic) => Buffer.from(topic)); - const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); - const eventDefinition = this.abi.getEvent(options.event.identifier); + const eventIdentifier = this.firstTopicIsIdentifier ? topics[0]?.toString() : options.event.identifier; if (this.firstTopicIsIdentifier) { - // Discard the first topic (not useful). topics.shift(); } + const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); + const eventDefinition = this.abi.getEvent(eventIdentifier); + const parsedEvent = this.legacyResultsParser.doParseEvent({ topics: topics, dataItems: dataItems, From 09cac50d6df1f34dae72f0d716df4255e50504d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 17:43:42 +0300 Subject: [PATCH 267/275] Rename file. --- ...ry.test.net.spec.ts => tokenOperationsFactory.testnet.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tokenOperations/{tokenOperationsFactory.test.net.spec.ts => tokenOperationsFactory.testnet.spec.ts} (100%) diff --git a/src/tokenOperations/tokenOperationsFactory.test.net.spec.ts b/src/tokenOperations/tokenOperationsFactory.testnet.spec.ts similarity index 100% rename from src/tokenOperations/tokenOperationsFactory.test.net.spec.ts rename to src/tokenOperations/tokenOperationsFactory.testnet.spec.ts From 65453ce10140e2597abe7c92bd91efebde7776cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 17:44:11 +0300 Subject: [PATCH 268/275] Use latest multisig for tests. --- ...ltisig.abi.json => multisig-full.abi.json} | 999 ++++++++++++++---- src/testdata/multisig-full.wasm | Bin 0 -> 26610 bytes 2 files changed, 768 insertions(+), 231 deletions(-) rename src/testdata/{multisig.abi.json => multisig-full.abi.json} (57%) create mode 100644 src/testdata/multisig-full.wasm diff --git a/src/testdata/multisig.abi.json b/src/testdata/multisig-full.abi.json similarity index 57% rename from src/testdata/multisig.abi.json rename to src/testdata/multisig-full.abi.json index 01a363c5a..401de7cc0 100644 --- a/src/testdata/multisig.abi.json +++ b/src/testdata/multisig-full.abi.json @@ -1,19 +1,20 @@ { "buildInfo": { "rustc": { - "version": "1.59.0-nightly", - "commitHash": "399ba6bb377ce02224b57c4d6e127e160fa76b34", - "commitDate": "2022-01-03", + "version": "1.71.0-nightly", + "commitHash": "a2b1646c597329d0a25efa3889b66650f65de1de", + "commitDate": "2023-05-25", "channel": "Nightly", - "short": "rustc 1.59.0-nightly (399ba6bb3 2022-01-03)" + "short": "rustc 1.71.0-nightly (a2b1646c5 2023-05-25)" }, "contractCrate": { "name": "multisig", - "version": "1.0.0" + "version": "1.0.0", + "gitVersion": "v0.45.2.1-reproducible-169-g37d970c" }, "framework": { - "name": "elrond-wasm", - "version": "0.25.0" + "name": "multiversx-sc", + "version": "0.47.2" } }, "docs": [ @@ -38,127 +39,30 @@ }, "endpoints": [ { - "docs": [ - "Allows the contract to receive funds even if it is marked as unpayable in the protocol." - ], - "name": "deposit", + "name": "upgrade", "mutability": "mutable", - "payableInTokens": [ - "*" - ], "inputs": [], "outputs": [] }, { "docs": [ - "Iterates through all actions and retrieves those that are still pending.", - "Serialized full action data:", - "- the action id", - "- the serialized action data", - "- (number of signers followed by) list of signer addresses." - ], - "name": "getPendingActionFullInfo", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "variadic", - "multi_result": true - } - ] - }, - { - "docs": [ - "Returns `true` (`1`) if the user has signed the action.", - "Does not check whether or not the user is still a board member and the signature valid." - ], - "name": "signed", - "mutability": "readonly", - "inputs": [ - { - "name": "user", - "type": "Address" - }, - { - "name": "action_id", - "type": "u32" - } - ], - "outputs": [ - { - "type": "bool" - } - ] - }, - { - "docs": [ - "Indicates user rights.", - "`0` = no rights,", - "`1` = can propose, but not sign,", - "`2` = can propose and sign." - ], - "name": "userRole", - "mutability": "readonly", - "inputs": [ - { - "name": "user", - "type": "Address" - } - ], - "outputs": [ - { - "type": "UserRole" - } - ] - }, - { - "docs": [ - "Lists all users that can sign actions." - ], - "name": "getAllBoardMembers", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "variadic
", - "multi_result": true - } - ] - }, - { - "docs": [ - "Lists all proposers that are not board members." - ], - "name": "getAllProposers", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "variadic
", - "multi_result": true - } - ] - }, - { - "docs": [ - "Used by board members to sign actions." + "Allows the contract to receive funds even if it is marked as unpayable in the protocol." ], - "name": "sign", + "name": "deposit", "mutability": "mutable", - "inputs": [ - { - "name": "action_id", - "type": "u32" - } + "payableInTokens": [ + "*" ], + "inputs": [], "outputs": [] }, { "docs": [ - "Board members can withdraw their signatures if they no longer desire for the action to be executed.", - "Actions that are left with no valid signatures can be then deleted to free up storage." + "Clears storage pertaining to an action that is no longer supposed to be executed.", + "Any signatures that the action received must first be removed, via `unsign`.", + "Otherwise this endpoint would be prone to abuse." ], - "name": "unsign", + "name": "discardAction", "mutability": "mutable", "inputs": [ { @@ -170,16 +74,15 @@ }, { "docs": [ - "Clears storage pertaining to an action that is no longer supposed to be executed.", - "Any signatures that the action received must first be removed, via `unsign`.", - "Otherwise this endpoint would be prone to abuse." + "Discard all the actions with the given IDs" ], - "name": "discardAction", + "name": "discardBatch", "mutability": "mutable", "inputs": [ { - "name": "action_id", - "type": "u32" + "name": "action_ids", + "type": "variadic", + "multi_arg": true } ], "outputs": [] @@ -212,11 +115,7 @@ ] }, { - "docs": [ - "Denormalized proposer count.", - "It is kept in sync with the user list by the contract." - ], - "name": "getNumProposers", + "name": "getNumGroups", "mutability": "readonly", "inputs": [], "outputs": [ @@ -227,10 +126,10 @@ }, { "docs": [ - "The index of the last proposed action.", - "0 means that no action was ever proposed yet." + "Denormalized proposer count.", + "It is kept in sync with the user list by the contract." ], - "name": "getActionLastIndex", + "name": "getNumProposers", "mutability": "readonly", "inputs": [], "outputs": [ @@ -240,56 +139,25 @@ ] }, { - "docs": [ - "Serialized action data of an action with index." - ], - "name": "getActionData", - "mutability": "readonly", - "inputs": [ - { - "name": "action_id", - "type": "u32" - } - ], - "outputs": [ - { - "type": "Action" - } - ] - }, - { - "docs": [ - "Gets addresses of all users who signed an action.", - "Does not check if those users are still board members or not,", - "so the result may contain invalid signers." - ], - "name": "getActionSigners", + "name": "getActionGroup", "mutability": "readonly", "inputs": [ { - "name": "action_id", + "name": "group_id", "type": "u32" } ], "outputs": [ { - "type": "List
" + "type": "variadic", + "multi_result": true } ] }, { - "docs": [ - "Gets addresses of all users who signed an action and are still board members.", - "All these signatures are currently valid." - ], - "name": "getActionSignerCount", + "name": "getLastGroupActionId", "mutability": "readonly", - "inputs": [ - { - "name": "action_id", - "type": "u32" - } - ], + "inputs": [], "outputs": [ { "type": "u32" @@ -298,20 +166,12 @@ }, { "docs": [ - "It is possible for board members to lose their role.", - "They are not automatically removed from all actions when doing so,", - "therefore the contract needs to re-check every time when actions are performed.", - "This function is used to validate the signers before performing an action.", - "It also makes it easy to check before performing an action." + "The index of the last proposed action.", + "0 means that no action was ever proposed yet." ], - "name": "getActionValidSignerCount", + "name": "getActionLastIndex", "mutability": "readonly", - "inputs": [ - { - "name": "action_id", - "type": "u32" - } - ], + "inputs": [], "outputs": [ { "type": "u32" @@ -408,12 +268,39 @@ "type": "BigUint" }, { - "name": "opt_function", - "type": "optional", + "name": "opt_gas_limit", + "type": "Option" + }, + { + "name": "function_call", + "type": "variadic", "multi_arg": true + } + ], + "outputs": [ + { + "type": "u32" + } + ] + }, + { + "name": "proposeTransferExecuteEsdt", + "mutability": "mutable", + "inputs": [ + { + "name": "to", + "type": "Address" }, { - "name": "arguments", + "name": "tokens", + "type": "List" + }, + { + "name": "opt_gas_limit", + "type": "Option" + }, + { + "name": "function_call", "type": "variadic", "multi_arg": true } @@ -426,7 +313,7 @@ }, { "docs": [ - "Propose a transaction in which the contract will perform a transfer-execute call.", + "Propose a transaction in which the contract will perform an async call call.", "Can call smart contract endpoints directly.", "Can use ESDTTransfer/ESDTNFTTransfer/MultiESDTTransfer to send tokens, while also optionally calling endpoints.", "Works well with builtin functions.", @@ -444,12 +331,11 @@ "type": "BigUint" }, { - "name": "opt_function", - "type": "optional", - "multi_arg": true + "name": "opt_gas_limit", + "type": "Option" }, { - "name": "arguments", + "name": "function_call", "type": "variadic", "multi_arg": true } @@ -521,28 +407,51 @@ ] }, { - "docs": [ - "Returns `true` (`1`) if `getActionValidSignerCount >= getQuorum`." - ], - "name": "quorumReached", - "mutability": "readonly", + "name": "proposeBatch", + "mutability": "mutable", "inputs": [ { - "name": "action_id", - "type": "u32" + "name": "actions", + "type": "variadic", + "multi_arg": true } ], "outputs": [ { - "type": "bool" + "type": "u32" } ] }, { "docs": [ - "Proposers and board members use this to launch signed actions." + "Used by board members to sign actions." ], - "name": "performAction", + "name": "sign", + "mutability": "mutable", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "docs": [ + "Sign all the actions in the given batch" + ], + "name": "signBatch", + "mutability": "mutable", + "inputs": [ + { + "name": "group_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "name": "signAndPerform", "mutability": "mutable", "inputs": [ { @@ -552,34 +461,597 @@ ], "outputs": [ { - "type": "PerformActionResult" + "type": "optional
", + "multi_result": true } ] - } - ], - "hasCallback": false, - "types": { - "CallActionData": { - "type": "struct", - "fields": [ + }, + { + "name": "signBatchAndPerform", + "mutability": "mutable", + "inputs": [ + { + "name": "group_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "docs": [ + "Board members can withdraw their signatures if they no longer desire for the action to be executed.", + "Actions that are left with no valid signatures can be then deleted to free up storage." + ], + "name": "unsign", + "mutability": "mutable", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "docs": [ + "Unsign all actions with the given IDs" + ], + "name": "unsignBatch", + "mutability": "mutable", + "inputs": [ + { + "name": "group_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "docs": [ + "Returns `true` (`1`) if the user has signed the action.", + "Does not check whether or not the user is still a board member and the signature valid." + ], + "name": "signed", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + }, + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "bool" + } + ] + }, + { + "name": "unsignForOutdatedBoardMembers", + "mutability": "mutable", + "inputs": [ + { + "name": "action_id", + "type": "u32" + }, + { + "name": "outdated_board_members", + "type": "variadic", + "multi_arg": true + } + ], + "outputs": [] + }, + { + "docs": [ + "Returns `true` (`1`) if `getActionValidSignerCount >= getQuorum`." + ], + "name": "quorumReached", + "mutability": "readonly", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "bool" + } + ] + }, + { + "docs": [ + "Proposers and board members use this to launch signed actions." + ], + "name": "performAction", + "mutability": "mutable", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "optional
", + "multi_result": true + } + ] + }, + { + "docs": [ + "Perform all the actions in the given batch" + ], + "name": "performBatch", + "mutability": "mutable", + "inputs": [ + { + "name": "group_id", + "type": "u32" + } + ], + "outputs": [] + }, + { + "name": "dnsRegister", + "onlyOwner": true, + "mutability": "mutable", + "payableInTokens": [ + "EGLD" + ], + "inputs": [ + { + "name": "dns_address", + "type": "Address" + }, + { + "name": "name", + "type": "bytes" + } + ], + "outputs": [] + }, + { + "docs": [ + "Iterates through all actions and retrieves those that are still pending.", + "Serialized full action data:", + "- the action id", + "- the serialized action data", + "- (number of signers followed by) list of signer addresses." + ], + "name": "getPendingActionFullInfo", + "mutability": "readonly", + "inputs": [ + { + "name": "opt_range", + "type": "optional>", + "multi_arg": true + } + ], + "outputs": [ + { + "type": "variadic", + "multi_result": true + } + ], + "labels": [ + "multisig-external-view" + ], + "allow_multiple_var_args": true + }, + { + "docs": [ + "Indicates user rights.", + "`0` = no rights,", + "`1` = can propose, but not sign,", + "`2` = can propose and sign." + ], + "name": "userRole", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "UserRole" + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "Lists all users that can sign actions." + ], + "name": "getAllBoardMembers", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "variadic
", + "multi_result": true + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "Lists all proposers that are not board members." + ], + "name": "getAllProposers", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "variadic
", + "multi_result": true + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "Serialized action data of an action with index." + ], + "name": "getActionData", + "mutability": "readonly", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "Action" + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "Gets addresses of all users who signed an action.", + "Does not check if those users are still board members or not,", + "so the result may contain invalid signers." + ], + "name": "getActionSigners", + "mutability": "readonly", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "List
" + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "Gets addresses of all users who signed an action and are still board members.", + "All these signatures are currently valid." + ], + "name": "getActionSignerCount", + "mutability": "readonly", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "u32" + } + ], + "labels": [ + "multisig-external-view" + ] + }, + { + "docs": [ + "It is possible for board members to lose their role.", + "They are not automatically removed from all actions when doing so,", + "therefore the contract needs to re-check every time when actions are performed.", + "This function is used to validate the signers before performing an action.", + "It also makes it easy to check before performing an action." + ], + "name": "getActionValidSignerCount", + "mutability": "readonly", + "inputs": [ + { + "name": "action_id", + "type": "u32" + } + ], + "outputs": [ + { + "type": "u32" + } + ], + "labels": [ + "multisig-external-view" + ] + } + ], + "events": [ + { + "identifier": "asyncCallSuccess", + "inputs": [ + { + "name": "results", + "type": "variadic", + "indexed": true + } + ] + }, + { + "identifier": "asyncCallError", + "inputs": [ + { + "name": "err_code", + "type": "u32", + "indexed": true + }, + { + "name": "err_message", + "type": "bytes", + "indexed": true + } + ] + }, + { + "identifier": "startPerformAction", + "inputs": [ + { + "name": "data", + "type": "ActionFullInfo" + } + ] + }, + { + "identifier": "performChangeUser", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "changed_user", + "type": "Address", + "indexed": true + }, + { + "name": "old_role", + "type": "UserRole", + "indexed": true + }, + { + "name": "new_role", + "type": "UserRole", + "indexed": true + } + ] + }, + { + "identifier": "performChangeQuorum", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "new_quorum", + "type": "u32", + "indexed": true + } + ] + }, + { + "identifier": "performAsyncCall", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, { "name": "to", - "type": "Address" + "type": "Address", + "indexed": true }, { - "name": "egld_amount", - "type": "BigUint" + "name": "egld_value", + "type": "BigUint", + "indexed": true }, { - "name": "endpoint_name", - "type": "bytes" + "name": "gas", + "type": "u64", + "indexed": true + }, + { + "name": "endpoint", + "type": "bytes", + "indexed": true }, { "name": "arguments", - "type": "List" + "type": "variadic", + "indexed": true + } + ] + }, + { + "identifier": "performTransferExecuteEgld", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "to", + "type": "Address", + "indexed": true + }, + { + "name": "egld_value", + "type": "BigUint", + "indexed": true + }, + { + "name": "gas", + "type": "u64", + "indexed": true + }, + { + "name": "endpoint", + "type": "bytes", + "indexed": true + }, + { + "name": "arguments", + "type": "variadic", + "indexed": true + } + ] + }, + { + "identifier": "performTransferExecuteEsdt", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "to", + "type": "Address", + "indexed": true + }, + { + "name": "tokens", + "type": "List", + "indexed": true + }, + { + "name": "gas", + "type": "u64", + "indexed": true + }, + { + "name": "endpoint", + "type": "bytes", + "indexed": true + }, + { + "name": "arguments", + "type": "variadic", + "indexed": true + } + ] + }, + { + "identifier": "performDeployFromSource", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "egld_value", + "type": "BigUint", + "indexed": true + }, + { + "name": "source_address", + "type": "Address", + "indexed": true + }, + { + "name": "code_metadata", + "type": "CodeMetadata", + "indexed": true + }, + { + "name": "gas", + "type": "u64", + "indexed": true + }, + { + "name": "arguments", + "type": "variadic", + "indexed": true } ] }, + { + "identifier": "performUpgradeFromSource", + "inputs": [ + { + "name": "action_id", + "type": "u32", + "indexed": true + }, + { + "name": "target_address", + "type": "Address", + "indexed": true + }, + { + "name": "egld_value", + "type": "BigUint", + "indexed": true + }, + { + "name": "source_address", + "type": "Address", + "indexed": true + }, + { + "name": "code_metadata", + "type": "CodeMetadata", + "indexed": true + }, + { + "name": "gas", + "type": "u64", + "indexed": true + }, + { + "name": "arguments", + "type": "variadic", + "indexed": true + } + ] + } + ], + "esdtAttributes": [], + "hasCallback": true, + "types": { "Action": { "type": "enum", "variants": [ @@ -628,7 +1100,7 @@ ] }, { - "name": "SendTransferExecute", + "name": "SendTransferExecuteEgld", "discriminant": 5, "fields": [ { @@ -638,8 +1110,18 @@ ] }, { - "name": "SendAsyncCall", + "name": "SendTransferExecuteEsdt", "discriminant": 6, + "fields": [ + { + "name": "0", + "type": "EsdtTransferExecuteData" + } + ] + }, + { + "name": "SendAsyncCall", + "discriminant": 7, "fields": [ { "name": "0", @@ -649,7 +1131,7 @@ }, { "name": "SCDeployFromSource", - "discriminant": 7, + "discriminant": 8, "fields": [ { "name": "amount", @@ -671,7 +1153,7 @@ }, { "name": "SCUpgradeFromSource", - "discriminant": 8, + "discriminant": 9, "fields": [ { "name": "sc_address", @@ -707,6 +1189,10 @@ "name": "action_id", "type": "u32" }, + { + "name": "group_id", + "type": "u32" + }, { "name": "action_data", "type": "Action" @@ -717,32 +1203,83 @@ } ] }, - "PerformActionResult": { + "ActionStatus": { "type": "enum", "variants": [ { - "name": "Nothing", + "name": "Available", "discriminant": 0 }, { - "name": "DeployResult", - "discriminant": 1, - "fields": [ - { - "name": "0", - "type": "Address" - } - ] + "name": "Aborted", + "discriminant": 1 + } + ] + }, + "CallActionData": { + "type": "struct", + "fields": [ + { + "name": "to", + "type": "Address" }, { - "name": "SendAsyncCall", - "discriminant": 2, - "fields": [ - { - "name": "0", - "type": "AsyncCall" - } - ] + "name": "egld_amount", + "type": "BigUint" + }, + { + "name": "opt_gas_limit", + "type": "Option" + }, + { + "name": "endpoint_name", + "type": "bytes" + }, + { + "name": "arguments", + "type": "List" + } + ] + }, + "EsdtTokenPayment": { + "type": "struct", + "fields": [ + { + "name": "token_identifier", + "type": "TokenIdentifier" + }, + { + "name": "token_nonce", + "type": "u64" + }, + { + "name": "amount", + "type": "BigUint" + } + ] + }, + "EsdtTransferExecuteData": { + "type": "struct", + "fields": [ + { + "name": "to", + "type": "Address" + }, + { + "name": "tokens", + "type": "List" + }, + { + "name": "opt_gas_limit", + "type": "Option" + }, + { + "name": "endpoint_name", + "type": "bytes" + }, + { + "name": "arguments", + "type": "List" } ] }, diff --git a/src/testdata/multisig-full.wasm b/src/testdata/multisig-full.wasm new file mode 100644 index 0000000000000000000000000000000000000000..acb183e628c562f2c976d3d05d258baf09f7ab29 GIT binary patch literal 26610 zcmcJY3!G$EUFYw)Rn=YH)sHiiA#^5z+$u-yNM4}k z-P6-O>Bl64I5U_bj1V9qFBMo6bkH>h6kSAo<1V`@i?D*bYBu;nbeF})y67U=@9%%k zy;c2444;pifvQ{Qp7THd_xb<-=iJ-L#Nr8;B#C>Id+vSd*|W)g?yNg|U!w0s4g9E_ zRl7cQhyPc(q{Y7YnVvmk!_M62xTu{ydnWcgqaW6_a^{S{>7$ps`j3IV>dAj$qBCI% zebF!da_?xRJ$Gv8@buA}=9Uh&m-yVdBk5OTUuevyrjnX|Hx{Rl&P~kjSy-4~ND{RS zo)}*~a-_YGpFG)~n@Xx`>yK@>wI4`&yF2Zjo||4gmN>Ny$4*Q*etN0BnDm666LS+s z+fz48%+9tKl1g{aeML{3WW&++(!paB3sbir0lkIx;$nciF`!Im!Fbuk>~cGR*%&9} zPQGw-`9yneDWF^22qbhNv++bg=3p1mhSBAVCx8u~fOXfLc+#FKVK#)b?@YG8J$G~| z5`9^T+?rv=&0&bTZTUn2Yca6z(qg*6zhY=IpqWM@lAvC?c=;+?$<^C!kl_9b9r@N?t+JLlKCyD8qiVgBUlRe%eA9$cDVK$iRG zC!$^yxWpU!YDbL;d=aAy?Fg*DdtrJB2uFjmT^?z@b75j`5v4Qf?s>31xxCa)21Qgq z4BR)dxW9d5DH&43m2t@K_Q~1#)1vj@{PMzN`-b_srG<&frDUUeWwF;?Cyy>nOtshP zc8R*RVz*nDXP2f6B=#KKedld^?_7b#(B!f9{u{WyD40F>2i6v|=8LE2CS?*yz48_J56<-t zr!J98(ua@Vt|#fCRsVCnNmA_@-sEbvN>Z;TRr;xWrPtNfjsILvrRO=Wr;e&sQa-qs z)c9BLbA7H_Ph4NE;u?UeB>mND-8FhNO;WAan4wnX22iWDq-tpNC;fJp)(zZFYJS6| zE*a|8j4t8-y<9Sf>#aFZ;=@&3`t1LMjtclBm7Ys0XI*~oT)lBN$)9|p{ObK|&$gZu z?Gy70r_-d0uUbm}m+M^)I+1+Y^-i@<&M(sXH*RohdT|oxlTR*9&(9@)>jq-O_{7rW zvE=VuAENut<@tr>6UpDZjX{p%^NhH)ed2I?VKMpNZXmSoTbN%yxtRQei^hLoVV+sk z<^Q-Lx`ZjLSMn9NiI)8ni%a%9+`4Hh`A3@~{M6l>=BC;YCjaD~b20!!L%JqU{;%8E zxlzoQeAR7;t#`nKQ|-GzBKc=`No>5~*u>n?cBJWR?$X#?C}yGmPr1$O-`TS`wUnGo zeZ1Sz$JeBn#kPYttTxl+`_cm3!5h|CXYx=w5Qhf7pHHju#>s2bK7EJAhtnbb$mgaG zv=@%dFPunTmtIod?rOe}_AHw>Prg5GgsTAI^=Xg#W0r47pBHZIonN?pd1-25sol-l z#pIE6@O~5f9qkF6z*O?abns-DHtNcoz&SJo;BQVFQ*(=Vw2w|NF2V3e(-A~`fW>rr z?r0dYcUg(RRYKbj`F zJKjomrb(7Gwk7Ep-O^jDV_BM2Zyj|01xZ8y&k`Ek@ttXvE0`W`5OQ;D#LUG?lYB>C7(tFnc@%;2{*(<~WHN3+ylql>F`k&dnRFH5d*LTRYarIl)} zr?=k6>}j6(?E`(faDF?e0Ho?)I8awh+TGHtmP&U^k6NmfVvW~f)PnjhYo`mB<}v4O0TRd=R!eq}SwYGsUzkr_Vf zGk!-_xvDa9U=NI}{;W>f9GdH71HLb^63n11m>)8wGl! z>GoFDUr)ztM1uH`K>>WYg5L?G>`X_*0~$wW{EM>+n42DPQT3J0MkUH6RjcG<$G0Sn zVJT>}2iu zeg>%DvHj@3>_R4_7+J4MGV z9pCjZAF%kL@zICR>+;-JdmkDfvDS0vzB2sKc>Uq?x>3KtJvDGWqHFr8eUxj4bG7Tj z`Sa(mt<=X|Z9Hk1vImhoADpCR#y&CD`QI{@BR~J`jVri)K)NC`AC`j3${o7)Tdr}t zOIIp|A8w&yOR%g|40sx894E}3{ zPNGrism2>zaHCP5(4cAyH-;9G{|WfUglYx<8`hv$ZxUC=l)^W zxYea+(lPxj=b6u+a`z8miAf`jQpA}L`l+Nb?!<`*>tqub%FJQPlqnmR2zG#e+~#1u zo#+V|1R9Swoxi!6R?cRKMS2n2bAJnP9k)#nP=RA>c(q%+@_Qne_O9lV-xv9FC&5M_d;}0xRACZvrp;yWCnf3>X{y1t+L4F#7qinsmQ!4bk6K z+LYUph*2<6mKChY1#6;7)&vV>O%5qzO>&LKQ7#7jHh+uw=**t76n0*sCE}`9lE3rK zb-Y8*X2O)ct4zyDx5+PxWdit7x49F&fz-;DiGj_9g5`kG{20~>o8rD>F*8FG5vbg) zO@!QlEOaE8hnBI1@yq#lI{&C^yr{%V3jjtb6W7Ji4Csp^slOeOrT)N0e>Lr9TH7T> z*kKc?%Nw0y1|0XNUsKPArMyy2L&JhD{0fSnxjlmkj)^Y^=~BQfd0_&s^43BW8k)&K z(opo&cwvbf@}Ymk%|+b&9UZ(R7kt^)_3(-~NsCq@)u6W#IIy`f8*~B3rMZ&yZ2pla z>RXefl@blk?!W(0oZr zm_-Z%^?pLqM?VQ%e;$6y3Bnrl+5v(IF#4G13hT;VI8F~n{BSyK;qC^&qID*3=^UD< z$({c$U)$WcY2~CD^bE)+C>F%8&iFUm#QfNr3_x>1su7<+yjD2lvepZrzQW&Y?oEpB z8&dIaV+w8znb z1Ma_puz-1to-l%r-kWZL|)p@WrCa07wEiSLEl4WjMWo~Zl!X8Y=EY~yzR zySVS?`ny^3#3T&2n*SM16}yDt;ld9FL(Cs}L!H3(NaJdOzPVY!)5vb}k3FF@=Qg}d zrKV67N>YDJo(BJ7P5>p9;uT$QL?2xK3$NGWaSRC**GCv3=jLxl8HH4r69D9le?@2R zu@!S$9XfaPNbKy)w{8^^kRGqluaq}TrCO!GE4Ht26_!V>I6A9dLRUULS6U0-uu@Xg6^BMi^q zh)9Nn>y=2+zXA;&&a-_2!werFLhyl*#;-W=w=ja(EBGPIHT5q~$5MKCVE~`irdC<> zZ<-{!mv?Jfv%HsGZG|rZ?i(cMc}AMxU?&)$tD-sR3$v8;Nn9ZYip&prMaA+8QHy)8 zY$ex-u6@U9aVgxF(JBK#T!h0>T=i01wxpOFAS!BX!Pmpnp;kqa_c{Oa$kh_1ta34G zgzIh+=q#`m~dR6ko+NmpBy>X;|1^mih2w>7D1 z9pVa)qNOMyU6gZCJSC&|3S3pfIOn)Wr6TpOvEC>m3zh#q%mi=5K$)Wal0K^bo0G=n z_z=^|OY%>^zJ8oCFhbJ4IvV@Bl6Fu@!-8_om1`8{m5yQj2_)f!Sj@GAij?Z{EWK%v zB^!cBnyFD?Nd7<3AiR|=X8`msQ-7_;$pEzxqeRUE;x1^jJa@G<3iWx~#L)Qm^(Kag zRwRaH^738&vdxY6xFE~zvCxr^QY;HKffVP1xmbMwTbyZ;Nn28+FAuXITpY_YgRx56=vkrfraal#iEA!ZTysY$R(U3 zN<;22R-4M8)fD=Ih-OfI0Fjm9@e8}$Y*GDsS0@iZ6Gas*8>8l!5HRn|i= zT|;7Gr13E5gyQZx0gt4k^(WXA012#UOZ=OR3XQO_RqQA+i&6Ml&s2vJm9NE!qOiX; z0a045U@Y{Wwq&fZ-13)uN)0eKhKZw@z{k?fPvr$-LMNE1$k2)d*Mzi1yIrw#j3`@S zvHSr?!Mj*3V{l>#i@VskuWQXSRgqDleEzLYVGAo--|aY@u)Kyrh7+>-1jxWr`PP!6 zDRNDs*jeqysg^P%8}gX@i@Bi0wTrKzYb)BT5Jq0*N_X72CBRy~0))Nt$-Xr-o?W;I zK0_CqJutAA_lPhwzp1L}KG1jmMygDduKqPB>;;pwk=G;l@GpC)*wvsFJNMt&9N_cD zW)0cqePth38>E7J*<-zS!>}If+e2TrSwQy+eT?iI6xE|MTayI+SZs4fcoHAnBEAgSa-;2H~dMIcp83n)Qa%Yv6h(Pg=R&XTT2wKN2hb4C-`mIjIsjg!dS@I;OIMD z6N_2zUzV=7$(4*JSh{w(DnxYbqgX_@UsqW6&h$o9=o1OiLGJu}&}tccRVg`a7}eda z$$o-3ZHg&ADqsv;mqZwFumdA~Mi^|PDX1=BY${>+ZWxtkgn>rbR#2qniW0_1H;k%a zh!Xac$c9&vf<0FVhzc~elpwNh5H$l~Hs#;Dh8-Ak1zjv)TwTH#?S|3Q1>;B8z`*LX zSy#Z=QNq~X4WqXU##%gxM70%Iz<6;9V^=qfdKWuh8Dv}!WtS9};eQNXsR~q8=)Q_s z_~8osYQ+S*%L&H1C+O1z9o>QR#0Wl4HL!Xrg^X*bB16e)T9%m5OfRc7zPU8BP-0rS z>vm3fTYPw~6Y0=V))C`;EN2+q?uzy+#|cgthqJ^6%2Gw z(d{~nRFQ=@+X?%9uUx&~_uJM*8-9ma_-(`QHLmggGHZ^Z`$|A;6FbYYfWAoyg93Jo zM)6f-V|cL27){E(WT870c!ynLPv=U(#A5dQt(aX#4Szw@Fr=tKo{jC%7~lK%GtL4Nt1@1+ zLE1&JP~-0z)MJA}lyea}tn&~(fb&xfR(w;=@=wJq@Y7-w)jy>f3NsXU*!54ZzoC)4 zCbHK5tXg6L;8X4%#gi9_(>u}Jb^ryC7P*Aj*8jAFH|!kcig3C@5onDpdEEK8acrWX z?gEj#QCA@QI47kHTg0RIkU-ggh#09Vv?(~UZKvicD?=-ut*Gp6^`hHqQbtQB_0Tr_ zt%^osz*WgeYFS6J9&rynP&!+TVRptaf&lJqX3_*0{_QU7Ro1}L%+Q~OE5hbyTmw#& zt7C^Q_ANrf<{vKvdK)X6X__!nHuPaddLNI`9 z!w+G#`|OkmX!8ca?j>3S|=in_*jXRsNbPe`@l-^Wr?bTNvArOtE2N}a1dSLhnmjbFe+eZx#ZBa5+U{3kc7V!JNPXp7E;d2B z0XPT?L9+^$018!P#dWr*TbjVcoHRE;h>8tu^NAT*t;ap*J!zj(3+AQ$9-QSMfc z!8*_Bngrqzi`uteIN$2MsI_ZPRyi<($L~Ggs)PoGOpcs#MMG`HFE{R2-mabxV_O(L zS?7WKXIk}mS2Tv3d&)glj6L1P7(U6CN=9 zLTO}5wuKy(!}igdEZ_cltz`W37dL97BN>14;>PdAjNZ=n&t?9;gmOs!$0%0a-`&v0 zZT{!{7*r`*Ap@HCA6?@rG%^2M+8frst%X{3bdhd52ul4;&1l_9m!VGSGSn%RX0u1fY&cP)tl9Q_ zJ|9DGC9Cp)+7t8t-KAstCrMtBrz*Q@4mmyl-<xcK>Lu13=>u;}L<89r09 zmaEi3!n-rwL4!K(Ot%x{DnI6foN2!X`8|W63`tE*OX&L({&R{S zQvY+dWahv9a6NyHWS{@zYwP*tcJ)@;zS*vRi7T%wU|Jrc9ka9ku(;xXj~V>?9NO{w z&Oe3uPg8pn`pAA;{HGsc}c(p{3XKA>D&@L zH|CqTNG>Fs_kg;(>noiSlc z8KGI#zmi|A3eWFfkPDk(>$g9w=yx(l|HW3%o~$ST>nGgag+bV-Vq4dar=6Dpg)sP7 z!}fyhu6^16h&dGyBcwx4B>r4x=6I58b)|Svw#%Hl6DnZh*VTSm zUmR#w71g2z)l_R}&T0Rkwd!NnEi4G-mMj9xe+8TN{@1lg;OC4bCaj@ zrRW-eQl2aZBz253xF&ADT#L*H0Xk$r$s0i5@`jXp<}ECc>dpsUNvS1;kOYQk1|1b) z7Wmqd#DsQE`76=TQJG*|_|4ClN#SB+{v~yc78ewF%WCHcNIauF?JD1hXt6i!QZD~z zP#Unt&obUDp3MGD-?r&HEF<)|7?iV_sAoUrkOql0#0`N3rjU<<0>wK?PpcI zH^>#Gjq*uy(>S|S4qh(!gUY1?To$m zj{(>{006G48SFuTFDGF~)&H^Rs;S)`2e6~}Ox}Y71p)4Dp{fhbQqT{mFY2Q*hziv2 zbvT6-KJxKi7b`p4?fgGQon4ggK}!X5zQzFBt6`oBB!_adzH2K&lgjo?)yFLq=f3;{=e0lZ>)K?(3G7Ud;Sy?ot0Iok^q9XKfM3AGnmub(70oV{ zwXfdWlV}5L0K!5|p6}7(36B)p;dj>g%@ZI|lq$+LwFwrBmMGX7Jp+1JRw3VNGC zPf@@BMHwS#jrm`QSG)Z$>8j6vOkY+1@2oxl9n|GlxRh730s7dTnabU$>;3+UJ%f$> zlWdMy1Ql@pSHbx0I9tP5P5_KePlU0mDB`l=B8#C&WES&QSxlOLJi)80_?4q~&0syq zi{FnH=5y=-F(XIF&?7B7I;>!ttAP00%6l~yQ-kgo#bd4}3FcfWiI#voTUlIWSqj3i zwKb?IcALKr(P*h^C4o>PYsrOWQ9@xKOF|*-kx($NLMW885DF_*(zHGGqzPvzNNHoz zq`TXk8zw4s)WEMMGx_D=l5ivFJi04;K)YpU=sF%u1#i5DIg9UQ88@>u_WOXf9vm_D zZ(_yp&ujMOzY7h|U7=ovd?k<~jr!#-{gN52(5vk%?NvX4Vo_YoIn&9Bpo+iBKc9TC z*<(&wmTWj|3a-w}uJOla)m*Ui6HxgxP#IZ)NgDz~D z{y06ZRF5w?B1+GYVKGiv^rRW{$@@^`?m4MFTlaB!{=^sh3P~he z65k|ua{d7w4???p`~s?F0ei+*Hj_V2Yt2tfl0?B|B%lG#I!l`@(l`s-)%=gUd_ zp42Mk48N?yxM?=H0*et=!K^Z77!?zvu1un-Roi`^Yt;~6l3%H3{}TUaj_g1jlO3iq zKPEvTev%RDLpy!gcHzm7j!RG{*(`_3u0#~r4da9^vy6Z-RT6Zq+cOD;Dmzp1byeL& z62W7HGu4UtJ0y=5gG`e;w1$3wYR%oz%A!bA6D{>GI^}->TK$DCcu7Q10Sb6OBCm9X>RB{sMdqfA!%D(z*3Unsz+N;sI}N&SZiI#{}67}{em*FL`ZBxMnQ4;lH&4Z`XaM4UEQy4dLS`* z5xLUFh_N}M60twjyh8<=e@aTc5v+5UZ_2;&`nvy-RKL>P=TDTsc%&fzbolkswFrah zm#E72V}+6n$rRNt;WiLh{XaAXmxe}ff?>WZZG0$AYay2;k1j-4F_Zojz*2vrSq=71 zk_}s4A?G0D5v{4e7da`nHP>m+7a$jH401dF0RFGXFPbL_snata_*ce@=d2j^=-r(5 z*L}05FI8ESoW&B;=7OZ;sHubeh~l`4zD7_g=O4kb=AU>ZmMH1`Vh~mAmgt#pKD(4ssED~lu!}WfB&A$Yg=5m>e)X0Vt0e*^J4&3rtDJDvB=$4R*^k7S zA1s);#G=9jI$1(d7Sm8rQK9DNwZKZ-E7lBEh(LUg0o8>JD4gBo!RSa zu`a0)mgxCWMK4NOb<|IXC|zfG_f^&xpFIr^#PqK?Ng1{r%jaHmEkOpACw6P$JY{!- z9jNSXuoIQBAx?9gfkdX_Z3OilBIMp6(0eFK@axWC76+PiRBnSnIg%zV2!}5D8l!+( zgHDPoflfU|to6S83EPT{+?dIB00t+9#17H88Q_i^yMPlR_3-SmEVs4MPEihI8!tAi zaFFtb=$F-UY%#*g!MMkdld(|t_*bE-7j!7B)(c*vRDq_KVtOf5s<;taZfg$GGTuxP zHzzA2r?FDRLnXEt#zS$I*u4a&Q?zPmm7(I_C>bCh#}tsTU_MBwvi>PcjA{xt^;7)d z3%k3QFM`#3_!`)m-pLnMdVnuH!+yRfLfyz0o?$m%gV(c%m}J!6#-xJqzW4Z0g*SYt zlD}uL(y$b;MffpUocX0s?f6jY5{gHlcrQjbXb$KeKgpw(oLc{59Hzycy02F2_Q_zI zqv?Gbp|gYg^yxEf5Y;0vhFcp*%c9I>CB(vg*^u^%dK#EHW=Wh<4@(azwJqAl(oVTM z|0uH$DWvE)?)=@fJT4YxQHvaRj zyR}&0pKy)Wb{_FJUzQUMuN;ee_`FoaA|u#e#6}^5@PDOe(POz)ioo?>(w)#HSYyJb zgmST01HuPxe2pD53#jtHA@BP}k@0sCjbc#-4LNniW)WG!%qN6K$8DBrjQnCzI!-io zQT1j4SH0SFPW5VGzy~D-v<#mb9PTD)$jBw|el=4swz3s<3#!9ViZEymRDcJl76uhi z3E9C@@CV>Ts0vAWqzD!dm*n60>|@bXhiIOJZ3ZI@VB2}%Eq;@5`dAUXUvhwgt zP`1=0{5j&yYFNgLNSvta_YjJ0o$}5SJcH~^DAV|1_n2Po;lH7v|Buo&0Yb>qVq93xmn-T{S!zLLQ0& zs1gMOsh0c;uPM+bGwW4%1V6IYo%|J{^*1ygib;@#NG z?=N1DzX<#9rRVs?G(5)E@f_V=!;o0VWvCFrv4X%k6Su5f=L%#1G?yuRI9yPA5-Ct& z_G_F8)+Axu9<}A%l9UqrAS;BRv&4x+wLOYzyAHMK=oBNjlYKq&OC-P!e+x6Em*!}z zK~{Om8SZuYn$q&R%5kOtc}FxG9mT*NsUB<*qPPWg}6(LD~zw|%CP05XID^XGoyKW8z-J%WU0Jjr#hzFy}zedvoAtt_4LLmBS>Uc)Q|0zp< zV9RHau`&&bSdU@${pDw zCPX0>;N4unGVQgMoNZ$!3PmpEqXfumkbC`MZe8O>gO~UdL#=QZJ5z!QfqO8B0$(fc z=eEga)19M5dl`>NOA>8S+Ws1#AL$g%U>>r>F;bNy6qTwd6cs3J`=sD?r=AwUI|Iv8s2c`gZz$q$k7zWlp({FV*IO zBqN-}B|>Df9GKGC_m(Dh{)vGHh>}*k#*U0}qjt3u9?^h6d%Q>N1QrYsN7=^+W*d?Q{UxQ#~R89#JwM)vZ8*rIM67<9HtFiQ}{G@%BhhlK%nhcK*GF zNeRIc$k7r45A;L`Y^QfHum^ey2tT?Kf+chFuoAZ8_y(7+9nS*+S$)aZS2%g};Y6tnRa;JkXn{<|F%Dfl>%ht3=Hq z^|QcyozUset?>D)F=~0TSbAl({tP)d5ALQ)J`t%_6i4K{&EE?#zaby!bll$DwSo#z zuUI#3cD)XZ4Gf66S|6i2JSHW1x|M`%{%!PNmWND$>^X*+wYvDfwl1!8eHOK6A;h2KbBfM9#^r=L+vZ* zSdtb_gwUJ6`uD#B(t*-3|2^o zV}(W@r#Fo}e72&iNM2&(HNK;)o3oQxtWzc>3fKVwahSZU zmJ{jN2H2`Z*-pi5LJDz~VkemE3N5nt_VMJAirL6Z#cZ24P!!LSy`VH> zBS(8e>g>OSKcTA6V;BB=_%iEld?+{xvoY-xTzo1LFK zy3n4SJ~_>c<+F+KO73iKekogQFY(geX$HNjy^u|{C+DZySzE8rzb>1IZ=zq(oQ+;} zU3O%7&R*G@P0hC#4bH^mWc%b&rniA-C&P=yHSv-510|S6HSlWi)18(F7CTSTf;AgzEZCWpx zW=6f_eFgs4W!q-kbB8CUm~3IiZ0S^xq&h3c;L;I@@<*$RwsMBJ>=;y^?41 zbF-&2<6;)Mm`zU1W#Tg5rs-T}f%%K3Yy3KlMzyE1!+J0JP0@60p6sUGp=(FO+Yj;% z?5CM#d2Xv_TIcS>+*DTTgrO9fQJ@lVUc~%#SBSPBoNR;C?DUE0rK#nU{80p6A(O!&!Lknlv>*Ht3;wV`L~#`j>#;LH&5lh3|8Th7p34@(YscfQmE?B#5Zf2* zJ?|Nate|}{Tfx#>G2y^8`$G#*J57(^oDQGPrtxmGN2cc%`8y!flji-7f)Une?2778 zxHF?zETzvOUtLg&+$TG1q?JP$0&zkM>*KE!^j#d@A>rCgda*?Jqnm%^z>i zEiO(LeQ%pD^x@g*PMH=ov}NUv`?H|I-SkWVNBCYSEGSj=jWJuet8ye!VH=QbRx%jwa47l z$@yv4UO+HRzDoAa-;tp|fb^F#Y{|-SZ^GD6FPQx@t>*D>7-UBvqdj%v>Ho?{>~V5p dZhA7CpPXD?SZGfrdV_tV{w|fko_gx+{{yVfDy;wj literal 0 HcmV?d00001 From 1bea5fd732dd4897f3c46cf8dac8c2f30020b1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 17:44:49 +0300 Subject: [PATCH 269/275] Adjust naming convention for integration tests. --- package-lock.json | 4 ++-- package.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf54b9f9c..920874bda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.16", + "version": "13.0.0-beta.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.16", + "version": "13.0.0-beta.17", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index 6a1534a4c..c2f537e52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.16", + "version": "13.0.0-beta.17", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", @@ -10,10 +10,10 @@ ], "scripts": { "test": "npm run tests-unit", - "tests-unit": "mocha $(find . -name '*.spec.ts' ! -name '*.net.spec.*')", + "tests-unit": "mocha $(find . -name '*.spec.ts' ! -name '*.local.net.spec.*' ! -name '*.devnet.spec.*' ! -name '*.testnet.spec.*')", "tests-localnet": "mocha $(find . -name '*.local.net.spec.ts')", - "tests-devnet": "mocha $(find . -name '*.dev.net.spec.ts')", - "tests-testnet": "mocha $(find . -name '*.test.net.spec.ts')", + "tests-devnet": "mocha $(find . -name '*.devnet.spec.ts')", + "tests-testnet": "mocha $(find . -name '*.testnet.spec.ts')", "compile-browser": "tsc -p tsconfig.json && browserify out/index.js -o out-browser/sdk-core.js --standalone multiversxSdkCore -p esmify", "compile": "tsc -p tsconfig.json", "compile-proto": "npx pbjs -t static-module -w default -o src/proto/compiled.js src/proto/transaction.proto", From 68ea74e49ce55d213133eaa66ef00815c71ec5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 17:45:11 +0300 Subject: [PATCH 270/275] Fix test to work with newer multisig data. --- src/smartcontracts/typesystem/abiRegistry.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/smartcontracts/typesystem/abiRegistry.spec.ts b/src/smartcontracts/typesystem/abiRegistry.spec.ts index e9930b4ec..d3d966e8e 100644 --- a/src/smartcontracts/typesystem/abiRegistry.spec.ts +++ b/src/smartcontracts/typesystem/abiRegistry.spec.ts @@ -63,20 +63,20 @@ describe("test abi registry", () => { it("binary codec correctly decodes perform action result", async () => { let bc = new BinaryCodec(); let buff = Buffer.from( - "0588c738a5d26c0e3a2b4f9e8110b540ee9c0b71a3be057569a5a7b0fcb482c8f70000000806f05b59d3b200000000000b68656c6c6f20776f726c6400000000", + "0500000000000000000500d006f73c4221216fa679bc559005584c4f1160e569e1000000012a0000000003616464000000010000000107", "hex", ); - let registry = await loadAbiRegistry("src/testdata/multisig.abi.json"); + let registry = await loadAbiRegistry("src/testdata/multisig-full.abi.json"); let performAction = registry.getEndpoint("getActionData"); assert.equal(performAction.output[0].type.getName(), "Action"); let result = bc.decodeTopLevel(buff, performAction.output[0].type); assert.deepEqual( JSON.stringify(result.valueOf()), - `{"name":"SendTransferExecute","fields":[{"to":{"bech32":"erd13rrn3fwjds8r5260n6q3pd2qa6wqkudrhczh26d957c0edyzermshds0k8","pubkey":"88c738a5d26c0e3a2b4f9e8110b540ee9c0b71a3be057569a5a7b0fcb482c8f7"},"egld_amount":"500000000000000000","endpoint_name":{"type":"Buffer","data":[104,101,108,108,111,32,119,111,114,108,100]},"arguments":[]}]}`, + `{"name":"SendTransferExecuteEgld","fields":[{"to":{"bech32":"erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60","pubkey":"00000000000000000500d006f73c4221216fa679bc559005584c4f1160e569e1"},"egld_amount":"42","opt_gas_limit":null,"endpoint_name":{"type":"Buffer","data":[97,100,100]},"arguments":[{"type":"Buffer","data":[7]}]}]}`, ); - assert.equal(result.valueOf().name, "SendTransferExecute"); + assert.equal(result.valueOf().name, "SendTransferExecuteEgld"); }); it("should load ABI containing arrayN and nested structs", async () => { From 726542ffdbf3f2ae5a2d67e631c391352b9bdf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 3 Apr 2024 23:01:29 +0300 Subject: [PATCH 271/275] Find by first topic. Additional tests. --- .../resources.spec.ts | 69 +++++++++++++++++++ src/transactionsOutcomeParsers/resources.ts | 4 ++ .../transactionEventsParser.spec.ts | 65 ++++++++++++++++- .../transactionEventsParser.ts | 4 +- 4 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 src/transactionsOutcomeParsers/resources.spec.ts diff --git a/src/transactionsOutcomeParsers/resources.spec.ts b/src/transactionsOutcomeParsers/resources.spec.ts new file mode 100644 index 000000000..1d8fbd8ea --- /dev/null +++ b/src/transactionsOutcomeParsers/resources.spec.ts @@ -0,0 +1,69 @@ +import { assert } from "chai"; +import { + SmartContractResult, + TransactionEvent, + TransactionLogs, + TransactionOutcome, + findEventsByFirstTopic, + findEventsByIdentifier, +} from "./resources"; + +describe("test resources", () => { + it("finds events by identifier, by first topic", async function () { + const outcome = new TransactionOutcome({ + logs: new TransactionLogs({ + events: [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("a")], + }), + ], + }), + smartContractResults: [ + new SmartContractResult({ + logs: new TransactionLogs({ + events: [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + new TransactionEvent({ + identifier: "bar", + topics: [Buffer.from("c")], + }), + ], + }), + }), + ], + }); + + const foundByIdentifierFoo = findEventsByIdentifier(outcome, "foo"); + const foundByIdentifierBar = findEventsByIdentifier(outcome, "bar"); + const foundByTopic = findEventsByFirstTopic(outcome, "b"); + + assert.deepEqual(foundByIdentifierFoo, [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("a")], + }), + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + ]); + + assert.deepEqual(foundByIdentifierBar, [ + new TransactionEvent({ + identifier: "bar", + topics: [Buffer.from("c")], + }), + ]); + + assert.deepEqual(foundByTopic, [ + new TransactionEvent({ + identifier: "foo", + topics: [Buffer.from("b")], + }), + ]); + }); +}); diff --git a/src/transactionsOutcomeParsers/resources.ts b/src/transactionsOutcomeParsers/resources.ts index 93a4d1e5f..b30bd2f1c 100644 --- a/src/transactionsOutcomeParsers/resources.ts +++ b/src/transactionsOutcomeParsers/resources.ts @@ -83,6 +83,10 @@ export function findEventsByIdentifier(transactionOutcome: TransactionOutcome, i return findEventsByPredicate(transactionOutcome, (event) => event.identifier == identifier); } +export function findEventsByFirstTopic(transactionOutcome: TransactionOutcome, topic: string): TransactionEvent[] { + return findEventsByPredicate(transactionOutcome, (event) => event.topics[0]?.toString() == topic); +} + export function gatherAllEvents(transactionOutcome: TransactionOutcome): TransactionEvent[] { const allEvents = []; diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts index d31e2ee81..9ed01c91c 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.spec.ts @@ -13,7 +13,7 @@ import { Address } from "../address"; import { TransactionsConverter } from "../converters/transactionsConverter"; import { AbiRegistry } from "../smartcontracts"; import { loadAbiRegistry } from "../testutils"; -import { TransactionEvent, findEventsByIdentifier } from "./resources"; +import { TransactionEvent, findEventsByFirstTopic } from "./resources"; import { TransactionEventsParser } from "./transactionEventsParser"; describe("test transaction events parser", () => { @@ -39,7 +39,7 @@ describe("test transaction events parser", () => { ]); }); - it("parses events", async function () { + it("parses events (esdt-safe, deposit)", async function () { const parser = new TransactionEventsParser({ abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), }); @@ -69,7 +69,7 @@ describe("test transaction events parser", () => { }); const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); - const events = findEventsByIdentifier(transactionOutcome, "deposit"); + const events = findEventsByFirstTopic(transactionOutcome, "deposit"); const parsed = parser.parseEvents({ events }); assert.deepEqual(parsed, [ @@ -92,6 +92,65 @@ describe("test transaction events parser", () => { ]); }); + it("parses events (multisig, startPerformAction)", async function () { + const parser = new TransactionEventsParser({ + abi: await loadAbiRegistry("src/testdata/multisig-full.abi.json"), + }); + + const transactionsConverter = new TransactionsConverter(); + const transactionOnNetwork = new TransactionOnNetwork({ + nonce: 7, + contractResults: new ContractResults([ + new ContractResultItem({ + nonce: 8, + data: "@6f6b", + }), + ]), + logs: new TransactionLogsOnNetwork({ + events: [ + new TransactionEventOnNetwork({ + identifier: "performAction", + topics: [new TransactionEventTopic("c3RhcnRQZXJmb3JtQWN0aW9u")], + dataPayload: new TransactionEventData( + Buffer.from( + "00000001000000000500000000000000000500d006f73c4221216fa679bc559005584c4f1160e569e1000000000000000003616464000000010000000107000000010139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "hex", + ), + ), + }), + ], + }), + }); + + const transactionOutcome = transactionsConverter.transactionOnNetworkToOutcome(transactionOnNetwork); + const events = findEventsByFirstTopic(transactionOutcome, "startPerformAction"); + const parsed = parser.parseEvents({ events }); + + assert.deepEqual(parsed, [ + { + data: { + action_id: new BigNumber("1"), + group_id: new BigNumber("0"), + action_data: { + name: "SendTransferExecuteEgld", + fields: [ + { + to: Address.fromBech32( + "erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60", + ), + egld_amount: new BigNumber("0"), + opt_gas_limit: null, + endpoint_name: Buffer.from("add"), + arguments: [Buffer.from("07", "hex")], + }, + ], + }, + signers: [Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")], + }, + }, + ]); + }); + it("cannot parse events, when definition is missing", async function () { const parser = new TransactionEventsParser({ abi: await loadAbiRegistry("src/testdata/esdt-safe.abi.json"), diff --git a/src/transactionsOutcomeParsers/transactionEventsParser.ts b/src/transactionsOutcomeParsers/transactionEventsParser.ts index 4288d8812..4d568e077 100644 --- a/src/transactionsOutcomeParsers/transactionEventsParser.ts +++ b/src/transactionsOutcomeParsers/transactionEventsParser.ts @@ -35,14 +35,14 @@ export class TransactionEventsParser { parseEvent(options: { event: TransactionEvent }): any { const topics = options.event.topics.map((topic) => Buffer.from(topic)); - const eventIdentifier = this.firstTopicIsIdentifier ? topics[0]?.toString() : options.event.identifier; + const abiIdentifier = this.firstTopicIsIdentifier ? topics[0]?.toString() : options.event.identifier; if (this.firstTopicIsIdentifier) { topics.shift(); } const dataItems = options.event.dataItems.map((dataItem) => Buffer.from(dataItem)); - const eventDefinition = this.abi.getEvent(eventIdentifier); + const eventDefinition = this.abi.getEvent(abiIdentifier); const parsedEvent = this.legacyResultsParser.doParseEvent({ topics: topics, From 4aa5df40a836beeaee8bc169df05d9cc0c4527d8 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 4 Apr 2024 14:18:03 +0300 Subject: [PATCH 272/275] fix tests after merge --- .../interaction.local.net.spec.ts | 28 ++++++++----------- .../smartContract.local.net.spec.ts | 28 +++++++++---------- .../smartContractResults.local.net.spec.ts | 17 ++++++----- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/smartcontracts/interaction.local.net.spec.ts b/src/smartcontracts/interaction.local.net.spec.ts index 292814b40..16247af5f 100644 --- a/src/smartcontracts/interaction.local.net.spec.ts +++ b/src/smartcontracts/interaction.local.net.spec.ts @@ -10,7 +10,6 @@ import { ReturnCode } from "./returnCode"; import { SmartContract } from "./smartContract"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; -import { TokenComputer } from "../tokens"; import { promises } from "fs"; import { ResultsParser } from "./resultsParser"; import { TransactionWatcher } from "../transactionWatcher"; @@ -98,7 +97,6 @@ describe("test smart contract interactor", function () { const factory = new SmartContractTransactionsFactory({ config: config, abi: abiRegistry, - tokenComputer: new TokenComputer(), }); const bytecode = await promises.readFile("src/testdata/answer.wasm"); @@ -142,13 +140,13 @@ describe("test smart contract interactor", function () { const queryResponse = await queryController.runQuery(query); const parsed = queryController.parseQueryResponse(queryResponse); assert.lengthOf(parsed, 1); - assert.deepEqual(parsed[0].valueOf(), new BigNumber(42)); + assert.deepEqual(parsed[0], new BigNumber(42)); // Query let transaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "getUltimateAnswer", + function: "getUltimateAnswer", gasLimit: 3000000n, }); transaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -164,7 +162,7 @@ describe("test smart contract interactor", function () { transaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "getUltimateAnswer", + function: "getUltimateAnswer", gasLimit: 3000000n, }); transaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -258,7 +256,6 @@ describe("test smart contract interactor", function () { const factory = new SmartContractTransactionsFactory({ config: config, abi: abiRegistry, - tokenComputer: new TokenComputer(), }); const bytecode = await promises.readFile("src/testdata/counter.wasm"); @@ -295,7 +292,7 @@ describe("test smart contract interactor", function () { let incrementTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 3000000n, }); incrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -314,7 +311,7 @@ describe("test smart contract interactor", function () { }); const queryResponse = await queryController.runQuery(query); const parsed = queryController.parseQueryResponse(queryResponse); - assert.deepEqual(parsed[0].valueOf(), new BigNumber(1)); + assert.deepEqual(parsed[0], new BigNumber(1)); const incrementTxHash = await provider.sendTransaction(incrementTransaction); transactionOnNetwork = await transactionCompletionAwaiter.awaitCompleted(incrementTxHash); @@ -324,7 +321,7 @@ describe("test smart contract interactor", function () { let decrementTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "decrement", + function: "decrement", gasLimit: 3000000n, }); decrementTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -455,7 +452,6 @@ describe("test smart contract interactor", function () { const factory = new SmartContractTransactionsFactory({ config: config, abi: abiRegistry, - tokenComputer: new TokenComputer(), }); const bytecode = await promises.readFile("src/testdata/lottery-esdt.wasm"); @@ -491,8 +487,8 @@ describe("test smart contract interactor", function () { let startTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "start", - args: ["lucky", "EGLD", 1, null, null, 1, null, null], + function: "start", + arguments: ["lucky", "EGLD", 1, null, null, 1, null, null], gasLimit: 30000000n, }); startTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -512,8 +508,8 @@ describe("test smart contract interactor", function () { let lotteryStatusTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "status", - args: ["lucky"], + function: "status", + arguments: ["lucky"], gasLimit: 5000000n, }); lotteryStatusTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -534,8 +530,8 @@ describe("test smart contract interactor", function () { let lotteryInfoTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "getLotteryInfo", - args: ["lucky"], + function: "getLotteryInfo", + arguments: ["lucky"], gasLimit: 5000000n, }); lotteryInfoTransaction.nonce = BigInt(alice.account.nonce.valueOf()); diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index fec52446f..f907b345e 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -118,7 +118,7 @@ describe("test on local testnet", function () { await alice.sync(provider); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new SmartContractTransactionsFactory({ config: config }); const bytecode = await promises.readFile("src/testdata/counter.wasm"); @@ -140,7 +140,7 @@ describe("test on local testnet", function () { const smartContractCallTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 3000000n, }); smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -152,7 +152,7 @@ describe("test on local testnet", function () { const simulateOne = factory.createTransactionForExecute({ sender: alice.address, - functionName: "increment", + function: "increment", contract: contractAddress, gasLimit: 100000n, }); @@ -166,7 +166,7 @@ describe("test on local testnet", function () { const simulateTwo = factory.createTransactionForExecute({ sender: alice.address, - functionName: "foobar", + function: "foobar", contract: contractAddress, gasLimit: 500000n, }); @@ -271,7 +271,7 @@ describe("test on local testnet", function () { await alice.sync(provider); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new SmartContractTransactionsFactory({ config: config }); const bytecode = await promises.readFile("src/testdata/counter.wasm"); @@ -293,7 +293,7 @@ describe("test on local testnet", function () { const firstScCallTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 3000000n, }); firstScCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -306,7 +306,7 @@ describe("test on local testnet", function () { const secondScCallTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 3000000n, }); secondScCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); @@ -435,7 +435,7 @@ describe("test on local testnet", function () { await alice.sync(provider); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new SmartContractTransactionsFactory({ config: config }); const bytecode = await promises.readFile("src/testdata/erc20.wasm"); @@ -443,7 +443,7 @@ describe("test on local testnet", function () { sender: alice.address, bytecode: bytecode, gasLimit: 50000000n, - args: [new U32Value(10000)], + arguments: [new U32Value(10000)], }); deployTransaction.nonce = BigInt(alice.account.nonce.valueOf()); const transactionComputer = new TransactionComputer(); @@ -457,9 +457,9 @@ describe("test on local testnet", function () { const transactionMintBob = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "transferToken", + function: "transferToken", gasLimit: 9000000n, - args: [new AddressValue(bob.address), new U32Value(1000)], + arguments: [new AddressValue(bob.address), new U32Value(1000)], }); transactionMintBob.nonce = BigInt(alice.account.nonce.valueOf()); transactionMintBob.signature = await alice.signer.sign( @@ -471,9 +471,9 @@ describe("test on local testnet", function () { const transactionMintCarol = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "transferToken", + function: "transferToken", gasLimit: 9000000n, - args: [new AddressValue(carol.address), new U32Value(1500)], + arguments: [new AddressValue(carol.address), new U32Value(1500)], }); transactionMintCarol.nonce = BigInt(alice.account.nonce.valueOf()); transactionMintCarol.signature = await alice.signer.sign( @@ -638,7 +638,7 @@ describe("test on local testnet", function () { contract: contractAddress, function: "start", gasLimit: 10000000n, - args: [ + arguments: [ BytesValue.fromUTF8("lucky"), new TokenIdentifierValue("EGLD"), new BigUIntValue(1), diff --git a/src/smartcontracts/smartContractResults.local.net.spec.ts b/src/smartcontracts/smartContractResults.local.net.spec.ts index 731c0b185..1ad837676 100644 --- a/src/smartcontracts/smartContractResults.local.net.spec.ts +++ b/src/smartcontracts/smartContractResults.local.net.spec.ts @@ -7,7 +7,6 @@ import { ResultsParser } from "./resultsParser"; import { SmartContract } from "./smartContract"; import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { SmartContractTransactionsFactory } from "../transactionsFactories/smartContractTransactionsFactory"; -import { TokenComputer } from "../tokens"; import { promises } from "fs"; import { TransactionComputer } from "../transactionComputer"; @@ -62,14 +61,14 @@ describe("fetch transactions from local testnet", function () { alice.account.incrementNonce(); // Broadcast & execute - await provider.sendTransaction(transactionDeploy); - await provider.sendTransaction(transactionIncrement); + const txHashDeploy = await provider.sendTransaction(transactionDeploy); + const txHashIncrement = await provider.sendTransaction(transactionIncrement); - await watcher.awaitCompleted(transactionDeploy.getHash().hex()); - await watcher.awaitCompleted(transactionIncrement.getHash().hex()); + await watcher.awaitCompleted(txHashDeploy); + await watcher.awaitCompleted(txHashIncrement); - let transactionOnNetworkDeploy = await provider.getTransaction(transactionDeploy.getHash().hex()); - let transactionOnNetworkIncrement = await provider.getTransaction(transactionIncrement.getHash().hex()); + const transactionOnNetworkDeploy = await provider.getTransaction(txHashDeploy); + const transactionOnNetworkIncrement = await provider.getTransaction(txHashIncrement); let bundle = resultsParser.parseUntypedOutcome(transactionOnNetworkDeploy); assert.isTrue(bundle.returnCode.isSuccess()); @@ -88,7 +87,7 @@ describe("fetch transactions from local testnet", function () { await alice.sync(provider); const config = new TransactionsFactoryConfig({ chainID: network.ChainID }); - const factory = new SmartContractTransactionsFactory({ config: config, tokenComputer: new TokenComputer() }); + const factory = new SmartContractTransactionsFactory({ config: config }); const bytecode = await promises.readFile("src/testdata/counter.wasm"); @@ -110,7 +109,7 @@ describe("fetch transactions from local testnet", function () { const smartContractCallTransaction = factory.createTransactionForExecute({ sender: alice.address, contract: contractAddress, - functionName: "increment", + function: "increment", gasLimit: 3000000n, }); smartContractCallTransaction.nonce = BigInt(alice.account.nonce.valueOf()); From febf3769f62b3c0fc154a48f16b02e2df0d82868 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 5 Apr 2024 12:13:58 +0300 Subject: [PATCH 273/275] add method to compute bytes for verifying transaction signature --- src/transaction.spec.ts | 57 ++++++++++++++++++++++++++++++++++++++ src/transactionComputer.ts | 9 ++++++ 2 files changed, 66 insertions(+) diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 0e26f2a42..efe3a227e 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -9,6 +9,7 @@ import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionComputer } from "./transactionComputer"; import { TransactionPayload } from "./transactionPayload"; +import { UserPublicKey, UserVerifier } from "@multiversx/sdk-wallet/out"; describe("test transaction", async () => { let wallets: Record; @@ -696,4 +697,60 @@ describe("test transaction", async () => { assert.equal(transaction.version, 2); assert.equal(transaction.options, 3); }); + + it("should compute bytes to verify transaction signature", async () => { + let transaction = new Transaction({ + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "D", + }); + + transaction.signature = await wallets.alice.signer.sign( + transactionComputer.computeBytesForSigning(transaction), + ); + + const userVerifier = new UserVerifier(new UserPublicKey(wallets.alice.address.getPublicKey())); + const isSignedByAlice = userVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + const wrongVerifier = new UserVerifier(new UserPublicKey(wallets.bob.address.getPublicKey())); + const isSignedByBob = wrongVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + assert.equal(isSignedByAlice, true); + assert.equal(isSignedByBob, false); + }); + + it("should compute bytes to verify transaction signature (signed by hash)", async () => { + let transaction = new Transaction({ + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "D", + }); + + transactionComputer.applyOptionsForHashSigning(transaction); + + transaction.signature = await wallets.alice.signer.sign(transactionComputer.computeHashForSigning(transaction)); + + const userVerifier = new UserVerifier(new UserPublicKey(wallets.alice.address.getPublicKey())); + const isSignedByAlice = userVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + const wrongVerifier = new UserVerifier(new UserPublicKey(wallets.bob.address.getPublicKey())); + const isSignedByBob = wrongVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + assert.equal(isSignedByAlice, true); + assert.equal(isSignedByBob, false); + }); }); diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 31707aed1..d4117a393 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -55,6 +55,15 @@ export class TransactionComputer { return new Uint8Array(Buffer.from(serialized)); } + computeBytesForVerifying(transaction: ITransaction): Uint8Array { + const isTxSignedByHash = this.hasOptionsSetForHashSigning(transaction); + + if (isTxSignedByHash) { + return this.computeHashForSigning(transaction); + } + return this.computeBytesForSigning(transaction); + } + computeHashForSigning(transaction: ITransaction): Uint8Array { const plainTransaction = this.toPlainObjectForSigning(transaction); const signable = Buffer.from(JSON.stringify(plainTransaction)); From 2ecda7d25b95b4d4fd01168fea85da673f660b11 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 5 Apr 2024 12:24:47 +0300 Subject: [PATCH 274/275] small fix & bump version --- package-lock.json | 4 ++-- package.json | 2 +- src/transaction.spec.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 920874bda..b4c79ed86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index c2f537e52..24cdd41d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index efe3a227e..c514a3abd 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -704,6 +704,7 @@ describe("test transaction", async () => { receiver: wallets.bob.address.toBech32(), gasLimit: 50000n, chainID: "D", + nonce: 7n, }); transaction.signature = await wallets.alice.signer.sign( @@ -732,6 +733,7 @@ describe("test transaction", async () => { receiver: wallets.bob.address.toBech32(), gasLimit: 50000n, chainID: "D", + nonce: 7n, }); transactionComputer.applyOptionsForHashSigning(transaction); From db7d81d6f8916ff18e0296c4bf494b97b95b68ee Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 5 Apr 2024 14:20:48 +0300 Subject: [PATCH 275/275] merge From feat & small refactoring --- .../smartContract.local.net.spec.ts | 12 +++---- src/testutils/contractController.ts | 15 ++------ src/transaction.local.net.spec.ts | 34 +++++++------------ 3 files changed, 21 insertions(+), 40 deletions(-) diff --git a/src/smartcontracts/smartContract.local.net.spec.ts b/src/smartcontracts/smartContract.local.net.spec.ts index f907b345e..75040dc0f 100644 --- a/src/smartcontracts/smartContract.local.net.spec.ts +++ b/src/smartcontracts/smartContract.local.net.spec.ts @@ -90,16 +90,16 @@ describe("test on local testnet", function () { simulateTwo.applySignature(await alice.signer.sign(simulateTwo.serializeForSigning())); // Broadcast & execute - await provider.sendTransaction(transactionDeploy); - await provider.sendTransaction(transactionIncrement); + const txHashDeploy = await provider.sendTransaction(transactionDeploy); + const txHashIncrement = await provider.sendTransaction(transactionIncrement); - await watcher.awaitCompleted(transactionDeploy.getHash().hex()); - let transactionOnNetwork = await provider.getTransaction(transactionDeploy.getHash().hex()); + await watcher.awaitCompleted(txHashDeploy); + let transactionOnNetwork = await provider.getTransaction(txHashDeploy); let bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); assert.isTrue(bundle.returnCode.isSuccess()); - await watcher.awaitCompleted(transactionIncrement.getHash().hex()); - transactionOnNetwork = await provider.getTransaction(transactionIncrement.getHash().hex()); + await watcher.awaitCompleted(txHashIncrement); + transactionOnNetwork = await provider.getTransaction(txHashIncrement); bundle = resultsParser.parseUntypedOutcome(transactionOnNetwork); assert.isTrue(bundle.returnCode.isSuccess()); diff --git a/src/testutils/contractController.ts b/src/testutils/contractController.ts index 8df126fb5..517d8eef6 100644 --- a/src/testutils/contractController.ts +++ b/src/testutils/contractController.ts @@ -4,7 +4,6 @@ import { Interaction } from "../smartcontracts/interaction"; import { TypedOutcomeBundle, UntypedOutcomeBundle } from "../smartcontracts/interface"; import { ResultsParser } from "../smartcontracts/resultsParser"; import { Transaction } from "../transaction"; -import { TransactionComputer } from "../transactionComputer"; import { TransactionWatcher } from "../transactionWatcher"; import { INetworkProvider } from "./networkProviders"; @@ -22,10 +21,9 @@ export class ContractController { } async deploy(transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: UntypedOutcomeBundle }> { - const txHash = this.getTransactionHash(transaction); + const txHash = await this.provider.sendTransaction(transaction); Logger.info(`ContractController.deploy [begin]: transaction = ${txHash}`); - - await this.provider.sendTransaction(transaction); + let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(txHash); let bundle = this.parser.parseUntypedOutcome(transactionOnNetwork); @@ -34,12 +32,11 @@ export class ContractController { } async execute(interaction: Interaction, transaction: Transaction): Promise<{ transactionOnNetwork: ITransactionOnNetwork, bundle: TypedOutcomeBundle }> { - const txHash = this.getTransactionHash(transaction); + const txHash = await this.provider.sendTransaction(transaction); Logger.info(`ContractController.execute [begin]: function = ${interaction.getFunction()}, transaction = ${txHash}`); interaction.check(); - await this.provider.sendTransaction(transaction); let transactionOnNetwork = await this.transactionCompletionAwaiter.awaitCompleted(txHash); let bundle = this.parser.parseOutcome(transactionOnNetwork, interaction.getEndpoint()); @@ -58,10 +55,4 @@ export class ContractController { Logger.debug(`ContractController.query [end]: function = ${interaction.getFunction()}, return code = ${bundle.returnCode}`); return bundle; } - - private getTransactionHash(transaction: Transaction): string { - const transactionComputer = new TransactionComputer(); - const txHash = transactionComputer.computeTransactionHash(transaction); - return Buffer.from(txHash).toString("hex"); - } } diff --git a/src/transaction.local.net.spec.ts b/src/transaction.local.net.spec.ts index fe564ac47..844091230 100644 --- a/src/transaction.local.net.spec.ts +++ b/src/transaction.local.net.spec.ts @@ -2,7 +2,7 @@ import BigNumber from "bignumber.js"; import { assert } from "chai"; import { Logger } from "./logger"; import { loadTestWallets, TestWallet } from "./testutils"; -import { createLocalnetProvider } from "./testutils/networkProviders"; +import { createLocalnetProvider, INetworkProvider } from "./testutils/networkProviders"; import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionPayload } from "./transactionPayload"; @@ -18,11 +18,8 @@ describe("test transaction", function () { ({ alice, bob } = await loadTestWallets()); }); - it("should send transactions and wait for completion", async function () { - this.timeout(70000); - - let provider = createLocalnetProvider(); - let watcher = new TransactionWatcher( + function createTransactionWatcher(provider: INetworkProvider) { + return new TransactionWatcher( { getTransaction: async (hash: string) => { return await provider.getTransaction(hash, true); @@ -30,6 +27,13 @@ describe("test transaction", function () { }, { timeoutMilliseconds: 100000 }, ); + } + + it("should send transactions and wait for completion", async function () { + this.timeout(70000); + + let provider = createLocalnetProvider(); + let watcher = createTransactionWatcher(provider); let network = await provider.getNetworkConfig(); let transactionOne = new Transaction({ @@ -75,14 +79,7 @@ describe("test transaction", function () { this.timeout(70000); let provider = createLocalnetProvider(); - let watcher = new TransactionWatcher( - { - getTransaction: async (hash: string) => { - return await provider.getTransaction(hash, true); - }, - }, - { timeoutMilliseconds: 100000 }, - ); + let watcher = createTransactionWatcher(provider); let network = await provider.getNetworkConfig(); @@ -148,14 +145,7 @@ describe("test transaction", function () { this.timeout(70000); const provider = createLocalnetProvider(); - const watcher = new TransactionWatcher( - { - getTransaction: async (hash: string) => { - return await provider.getTransaction(hash, true); - }, - }, - { timeoutMilliseconds: 100000 }, - ); + const watcher = createTransactionWatcher(provider); const network = await provider.getNetworkConfig();