From e165565349fb45d63ba45f899a902536b92f49c0 Mon Sep 17 00:00:00 2001 From: Veetrag Jain Date: Wed, 11 Feb 2026 00:32:25 +0530 Subject: [PATCH] feat(sdk-coin-hash): support valuless transactions Ticket: WIN-8912 --- modules/sdk-coin-atom/package.json | 2 +- modules/sdk-coin-hash/src/hash.ts | 5 +++ modules/sdk-coin-hash/src/lib/utils.ts | 2 +- .../transactionBuilder/transferBuilder.ts | 32 +++++++++++++++++++ modules/sdk-coin-sui/package.json | 2 +- modules/utxo-lib/package.json | 2 +- package.json | 4 +-- yarn.lock | 16 +++++----- 8 files changed, 51 insertions(+), 14 deletions(-) diff --git a/modules/sdk-coin-atom/package.json b/modules/sdk-coin-atom/package.json index c3ff177975..4a7fc705be 100644 --- a/modules/sdk-coin-atom/package.json +++ b/modules/sdk-coin-atom/package.json @@ -53,7 +53,7 @@ "@bitgo/sdk-api": "^1.73.4", "@bitgo/sdk-test": "^9.1.25", "@types/lodash": "^4.14.183", - "axios": "^1.12.0" + "axios": "^1.13.0" }, "gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c", "files": [ diff --git a/modules/sdk-coin-hash/src/hash.ts b/modules/sdk-coin-hash/src/hash.ts index ba234f67a7..d41fe821f4 100644 --- a/modules/sdk-coin-hash/src/hash.ts +++ b/modules/sdk-coin-hash/src/hash.ts @@ -65,4 +65,9 @@ export class Hash extends CosmosCoin { getAddressFromPublicKey(publicKey: string): string { return new KeyPair({ pub: publicKey }).getAddress(AddressFormat.mainnet); } + + /** @inheritDoc **/ + valuelessTransferAllowed(): boolean { + return true; + } } diff --git a/modules/sdk-coin-hash/src/lib/utils.ts b/modules/sdk-coin-hash/src/lib/utils.ts index 1327696e9a..a92f6b30cf 100644 --- a/modules/sdk-coin-hash/src/lib/utils.ts +++ b/modules/sdk-coin-hash/src/lib/utils.ts @@ -38,7 +38,7 @@ export class HashUtils extends CosmosUtils { /** @inheritdoc */ validateAmount(amount: Coin): void { const amountBig = BigNumber(amount.amount); - if (amountBig.isLessThanOrEqualTo(0)) { + if (amountBig.isLessThan(0)) { throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid amount: ' + amount.amount); } if (!constants.validDenoms.find((denom) => denom === amount.denom)) { diff --git a/modules/sdk-coin-hash/test/unit/transactionBuilder/transferBuilder.ts b/modules/sdk-coin-hash/test/unit/transactionBuilder/transferBuilder.ts index 203b47cb67..c3bfd0916e 100644 --- a/modules/sdk-coin-hash/test/unit/transactionBuilder/transferBuilder.ts +++ b/modules/sdk-coin-hash/test/unit/transactionBuilder/transferBuilder.ts @@ -124,6 +124,38 @@ describe('Hash Transfer Builder', () => { ]); }); + it('should build a transfer tx of zero amount without signature', async function () { + const zeroAmountTx = JSON.parse(JSON.stringify(testTx)); + zeroAmountTx.sendMessage.value.amount[0].amount = '0'; + const txBuilder = factory.getTransferBuilder(); + txBuilder.sequence(zeroAmountTx.sequence); + txBuilder.gasBudget(zeroAmountTx.gasBudget); + txBuilder.messages([zeroAmountTx.sendMessage.value]); + txBuilder.publicKey(toHex(fromBase64(zeroAmountTx.pubKey))); + const tx = await txBuilder.build(); + const json = await (await txBuilder.build()).toJson(); + should.equal(tx.type, TransactionType.Send); + should.deepEqual(json.gasBudget, zeroAmountTx.gasBudget); + should.deepEqual(json.sendMessages, [zeroAmountTx.sendMessage]); + should.deepEqual(json.publicKey, toHex(fromBase64(zeroAmountTx.pubKey))); + should.deepEqual(json.sequence, zeroAmountTx.sequence); + tx.toBroadcastFormat(); + should.deepEqual(tx.inputs, [ + { + address: testData.TEST_SEND_TX.sender, + value: '0', + coin: basecoin.getChain(), + }, + ]); + should.deepEqual(tx.outputs, [ + { + address: testData.TEST_SEND_TX.sendMessage.value.toAddress, + value: '0', + coin: basecoin.getChain(), + }, + ]); + }); + it('should sign a Transfer tx', async function () { const txBuilder = factory.getTransferBuilder(); txBuilder.sequence(testTx.sequence); diff --git a/modules/sdk-coin-sui/package.json b/modules/sdk-coin-sui/package.json index ec2ce1dba2..59c32f1b40 100644 --- a/modules/sdk-coin-sui/package.json +++ b/modules/sdk-coin-sui/package.json @@ -56,7 +56,7 @@ "@bitgo/sdk-api": "^1.73.4", "@bitgo/sdk-test": "^9.1.25", "@types/lodash": "^4.14.183", - "axios": "^1.12.0", + "axios": "^1.13.0", "debug": "^4.3.4" }, "gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c", diff --git a/modules/utxo-lib/package.json b/modules/utxo-lib/package.json index f2078061e1..d5585c7a3e 100644 --- a/modules/utxo-lib/package.json +++ b/modules/utxo-lib/package.json @@ -62,7 +62,7 @@ "devDependencies": { "@types/fs-extra": "^9.0.12", "@types/node": "^24.10.9", - "axios": "^1.12.0", + "axios": "^1.13.0", "debug": "^3.1.0", "fs-extra": "^9.1.0" }, diff --git a/package.json b/package.json index 70cb7dc6d4..393dea9af4 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "@polkadot/api": "14.1.1", "elliptic": "^6.6.1", "cookie": "^0.7.1", - "axios": "^1.12.0", + "axios": "^1.13.0", "canvg": "4.0.3", "**/stellar-sdk/**/bignumber.js": "4.1.0", "**/stellar-base/**/bignumber.js": "4.1.0", @@ -155,7 +155,7 @@ "test:prepare-release": "mocha --require tsx ./scripts/tests/prepareRelease/prepare-release-main.test.ts" }, "dependencies": { - "axios": "^1.12.0", + "axios": "^1.13.0", "terser": "^5.14.2", "tmp": "^0.2.3", "bigint-buffer": "npm:@trufflesuite/bigint-buffer@1.1.10" diff --git a/yarn.lock b/yarn.lock index 35b27978cd..8cbecbf4db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7675,13 +7675,13 @@ aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@0.25.0, axios@0.27.2, axios@1.7.4, axios@^0.21.2, axios@^0.26.1, axios@^1.12.0, axios@^1.6.0, axios@^1.8.3: - version "1.12.1" - resolved "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz" - integrity sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ== +axios@0.25.0, axios@0.27.2, axios@1.7.4, axios@^0.21.2, axios@^0.26.1, axios@^1.13.0, axios@^1.6.0, axios@^1.8.3: + version "1.13.5" + resolved "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz#5e464688fa127e11a660a2c49441c009f6567a43" + integrity sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q== dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.4" + follow-redirects "^1.15.11" + form-data "^4.0.5" proxy-from-env "^1.1.0" b4a@^1.6.4: @@ -11943,7 +11943,7 @@ flux@^4.0.1: fbemitter "^3.0.0" fbjs "^3.0.1" -follow-redirects@1.15.11, follow-redirects@^1.0.0, follow-redirects@^1.15.6: +follow-redirects@1.15.11, follow-redirects@^1.0.0, follow-redirects@^1.15.11: version "1.15.11" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== @@ -11981,7 +11981,7 @@ forge-light@1.1.4: resolved "https://registry.npmjs.org/forge-light/-/forge-light-1.1.4.tgz" integrity sha512-Nr0xdu93LJawgBZVU/tC+A+4pbKqigdY5PRBz8CXNm4e5saAZIqU2Qe9+nVFtVO5TWCHSgvI0LaZZuatgE5J1g== -form-data@^2.3.1, form-data@^4.0.0, form-data@^4.0.4, form-data@~4.0.4: +form-data@^2.3.1, form-data@^4.0.0, form-data@^4.0.4, form-data@^4.0.5, form-data@~4.0.4: version "4.0.4" resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz" integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==