Changeset View
Changeset View
Standalone View
Standalone View
cashtab/src/utils/__tests__/transactions.test.js
Show All 29 Lines | it('sends XEC correctly', async () => { | ||||
chronik.broadcastTx = jest | chronik.broadcastTx = jest | ||||
.fn() | .fn() | ||||
.mockResolvedValue({ txid: expectedTxId }); | .mockResolvedValue({ txid: expectedTxId }); | ||||
expect( | expect( | ||||
await sendXec( | await sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
), | ), | ||||
).toBe(`${currency.blockExplorerUrl}/tx/${expectedTxId}`); | ).toBe(`${currency.blockExplorerUrl}/tx/${expectedTxId}`); | ||||
}); | }); | ||||
Show All 10 Lines | it('sends XEC correctly with an encrypted OP_RETURN message', async () => { | ||||
chronik.broadcastTx = jest | chronik.broadcastTx = jest | ||||
.fn() | .fn() | ||||
.mockResolvedValue({ txid: expectedTxId }); | .mockResolvedValue({ txid: expectedTxId }); | ||||
expect( | expect( | ||||
await sendXec( | await sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'This is an encrypted opreturn message', | 'This is an encrypted opreturn message', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
true, // encryption flag for the OP_RETURN message | true, // encryption flag for the OP_RETURN message | ||||
false, // airdrop flag | false, // airdrop flag | ||||
'', // airdrop token id | '', // airdrop token id | ||||
Show All 18 Lines | it('sends one to many XEC correctly', async () => { | ||||
chronik.broadcastTx = jest | chronik.broadcastTx = jest | ||||
.fn() | .fn() | ||||
.mockResolvedValue({ txid: expectedTxId }); | .mockResolvedValue({ txid: expectedTxId }); | ||||
expect( | expect( | ||||
await sendXec( | await sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
true, | true, | ||||
addressAndValueArray, | addressAndValueArray, | ||||
), | ), | ||||
).toBe(`${currency.blockExplorerUrl}/tx/${expectedTxId}`); | ).toBe(`${currency.blockExplorerUrl}/tx/${expectedTxId}`); | ||||
}); | }); | ||||
it('Broadcasts a v0 alias registration tx for an 8-byte alias to a p2pkh address', async () => { | it('Broadcasts a v0 alias registration tx for an 8-byte alias to a p2pkh address', async () => { | ||||
Show All 12 Lines | it('Broadcasts a v0 alias registration tx for an 8-byte alias to a p2pkh address', async () => { | ||||
rawTxHex: | rawTxHex: | ||||
'0200000001049c2df49978e91fbd28e7827c2cee71c1d56c7743706b7f959dc090ba649e87000000006b483045022100dd79c2a3e8773e7d4963ad3f6f03b54aca569e8e383c5cdc285afa601ee50829022058dfcdc905ec8f45d7418644ccfdf45cd8db41aade2d57d455c50e1a181cf7bb4121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff030000000000000000266a042e78656300086e65777465737431150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388ac92929800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | '0200000001049c2df49978e91fbd28e7827c2cee71c1d56c7743706b7f959dc090ba649e87000000006b483045022100dd79c2a3e8773e7d4963ad3f6f03b54aca569e8e383c5cdc285afa601ee50829022058dfcdc905ec8f45d7418644ccfdf45cd8db41aade2d57d455c50e1a181cf7bb4121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff030000000000000000266a042e78656300086e65777465737431150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388ac92929800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | ||||
txid: '1272c4a9bf5829c9dba1efb252e753ed20e3cdd49b6e75a778befc7a87eaf7d0', | txid: '1272c4a9bf5829c9dba1efb252e753ed20e3cdd49b6e75a778befc7a87eaf7d0', | ||||
}; | }; | ||||
expect( | expect( | ||||
await registerNewAlias( | await registerNewAlias( | ||||
chronik, | chronik, | ||||
aliasRegisteringWallet, | aliasRegisteringWallet, | ||||
currency.defaultFee, | 2.01, | ||||
'newtest1', | 'newtest1', | ||||
'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | 'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | ||||
551, | 551, | ||||
), | ), | ||||
).toStrictEqual(expectedResult); | ).toStrictEqual(expectedResult); | ||||
}); | }); | ||||
it('Broadcasts a v0 alias registration tx for a 21-byte alias to a p2pkh address', async () => { | it('Broadcasts a v0 alias registration tx for a 21-byte alias to a p2pkh address', async () => { | ||||
const chronik = new ChronikClient( | const chronik = new ChronikClient( | ||||
Show All 10 Lines | it('Broadcasts a v0 alias registration tx for a 21-byte alias to a p2pkh address', async () => { | ||||
txid: mockTxid, | txid: mockTxid, | ||||
rawTxHex: | rawTxHex: | ||||
'0200000001d0f7ea877afcbe78a7756e9bd4cde320ed53e752b2efa1dbc92958bfa9c47212020000006a47304402205cf1941bd0ed8c49319189973feebd14e8d7faf6c5a3cdc6c16f676bd62c63ac022068c10726326e37f960433a92894609f7f0b65946d8104038110e2104d973c8e24121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff030000000000000000336a042e78656300157477656e74796f6e6562797465616c696173726567150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388aca48e9800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | '0200000001d0f7ea877afcbe78a7756e9bd4cde320ed53e752b2efa1dbc92958bfa9c47212020000006a47304402205cf1941bd0ed8c49319189973feebd14e8d7faf6c5a3cdc6c16f676bd62c63ac022068c10726326e37f960433a92894609f7f0b65946d8104038110e2104d973c8e24121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff030000000000000000336a042e78656300157477656e74796f6e6562797465616c696173726567150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388aca48e9800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | ||||
}; | }; | ||||
expect( | expect( | ||||
await registerNewAlias( | await registerNewAlias( | ||||
chronik, | chronik, | ||||
aliasRegisteringWalletAfterTx, | aliasRegisteringWalletAfterTx, | ||||
currency.defaultFee, | 2.01, | ||||
'twentyonebytealiasreg', | 'twentyonebytealiasreg', | ||||
'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | 'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | ||||
551, | 551, | ||||
), | ), | ||||
).toStrictEqual(expectedResult); | ).toStrictEqual(expectedResult); | ||||
}); | }); | ||||
it('Broadcasts a v0 alias registration tx for a 16-byte alias to a p2pkh address', async () => { | it('Broadcasts a v0 alias registration tx for a 16-byte alias to a p2pkh address', async () => { | ||||
const chronik = new ChronikClient( | const chronik = new ChronikClient( | ||||
Show All 10 Lines | it('Broadcasts a v0 alias registration tx for a 16-byte alias to a p2pkh address', async () => { | ||||
txid: mockTxid, | txid: mockTxid, | ||||
rawTxHex: | rawTxHex: | ||||
'0200000001ab6c7e3261b2c9c77d7e133e97db3be50cbb5ce1ba8e4ff168b511dca1822591020000006b483045022100d0bd27e798ac38de8b4c654c6670386c68d8bfac4bf5fe26a185d8250bd7ae7e02206acfe247b95ee9879080e6e413d7f28734aa498046e7363a638a537fc657c50e4121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff0300000000000000002e6a042e78656300107768796e6f7474687265657465737473150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388acb68a9800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | '0200000001ab6c7e3261b2c9c77d7e133e97db3be50cbb5ce1ba8e4ff168b511dca1822591020000006b483045022100d0bd27e798ac38de8b4c654c6670386c68d8bfac4bf5fe26a185d8250bd7ae7e02206acfe247b95ee9879080e6e413d7f28734aa498046e7363a638a537fc657c50e4121036ea648569566fa0843b914f67e54ebcfa6921208acd6408d2881488809403ac6ffffffff0300000000000000002e6a042e78656300107768796e6f7474687265657465737473150020edc8389101aed204b9c17b7d64a00ead0e8cfc27020000000000001976a914638568e36d0b5d7d49a6e99854caa27d9772b09388acb68a9800000000001976a91420edc8389101aed204b9c17b7d64a00ead0e8cfc88ac00000000', | ||||
}; | }; | ||||
expect( | expect( | ||||
await registerNewAlias( | await registerNewAlias( | ||||
chronik, | chronik, | ||||
aliasRegisteringWalletAfterTwoTxs, | aliasRegisteringWalletAfterTwoTxs, | ||||
currency.defaultFee, | 2.01, | ||||
'whynotthreetests', | 'whynotthreetests', | ||||
'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | 'ecash:qqswmjpcjyq6a5syh8qhklty5q826r5vlsh7a7uqtq', | ||||
551, | 551, | ||||
), | ), | ||||
).toStrictEqual(expectedResult); | ).toStrictEqual(expectedResult); | ||||
}); | }); | ||||
it(`Throws error if called trying to send one base unit ${currency.ticker} more than available in utxo set`, async () => { | it(`Throws error if called trying to send one base unit ${currency.ticker} more than available in utxo set`, async () => { | ||||
Show All 19 Lines | it(`Throws error if called trying to send one base unit ${currency.ticker} more than available in utxo set`, async () => { | ||||
.toString(); | .toString(); | ||||
let errorThrown; | let errorThrown; | ||||
try { | try { | ||||
await sendXec( | await sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
oneBaseUnitMoreThanBalance, | oneBaseUnitMoreThanBalance, | ||||
); | ); | ||||
} catch (err) { | } catch (err) { | ||||
errorThrown = err; | errorThrown = err; | ||||
} | } | ||||
expect(errorThrown.message).toStrictEqual('Insufficient funds'); | expect(errorThrown.message).toStrictEqual('Insufficient funds'); | ||||
const nullValuesSendBch = sendXec( | const nullValuesSendBch = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
null, | null, | ||||
); | ); | ||||
await expect(nullValuesSendBch).rejects.toThrow( | await expect(nullValuesSendBch).rejects.toThrow( | ||||
new Error('Invalid singleSendValue'), | new Error('Invalid singleSendValue'), | ||||
); | ); | ||||
}); | }); | ||||
it('Throws error on attempt to send one satoshi less than backend dust limit', async () => { | it('Throws error on attempt to send one satoshi less than backend dust limit', async () => { | ||||
const chronik = new ChronikClient( | const chronik = new ChronikClient( | ||||
'https://FakeChronikUrlToEnsureMocksOnly.com', | 'https://FakeChronikUrlToEnsureMocksOnly.com', | ||||
); | ); | ||||
const { utxos, wallet, destinationAddress } = sendBCHMock; | const { utxos, wallet, destinationAddress } = sendBCHMock; | ||||
const failedSendBch = sendXec( | const failedSendBch = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
new BigNumber(fromSatoshisToXec(currency.dustSats).toString()) | new BigNumber(fromSatoshisToXec(currency.dustSats).toString()) | ||||
.minus(new BigNumber('0.00000001')) | .minus(new BigNumber('0.00000001')) | ||||
.toString(), | .toString(), | ||||
); | ); | ||||
Show All 29 Lines | it('receives errors from the network and parses it', async () => { | ||||
const { sendAmount, utxos, wallet, destinationAddress } = sendBCHMock; | const { sendAmount, utxos, wallet, destinationAddress } = sendBCHMock; | ||||
chronik.broadcastTx = jest.fn().mockImplementation(async () => { | chronik.broadcastTx = jest.fn().mockImplementation(async () => { | ||||
throw new Error('insufficient priority (code 66)'); | throw new Error('insufficient priority (code 66)'); | ||||
}); | }); | ||||
const insufficientPriority = sendXec( | const insufficientPriority = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
); | ); | ||||
await expect(insufficientPriority).rejects.toThrow( | await expect(insufficientPriority).rejects.toThrow( | ||||
new Error('insufficient priority (code 66)'), | new Error('insufficient priority (code 66)'), | ||||
); | ); | ||||
chronik.broadcastTx = jest.fn().mockImplementation(async () => { | chronik.broadcastTx = jest.fn().mockImplementation(async () => { | ||||
throw new Error('txn-mempool-conflict (code 18)'); | throw new Error('txn-mempool-conflict (code 18)'); | ||||
}); | }); | ||||
const txnMempoolConflict = sendXec( | const txnMempoolConflict = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
); | ); | ||||
await expect(txnMempoolConflict).rejects.toThrow( | await expect(txnMempoolConflict).rejects.toThrow( | ||||
new Error('txn-mempool-conflict (code 18)'), | new Error('txn-mempool-conflict (code 18)'), | ||||
); | ); | ||||
chronik.broadcastTx = jest.fn().mockImplementation(async () => { | chronik.broadcastTx = jest.fn().mockImplementation(async () => { | ||||
throw new Error('Network Error'); | throw new Error('Network Error'); | ||||
}); | }); | ||||
const networkError = sendXec( | const networkError = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
); | ); | ||||
await expect(networkError).rejects.toThrow(new Error('Network Error')); | await expect(networkError).rejects.toThrow(new Error('Network Error')); | ||||
chronik.broadcastTx = jest.fn().mockImplementation(async () => { | chronik.broadcastTx = jest.fn().mockImplementation(async () => { | ||||
const err = new Error( | const err = new Error( | ||||
'too-long-mempool-chain, too many unconfirmed ancestors [limit: 25] (code 64)', | 'too-long-mempool-chain, too many unconfirmed ancestors [limit: 25] (code 64)', | ||||
); | ); | ||||
throw err; | throw err; | ||||
}); | }); | ||||
const tooManyAncestorsMempool = sendXec( | const tooManyAncestorsMempool = sendXec( | ||||
chronik, | chronik, | ||||
wallet, | wallet, | ||||
utxos, | utxos, | ||||
currency.defaultFee, | 2.01, | ||||
'', | '', | ||||
false, | false, | ||||
null, | null, | ||||
destinationAddress, | destinationAddress, | ||||
sendAmount, | sendAmount, | ||||
); | ); | ||||
await expect(tooManyAncestorsMempool).rejects.toThrow( | await expect(tooManyAncestorsMempool).rejects.toThrow( | ||||
new Error( | new Error( | ||||
Show All 18 Lines | describe('Cashtab transaction broadcasting functions', () => { | ||||
it('Throws correct error if user attempts to create a token with an invalid wallet', async () => { | it('Throws correct error if user attempts to create a token with an invalid wallet', async () => { | ||||
const { invalidWallet, configObj } = createTokenMock; | const { invalidWallet, configObj } = createTokenMock; | ||||
const chronik = new ChronikClient( | const chronik = new ChronikClient( | ||||
'https://FakeChronikUrlToEnsureMocksOnly.com', | 'https://FakeChronikUrlToEnsureMocksOnly.com', | ||||
); | ); | ||||
const invalidWalletTokenCreation = createToken( | const invalidWalletTokenCreation = createToken( | ||||
chronik, | chronik, | ||||
invalidWallet, | invalidWallet, | ||||
currency.defaultFee, | 2.01, | ||||
configObj, | configObj, | ||||
); | ); | ||||
await expect(invalidWalletTokenCreation).rejects.toThrow( | await expect(invalidWalletTokenCreation).rejects.toThrow( | ||||
new Error('Invalid wallet'), | new Error('Invalid wallet'), | ||||
); | ); | ||||
}); | }); | ||||
it(`getRecipientPublicKey() correctly retrieves the public key of a cash address`, async () => { | it(`getRecipientPublicKey() correctly retrieves the public key of a cash address`, async () => { | ||||
Show All 17 Lines |