From 81111ff0c91801dc4edc10ec044fc0979c062003 Mon Sep 17 00:00:00 2001 From: alexloiko <13203602+alexloiko@users.noreply.github.com> Date: Tue, 4 Jul 2023 13:53:33 +0300 Subject: [PATCH] ALL-2085 Bch address format and tx preparation issues (#846) * ALL-2085 Fixed cashaddr address conversion for tx builder. * ALL-2085 Version --------- Co-authored-by: Alex Loiko --- package.json | 5 +- .../src/lib/__tests__/bch.tx.address.spec.ts | 68 +++++++++++++++++++ .../bch/src/lib/services/bch.sdk.tx.ts | 29 +++----- .../lib/services/bch.sdk.virtualAccount.ts | 13 +--- yarn.lock | 34 +++++----- 5 files changed, 101 insertions(+), 48 deletions(-) create mode 100644 packages/blockchain/bch/src/lib/__tests__/bch.tx.address.spec.ts diff --git a/package.json b/package.json index ffd2497eb7..fd156dac0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tatumio", - "version": "2.2.16", + "version": "2.2.17", "license": "MIT", "repository": "https://github.com/tatumio/tatum-js", "scripts": { @@ -50,12 +50,12 @@ "axios": "^0.26.0", "base-58": "^0.0.1", "base32.js": "^0.1.0", + "bchaddrjs": "^0.5.2", "bignumber.js": "^9.0.2", "bip32": "^2.0.5", "bip39": "^3.0.2", "bitcoinjs-lib": "^5.2.0", "bitcore-lib": "10.0.2", - "bitcore-lib-cash": "10.0.2", "bitcore-lib-doge": "10.0.0", "bitcore-lib-ltc": "10.0.0", "bn.js": "^5.2.1", @@ -91,6 +91,7 @@ "@nrwl/node": "14.8.4", "@nrwl/nx-cloud": "15.0.0", "@nrwl/workspace": "14.8.4", + "@types/bchaddrjs": "^0.4.0", "@types/bignumber.js": "^5.0.0", "@types/bip32": "^2.0.0", "@types/bip39": "^3.0.0", diff --git a/packages/blockchain/bch/src/lib/__tests__/bch.tx.address.spec.ts b/packages/blockchain/bch/src/lib/__tests__/bch.tx.address.spec.ts new file mode 100644 index 0000000000..5b92ab0c85 --- /dev/null +++ b/packages/blockchain/bch/src/lib/__tests__/bch.tx.address.spec.ts @@ -0,0 +1,68 @@ +import { TatumBchSDK } from '@tatumio/bch' + +describe('BchSDK - tx - address format', () => { + it('prepare tx for different address formats', async function () { + const bchSDK = TatumBchSDK({ + apiKey: '75ea3138-d0a1-47df-932e-acb3ee807dab', + }) + const args = { testnet: true } + + const fromUTXO = [ + { + txHash: '867f2474e7a21ded94d298861d6b46d44940222f763e827bfe6217206443c3dd', + index: 0, + privateKey: 'cVfQ1dCkyFyFUA9hq6Ye5QDETS7YTiLkuVCC7WdrnH6c8RAJaoeF', + }, + ] + + const VALUE = 0.000015 + const FEE = '0.00001' + + const txCashAddrPrefix = await bchSDK.transaction.prepareSignedTransaction( + { + fromUTXO, + to: [ + { + address: 'bchtest:qr5etpgkh96aflvmcmpkppa4vr3tex7a7ggncvlknk', + value: VALUE, + }, + ], + changeAddress: 'bchtest:qr8uq9zax5uh68k7rffuq4cuefrmy8msav8yq4z4yr', + fee: FEE, + }, + args, + ) + + const txCashAddr = await bchSDK.transaction.prepareSignedTransaction( + { + fromUTXO, + to: [ + { + address: 'qr5etpgkh96aflvmcmpkppa4vr3tex7a7ggncvlknk', + value: VALUE, + }, + ], + changeAddress: 'qr8uq9zax5uh68k7rffuq4cuefrmy8msav8yq4z4yr', + fee: FEE, + }, + args, + ) + + const txLegacy = await bchSDK.transaction.prepareSignedTransaction( + { + fromUTXO, + to: [ + { + address: 'n2p2raEPCPd77nAiw3Ck1SCsfhMjHu1xav', + value: VALUE, + }, + ], + changeAddress: 'mzTSGgcf4kxz8Aj3nyeFkniv5CqC8DiEsL', + fee: FEE, + }, + args, + ) + expect(txCashAddrPrefix).toBe(txCashAddr) + expect(txCashAddr).toBe(txLegacy) + }) +}) diff --git a/packages/blockchain/bch/src/lib/services/bch.sdk.tx.ts b/packages/blockchain/bch/src/lib/services/bch.sdk.tx.ts index b5f03c8217..10b44f0c65 100644 --- a/packages/blockchain/bch/src/lib/services/bch.sdk.tx.ts +++ b/packages/blockchain/bch/src/lib/services/bch.sdk.tx.ts @@ -1,5 +1,4 @@ import { ApiServices, BchTx, TransactionHash } from '@tatumio/api-client' -import { bcashAddressHelper } from '../utils/bch.address' import { BchSdkError } from '../bch.sdk.errors' import { amountUtils, SdkErrorCode } from '@tatumio/shared-abstract-sdk' // @ts-ignore @@ -9,9 +8,8 @@ import * as BitcoinCashJS from '@tatumio/bitcoincashjs2-lib' import BigNumber from 'bignumber.js' import _ from 'lodash' import { BchApiCallsType } from '../..' -// @ts-ignore -import * as bitcoreLibCash from 'bitcore-lib-cash' import { BchTransactionTypes, Signature } from '../bch.sdk.types' +import bchaddr from 'bchaddrjs' export const bchTransactions = (apiCalls: BchApiCallsType) => { const sendTransaction = async ( @@ -48,7 +46,9 @@ export const bchTransactions = (apiCalls: BchApiCallsType) => { if ('signatureId' in item) { privateKeysToSign.push(item.signatureId) signaturesToSign.push({ id: item.signatureId, index: item.signatureIdIndex }) - } else if ('privateKey' in item) privateKeysToSign.push(item.privateKey) + } else if ('privateKey' in item) { + privateKeysToSign.push(item.privateKey) + } const vout = txs?.[i]?.vout?.[item.index] if (!vout || !vout.value) throw new BchSdkError(SdkErrorCode.BTC_BASED_UTXO_NOT_FOUND) @@ -58,30 +58,19 @@ export const bchTransactions = (apiCalls: BchApiCallsType) => { for (const item of body.to) { const value = amountUtils.toSatoshis(item.value) - try { - const address = bcashAddressHelper.getAddress(item.address) - transactionBuilder.addOutput(address, value) - outputs.push(value) - } catch (e: any) { - const address = new bitcoreLibCash.Address.fromString(item.address) - transactionBuilder.addOutput(address.toLegacyAddress(), value) - outputs.push(value) - } + transactionBuilder.addOutput(bchaddr.toLegacyAddress(item.address), value) + outputs.push(value) } // send the change to change address - if (body.changeAddress) { + const changeAddress = body.changeAddress + if (changeAddress) { const sumOfInputs = _.sum(amountToSign) const sumOfOutputs = _.sum(outputs) const defaultFee = 0.00001 const txFee = amountUtils.toSatoshis(body.fee ?? defaultFee) const change = Number(new BigNumber(sumOfInputs).minus(sumOfOutputs).minus(txFee)) - try { - transactionBuilder.addOutput(bcashAddressHelper.getAddress(body.changeAddress), change) - } catch (e: any) { - const address = new bitcoreLibCash.Address.fromString(body.changeAddress) - transactionBuilder.addOutput(address.toLegacyAddress(), change) - } + transactionBuilder.addOutput(bchaddr.toLegacyAddress(changeAddress), change) } verifyAmounts(amountToSign, body) diff --git a/packages/blockchain/bch/src/lib/services/bch.sdk.virtualAccount.ts b/packages/blockchain/bch/src/lib/services/bch.sdk.virtualAccount.ts index 1bffdaaea2..5ee6477425 100644 --- a/packages/blockchain/bch/src/lib/services/bch.sdk.virtualAccount.ts +++ b/packages/blockchain/bch/src/lib/services/bch.sdk.virtualAccount.ts @@ -12,15 +12,13 @@ import { abstractBlockchainVirtualAccount } from '@tatumio/shared-blockchain-abs import { Blockchain } from '@tatumio/shared-core' import BigNumber from 'bignumber.js' import { BchSdkError } from '../bch.sdk.errors' -import stringify from 'fast-safe-stringify' import { btcBasedWalletUtils } from '@tatumio/shared-blockchain-btc-based' // @ts-ignore import * as BitcoinCashJS from '@tatumio/bitcoincashjs2-lib' -import { networks, TransactionBuilder } from 'bitcoinjs-lib' -// @ts-ignore -import * as bitcoreLibCash from 'bitcore-lib-cash' +import { TransactionBuilder } from 'bitcoinjs-lib' // @ts-ignore import * as coininfo from 'coininfo' +import bchaddr from 'bchaddrjs' interface KeyPair { address: string @@ -28,12 +26,7 @@ interface KeyPair { } const addOutputAddressValue = (transactionBuilder: TransactionBuilder, address: string, value: number) => { - try { - transactionBuilder.addOutput(address, value) - } catch (_) { - const addressFromString = new bitcoreLibCash.Address.fromString(address) - transactionBuilder.addOutput(addressFromString.toLegacyAddress(), value) - } + transactionBuilder.addOutput(bchaddr.toLegacyAddress(address), value) } const prepareTransaction = async ( diff --git a/yarn.lock b/yarn.lock index 953d11c03d..52c4b19eba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2799,6 +2799,11 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bchaddrjs@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@types/bchaddrjs/-/bchaddrjs-0.4.0.tgz#f3d29ab56096c9d7105b5ccbc69969d11426e087" + integrity sha512-Nvv3haWpXNWYfKasVoEp3VBgVsBTLTh45anhHUN8xVUPhn4ErU3FPS5AEcZtACWc5ICGUxbaiLTWOnwDkwYF1Q== + "@types/bech32@^1.1.2": version "1.1.4" resolved "https://registry.yarnpkg.com/@types/bech32/-/bech32-1.1.4.tgz#501590d41c81a5f1802e39d6be450e89ec6d75d6" @@ -4265,6 +4270,16 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== +bchaddrjs@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/bchaddrjs/-/bchaddrjs-0.5.2.tgz#1f52b5077329774e7c82d4882964628106bb11a0" + integrity sha512-OO7gIn3m7ea4FVx4cT8gdlWQR2+++EquhdpWQJH9BQjK63tJJ6ngB3QMZDO6DiBoXiIGUsTPHjlrHVxPGcGxLQ== + dependencies: + bs58check "2.1.2" + buffer "^6.0.3" + cashaddrjs "0.4.4" + stream-browserify "^3.0.0" + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -4466,19 +4481,6 @@ bitcoinjs-lib@^5.2.0: varuint-bitcoin "^1.0.4" wif "^2.0.1" -bitcore-lib-cash@10.0.2: - version "10.0.2" - resolved "https://registry.yarnpkg.com/bitcore-lib-cash/-/bitcore-lib-cash-10.0.2.tgz#9fc823de3c177c520a95c87454c138769b276df0" - integrity sha512-k4WkisK/OBD4CKl5r+GvOf3Hdw9W6UGviYUj6zNQujuyT/3eAgCs3QdhjLLVkauszg5pLXHezMV6C/UVLjBctQ== - dependencies: - bitcore-lib "^10.0.2" - bn.js "=4.11.8" - bs58 "^4.0.1" - buffer-compare "=1.1.1" - elliptic "^6.5.3" - inherits "=2.0.1" - lodash "^4.17.20" - bitcore-lib-doge@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/bitcore-lib-doge/-/bitcore-lib-doge-10.0.0.tgz#78adce96e75968640bd0fcad178cdea715c6b59f" @@ -4506,7 +4508,7 @@ bitcore-lib-ltc@10.0.0: lodash "^4.17.20" scryptsy "2.1.0" -bitcore-lib@10.0.2, bitcore-lib@^10.0.2: +bitcore-lib@10.0.2: version "10.0.2" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-10.0.2.tgz#7ba3a90e014584933893a7f8facebf9b9ce5e953" integrity sha512-x7bWAqZdk5B/aVM8ppcenErhjQ2Q8q+SIwqNkB+iKPDsYUCgx7Yvl2SCyQriU23HEJlfqkzBdsFm6tO0DbCikw== @@ -4792,7 +4794,7 @@ bs58@^5.0.0: dependencies: base-x "^4.0.0" -bs58check@<3.0.0, bs58check@^2.0.0, bs58check@^2.1.1, bs58check@^2.1.2: +bs58check@2.1.2, bs58check@<3.0.0, bs58check@^2.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== @@ -5010,7 +5012,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -cashaddrjs@^0.4.4: +cashaddrjs@0.4.4, cashaddrjs@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cashaddrjs/-/cashaddrjs-0.4.4.tgz#169f1ae620d325db77700273d972282adeeee331" integrity sha512-xZkuWdNOh0uq/mxJIng6vYWfTowZLd9F4GMAlp2DwFHlcCqCm91NtuAc47RuV4L7r4PYcY5p6Cr2OKNb4hnkWA==