From 0a34a8c1c0ba695ccb64c3360266c030183741ba Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 13 Feb 2024 15:23:00 +0200 Subject: [PATCH 01/20] 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 c00f61a3..63784a2f 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 0fe96076..70bdae7f 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 00000000..3abe9cef --- /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 00000000..bc0fe97f --- /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 4fe82b7e..9d22e54c 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 9518e31a..971d1c7a 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 02/20] add empty lines --- src/interface.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/interface.ts b/src/interface.ts index 70bdae7f..65a0099e 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 03/20] 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 9e389ab6..b0b354d8 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 8893ccd3..5949e0dd 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 e64e2e77..2c328e08 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 508c1e28..272fb599 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 ad606c65..29ea1573 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 04/20] 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 bc0fe97f..87725132 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 5949e0dd..a7ff15f8 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 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 05/20] Compiler option: ES2020. --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 716261e6..089ef306 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 06/20] 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 9fd54cd4..e7949b56 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 e6d18c28..66d200e0 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 d4ab3c62..fe447a9c 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 7804e7bd..593f9275 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 2f609159..39903b91 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 ba38f632..817496cc 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 6d326412..0e03b658 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 07/20] ES2015 -> ES2020. --- tsconfig.tests.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.tests.json b/tsconfig.tests.json index 29ec228e..52a987db 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 08/20] 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 66d200e0..361800ac 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 09/20] 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 54601745..123a5417 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 10/20] 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 c70fbdcc..4234381f 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 11/20] 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 68ccf609..d371afdc 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 248b858a..63abaa51 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 123a5417..b8a4b7c3 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 4fe82b7e..3277e106 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 1b5b71f3..9cf2b7b7 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 a298ebf0..3db54519 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 e257cc07..2c033a65 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 788c9d54..7e02329c 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 12/20] 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 3aec4764..b214c4f2 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 13/20] Fix comments. --- src/address.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/address.ts b/src/address.ts index b8a4b7c3..9745ac9c 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 14/20] 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 0fe96076..4ab8f672 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 788c9d54..85f8782f 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 9518e31a..68a1d7ce 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 3649ad01..ccb20392 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 a36a0334..465f4807 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 9e389ab6..89b5c17f 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 daa36d93..32fd2e84 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 8893ccd3..4dcf001d 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 e64e2e77..e6e72685 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 b675e0ce..fc29ceea 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 508c1e28..e26a97d8 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 c4b440f6..99967ffc 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 c0727670..1115fff9 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 39903b91..fcf09b09 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 ad606c65..1160a32a 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 15/20] 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 63abaa51..48313ab0 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 9745ac9c..a5b3fda5 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 16/20] 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 988c8f41..755529b6 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 68a1d7ce..07301c6a 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 ccb20392..78a46832 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 32fd2e84..24aa83e4 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 fe447a9c..eabe4664 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 99967ffc..e1c8b049 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 4680e993422ffde075de09e053ab34857748f9b7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 16 Feb 2024 13:55:55 +0200 Subject: [PATCH 17/20] 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 755529b6..1ca9e690 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 07301c6a..e61d0ea4 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 fc29ceea..c6ad6169 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 e26a97d8..03791e6f 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 817496cc..0da21c14 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 18/20] 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 65a0099e..663cfcec 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 87725132..d018f26d 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 19/20] 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 1ca9e690..755529b6 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 b3ce9ae92e69ae6ba12f0ec284398e4139feada2 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 20 Feb 2024 10:39:57 +0200 Subject: [PATCH 20/20] 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 e61d0ea4..fd6e54fd 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;