From 513ca9647930e5fd495fdc26aff13dddd8a92a53 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 22 Oct 2025 17:13:12 +0300 Subject: [PATCH 1/4] allow args as bytes for sc interactions --- package-lock.json | 4 +- package.json | 2 +- .../smartContractTransactionsFactory.spec.ts | 41 ++++++++++++++++++- .../smartContractTransactionsFactory.ts | 16 +++++++- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51626528..f3044f62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "15.2.2", + "version": "15.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "15.2.2", + "version": "15.3.0", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index b388b5dd..6492b598 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "15.2.2", + "version": "15.3.0", "description": "MultiversX SDK for JavaScript and TypeScript", "author": "MultiversX", "homepage": "https://multiversx.com", diff --git a/src/smartContracts/smartContractTransactionsFactory.spec.ts b/src/smartContracts/smartContractTransactionsFactory.spec.ts index 7e56c63d..05f48c20 100644 --- a/src/smartContracts/smartContractTransactionsFactory.spec.ts +++ b/src/smartContracts/smartContractTransactionsFactory.spec.ts @@ -1,5 +1,5 @@ import { assert } from "chai"; -import { Abi, U32Value } from "../abi"; +import { Abi, BigUIntValue, U32Value } from "../abi"; import { Address, Err, Token, TokenTransfer, TransactionsFactoryConfig } from "../core"; import { loadAbiRegistry, loadContractCode } from "../testutils/utils"; import { SmartContractTransactionsFactory } from "./smartContractTransactionsFactory"; @@ -44,6 +44,45 @@ describe("test smart contract transactions factory", function () { } }); + it("should allow args of type 'TypedValue'", async function () { + const sender = Address.newFromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const gasLimit = 6000000n; + const args = [new BigUIntValue(7)]; + + const transaction = await factory.createTransactionForDeploy(sender, { + bytecode: bytecode.valueOf(), + gasLimit: gasLimit, + arguments: args, + }); + + const bytecodeHex = Buffer.from(bytecode).toString("hex"); + assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07`)); + }); + + it("should allow args of type bytes", async function () { + const sender = Address.newFromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); + const gasLimit = 6000000n; + let args = [Buffer.from([7]), new Uint8Array([7])]; + const bytecodeHex = Buffer.from(bytecode).toString("hex"); + + let transaction = await factory.createTransactionForDeploy(sender, { + bytecode: bytecode.valueOf(), + gasLimit: gasLimit, + arguments: args, + }); + + assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07@07`)); + + args = [new Uint8Array([7]), Buffer.from("6161626261", "hex")]; + transaction = await factory.createTransactionForDeploy(sender, { + bytecode: bytecode.valueOf(), + gasLimit: gasLimit, + arguments: args, + }); + + assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07@6161626261`)); + }); + it("should create 'Transaction' for deploy", async function () { const sender = Address.newFromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000n; diff --git a/src/smartContracts/smartContractTransactionsFactory.ts b/src/smartContracts/smartContractTransactionsFactory.ts index c95939f2..409da359 100644 --- a/src/smartContracts/smartContractTransactionsFactory.ts +++ b/src/smartContracts/smartContractTransactionsFactory.ts @@ -11,7 +11,7 @@ import { Logger } from "../core/logger"; import { TokenComputer, TokenTransfer } from "../core/tokens"; import { TokenTransfersDataBuilder } from "../core/tokenTransfersDataBuilder"; import { Transaction } from "../core/transaction"; -import { byteArrayToHex, utf8ToHex } from "../core/utils.codec"; +import { byteArrayToHex, utf8ToHex, zeroPadStringIfOddLength } from "../core/utils.codec"; import * as resources from "./resources"; interface IConfig { @@ -226,9 +226,23 @@ export class SmartContractTransactionsFactory extends BaseFactory { return new ArgSerializer().valuesToStrings(args); } + if (this.areArgsBuffers(args)) { + return args.map((arg) => zeroPadStringIfOddLength(Buffer.from(arg).toString("hex"))); + } + throw new Err("Can't convert args to TypedValues"); } + private areArgsBuffers(args: any[]): boolean { + for (const arg of args) { + if (!ArrayBuffer.isView(arg)) { + return false; + } + } + + return true; + } + private areArgsOfTypedValue(args: any[]): boolean { return args.every((arg) => isTyped(arg)); } From b6cd73b18d97c7f78e8fd82ea7c726f92e0af94a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 22 Oct 2025 17:28:18 +0300 Subject: [PATCH 2/4] add empty array test --- .../smartContractTransactionsFactory.spec.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/smartContracts/smartContractTransactionsFactory.spec.ts b/src/smartContracts/smartContractTransactionsFactory.spec.ts index 05f48c20..1935b0b2 100644 --- a/src/smartContracts/smartContractTransactionsFactory.spec.ts +++ b/src/smartContracts/smartContractTransactionsFactory.spec.ts @@ -59,7 +59,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07`)); }); - it("should allow args of type bytes", async function () { + it.only("should allow args of type bytes", async function () { const sender = Address.newFromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000n; let args = [Buffer.from([7]), new Uint8Array([7])]; @@ -81,6 +81,15 @@ describe("test smart contract transactions factory", function () { }); assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07@6161626261`)); + + args = [new Uint8Array()]; + transaction = await factory.createTransactionForDeploy(sender, { + bytecode: bytecode.valueOf(), + gasLimit: gasLimit, + arguments: args, + }); + + assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@`)); }); it("should create 'Transaction' for deploy", async function () { From 0aeb6c65bd245a6f4edab033d7b026666efcf19e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 22 Oct 2025 17:30:13 +0300 Subject: [PATCH 3/4] remove only --- src/smartContracts/smartContractTransactionsFactory.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smartContracts/smartContractTransactionsFactory.spec.ts b/src/smartContracts/smartContractTransactionsFactory.spec.ts index 1935b0b2..2535a709 100644 --- a/src/smartContracts/smartContractTransactionsFactory.spec.ts +++ b/src/smartContracts/smartContractTransactionsFactory.spec.ts @@ -59,7 +59,7 @@ describe("test smart contract transactions factory", function () { assert.deepEqual(transaction.data, Buffer.from(`${bytecodeHex}@0500@0504@07`)); }); - it.only("should allow args of type bytes", async function () { + it("should allow args of type bytes", async function () { const sender = Address.newFromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"); const gasLimit = 6000000n; let args = [Buffer.from([7]), new Uint8Array([7])]; From 191fa7400aa377c604d048596db045dc1ea6f2e7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 22 Oct 2025 17:35:10 +0300 Subject: [PATCH 4/4] remove unnecessary zero padding --- src/smartContracts/smartContractTransactionsFactory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smartContracts/smartContractTransactionsFactory.ts b/src/smartContracts/smartContractTransactionsFactory.ts index 409da359..de8986d2 100644 --- a/src/smartContracts/smartContractTransactionsFactory.ts +++ b/src/smartContracts/smartContractTransactionsFactory.ts @@ -11,7 +11,7 @@ import { Logger } from "../core/logger"; import { TokenComputer, TokenTransfer } from "../core/tokens"; import { TokenTransfersDataBuilder } from "../core/tokenTransfersDataBuilder"; import { Transaction } from "../core/transaction"; -import { byteArrayToHex, utf8ToHex, zeroPadStringIfOddLength } from "../core/utils.codec"; +import { byteArrayToHex, utf8ToHex } from "../core/utils.codec"; import * as resources from "./resources"; interface IConfig { @@ -227,7 +227,7 @@ export class SmartContractTransactionsFactory extends BaseFactory { } if (this.areArgsBuffers(args)) { - return args.map((arg) => zeroPadStringIfOddLength(Buffer.from(arg).toString("hex"))); + return args.map((arg) => Buffer.from(arg).toString("hex")); } throw new Err("Can't convert args to TypedValues");