diff --git a/web/cashtab/src/utils/__mocks__/mockECPair.js b/web/cashtab/src/utils/__mocks__/mockECPair.js new file mode 100644 --- /dev/null +++ b/web/cashtab/src/utils/__mocks__/mockECPair.js @@ -0,0 +1,56 @@ +export const mockWif = 'L2mHRHSThu7JajH1V4vDDw56nWVCFckLVpJHzgp2dDknWfPJFr1w'; + +// Note that the ECPair `mockECPair` does not include BigInteger type information or undefined fields +export const mockECPair = { + d: { + 0: 58579411, + 1: 33017197, + 2: 12049976, + 3: 61298434, + 4: 15265756, + 5: 29527710, + 6: 19761499, + 7: 46297331, + 8: 18590431, + 9: 2710394, + 10: 0, + t: 10, + s: 0, + }, + compressed: true, + network: { + hashGenesisBlock: + '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f', + port: 8333, + portRpc: 8332, + protocol: { magic: 3652501241 }, + seedsDns: [ + 'seed.bitcoinabc.org', + 'seed-abc.bitcoinforks.org', + 'btccash-seeder.bitcoinunlimited.info', + 'seed.bitprim.org', + 'seed.deadalnix.me', + 'seeder.criptolayer.net', + ], + versions: { + bip32: { private: 76066276, public: 76067358 }, + bip44: 145, + private: 128, + public: 0, + scripthash: 5, + messagePrefix: '\u0018BitcoinCash Signed Message:\n', + }, + name: 'BitcoinCash', + per1: 100000000, + unit: 'BCH', + testnet: false, + messagePrefix: '\u0018BitcoinCash Signed Message:\n', + bip32: { public: 76067358, private: 76066276 }, + pubKeyHash: 0, + scriptHash: 5, + wif: 128, + dustThreshold: null, + }, +}; + +export const mockStringifiedECPair = JSON.stringify(mockECPair); diff --git a/web/cashtab/src/utils/__tests__/cashMethods.test.js b/web/cashtab/src/utils/__tests__/cashMethods.test.js --- a/web/cashtab/src/utils/__tests__/cashMethods.test.js +++ b/web/cashtab/src/utils/__tests__/cashMethods.test.js @@ -33,6 +33,7 @@ generateGenesisOpReturn, generateSendOpReturn, generateBurnOpReturn, + getECPairFromWIF, } from 'utils/cashMethods'; import { currency } from 'components/Common/Ticker'; import { @@ -118,6 +119,7 @@ } from '../__mocks__/mockTxBuilderData'; import createTokenMock from '../../hooks/__mocks__/createToken'; import TransactionBuilder from 'utils/txBuilder'; +import { mockWif, mockStringifiedECPair } from '../__mocks__/mockECPair'; it(`generateSendOpReturn() returns correct script object for valid tokenUtxo and send quantity`, () => { const BCH = new BCHJS(); @@ -1770,4 +1772,9 @@ const utxosMock = [{}, {}]; expect(calcFee(utxosMock, 2, 1.01)).toBe(378); }); + it(`Gets correct EC Pair from WIF`, () => { + expect(JSON.stringify(getECPairFromWIF(mockWif))).toBe( + mockStringifiedECPair, + ); + }); }); diff --git a/web/cashtab/src/utils/cashMethods.js b/web/cashtab/src/utils/cashMethods.js --- a/web/cashtab/src/utils/cashMethods.js +++ b/web/cashtab/src/utils/cashMethods.js @@ -9,6 +9,8 @@ import cashaddr from 'ecashaddrjs'; import bs58 from 'bs58'; import * as slpMdm from 'slp-mdm'; +import Bitcoin from '@psf/bitcoincashjs-lib'; +import coininfo from 'utils/coininfo'; // function is based on BCH-JS' generateBurnOpReturn() however it's been trimmed down for Cashtab use // Reference: https://github.com/Permissionless-Software-Foundation/bch-js/blob/62e56c832b35731880fe448269818b853c76dd80/src/slp/tokentype1.js#L217 @@ -141,14 +143,38 @@ return wif; }; +// Reference https://github.com/Permissionless-Software-Foundation/bch-js/blob/master/src/ecpair.js#L24 +// Modified for mainnet only +export const getECPairFromWIF = wif => { + let xec = coininfo.bitcoincash.main; + const xecBitcoinJSLib = xec.toBitcoinJS(); + + return Bitcoin.ECPair.fromWIF(wif, xecBitcoinJSLib); +}; + export const signUtxosByAddress = (BCH, inputUtxos, wallet, txBuilder) => { for (let i = 0; i < inputUtxos.length; i++) { const utxo = inputUtxos[i]; const accounts = [wallet.Path245, wallet.Path145, wallet.Path1899]; - const utxoEcPair = BCH.ECPair.fromWIF( - accounts.filter(acc => acc.cashAddress === utxo.address).pop() - .fundingWif, - ); + + const wif = accounts + .filter(acc => acc.cashAddress === utxo.address) + .pop().fundingWif; + + console.log(`wif`, wif); + + const utxoEcPair = BCH.ECPair.fromWIF(wif); + + const localUtxoEcPair = getECPairFromWIF(wif); + + console.log(`utxoEcPair`, utxoEcPair); + console.log(`localUtxoEcPair`, localUtxoEcPair); + + console.log(`stringified`, JSON.stringify(utxoEcPair)); + + if (JSON.stringify(utxoEcPair) === JSON.stringify(localUtxoEcPair)) { + console.log(`local method matches legacy method`); + } txBuilder.sign( i,