2020-04-22 17:13:18 +02:00
|
|
|
import { HDSegwitP2SHWallet } from '../../class';
|
2019-09-14 00:15:59 +02:00
|
|
|
const bitcoin = require('bitcoinjs-lib');
|
2020-06-01 14:54:23 +02:00
|
|
|
const assert = require('assert');
|
2019-01-29 03:27:07 +01:00
|
|
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
2020-03-26 17:37:11 +01:00
|
|
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
2020-07-01 13:56:52 +02:00
|
|
|
const BlueElectrum = require('../../blue_modules/BlueElectrum'); // so it connects ASAP
|
2019-03-30 20:21:14 +01:00
|
|
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000;
|
2019-01-29 03:27:07 +01:00
|
|
|
|
|
|
|
afterAll(() => {
|
|
|
|
// after all tests we close socket so the test suite can actually terminate
|
2019-05-06 00:17:31 +02:00
|
|
|
BlueElectrum.forceDisconnect();
|
2019-01-29 03:27:07 +01:00
|
|
|
});
|
2018-06-25 00:19:27 +02:00
|
|
|
|
2019-02-09 01:55:30 +01:00
|
|
|
beforeAll(async () => {
|
|
|
|
// awaiting for Electrum to be connected. For RN Electrum would naturally connect
|
|
|
|
// while app starts up, but for tests we need to wait for it
|
2019-03-30 18:00:34 +01:00
|
|
|
try {
|
|
|
|
await BlueElectrum.waitTillConnected();
|
|
|
|
} catch (Err) {
|
|
|
|
console.log('failed to connect to Electrum:', Err);
|
2019-03-30 20:21:14 +01:00
|
|
|
process.exit(2);
|
2019-03-30 18:00:34 +01:00
|
|
|
}
|
2019-02-09 01:55:30 +01:00
|
|
|
});
|
|
|
|
|
2020-06-01 14:54:23 +02:00
|
|
|
it('HD (BIP49) can work with a gap', async function () {
|
|
|
|
const hd = new HDSegwitP2SHWallet();
|
2019-03-30 14:04:18 +01:00
|
|
|
hd._xpub = 'ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy'; // has gap
|
|
|
|
await hd.fetchBalance();
|
|
|
|
|
|
|
|
// for (let c = 0; c < 5; c++) {
|
|
|
|
// console.log('internal', c, hd._getInternalAddressByIndex(c));
|
|
|
|
// }
|
|
|
|
|
|
|
|
// for (let c = 0; c < 5; c++) {
|
|
|
|
// console.log('external', c, hd._getExternalAddressByIndex(c));
|
|
|
|
// }
|
|
|
|
await hd.fetchTransactions();
|
2019-12-24 00:11:00 +01:00
|
|
|
assert.ok(hd.getTransactions().length >= 3);
|
2019-03-30 14:04:18 +01:00
|
|
|
});
|
|
|
|
|
2020-06-01 14:54:23 +02:00
|
|
|
it('Segwit HD (BIP49) can fetch more data if pointers to last_used_addr are lagging behind', async function () {
|
|
|
|
const hd = new HDSegwitP2SHWallet();
|
2019-05-22 21:48:40 +02:00
|
|
|
hd._xpub = 'ypub6WZ2c7YJ1SQ1rBYftwMqwV9bBmybXzETFxWmkzMz25bCf6FkDdXjNgR7zRW8JGSnoddNdUH7ZQS7JeQAddxdGpwgPskcsXFcvSn1JdGVcPQ';
|
|
|
|
hd.next_free_change_address_index = 40;
|
|
|
|
hd.next_free_address_index = 50;
|
|
|
|
await hd.fetchBalance();
|
|
|
|
await hd.fetchTransactions();
|
2020-01-04 23:38:45 +01:00
|
|
|
assert.strictEqual(hd.getTransactions().length, 153);
|
2019-03-30 14:04:18 +01:00
|
|
|
});
|
|
|
|
|
2018-09-01 01:28:19 +02:00
|
|
|
it('HD (BIP49) can create TX', async () => {
|
2019-06-16 14:41:18 +02:00
|
|
|
if (!process.env.HD_MNEMONIC_BIP49) {
|
2019-06-16 18:20:28 +02:00
|
|
|
console.error('process.env.HD_MNEMONIC_BIP49 not set, skipped');
|
2018-08-14 01:02:50 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-06-01 14:54:23 +02:00
|
|
|
const hd = new HDSegwitP2SHWallet();
|
2019-06-16 14:41:18 +02:00
|
|
|
hd.setSecret(process.env.HD_MNEMONIC_BIP49);
|
2018-08-14 01:02:50 +02:00
|
|
|
assert.ok(hd.validateMnemonic());
|
|
|
|
|
2019-12-24 00:11:00 +01:00
|
|
|
await hd.fetchBalance();
|
2018-08-14 01:02:50 +02:00
|
|
|
await hd.fetchUtxo();
|
2019-12-24 00:11:00 +01:00
|
|
|
assert.ok(typeof hd.utxo[0].confirmations === 'number');
|
|
|
|
assert.ok(hd.utxo[0].txid);
|
|
|
|
assert.ok(hd.utxo[0].vout !== undefined);
|
|
|
|
assert.ok(hd.utxo[0].amount);
|
|
|
|
assert.ok(hd.utxo[0].address);
|
|
|
|
assert.ok(hd.utxo[0].wif);
|
2020-04-22 17:13:18 +02:00
|
|
|
|
|
|
|
let txNew = hd.createTransaction(
|
|
|
|
hd.getUtxo(),
|
|
|
|
[{ address: '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', value: 500 }],
|
|
|
|
1,
|
|
|
|
hd._getInternalAddressByIndex(hd.next_free_change_address_index),
|
|
|
|
);
|
|
|
|
let tx = bitcoin.Transaction.fromHex(txNew.tx.toHex());
|
2019-01-21 14:55:39 +01:00
|
|
|
assert.strictEqual(
|
2020-04-22 17:13:18 +02:00
|
|
|
txNew.tx.toHex(),
|
2020-07-06 19:43:14 +02:00
|
|
|
'0200000000010187c9acd9d5714845343b18abaa26cb83299be2487c22da9c0e270f241b4d9cfe0000000017160014a239b6a0cbc7aadc2e77643de36306a6167fad150000008002f40100000000000017a914a3a65daca3064280ae072b9d6773c027b30abace87ba6200000000000017a9140acff2c37ed45110baece4bb9d4dcc0c6309dbbd8702483045022100a14eb345f26933b29ba2a68075994ecf10f16286611c1d34ccd5850d977c25620220050e80c62ba64d99101253d94f756791f881bdb92100885fbe5ea3e29964573001210202ac3bd159e54dc31e65842ad5f9a10b4eb024e83864a319b27de65ee08b2a3900000000',
|
2018-08-14 01:02:50 +02:00
|
|
|
);
|
2019-01-21 14:55:39 +01:00
|
|
|
assert.strictEqual(tx.ins.length, 1);
|
|
|
|
assert.strictEqual(tx.outs.length, 2);
|
|
|
|
assert.strictEqual(tx.outs[0].value, 500);
|
2020-07-06 19:43:14 +02:00
|
|
|
assert.strictEqual(tx.outs[1].value, 25274);
|
2019-09-14 00:15:59 +02:00
|
|
|
let toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script);
|
2020-06-01 14:54:23 +02:00
|
|
|
const changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script);
|
2019-01-21 14:55:39 +01:00
|
|
|
assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress);
|
|
|
|
assert.strictEqual(hd._getInternalAddressByIndex(hd.next_free_change_address_index), changeAddress);
|
2018-08-14 01:02:50 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
|
2020-04-22 17:13:18 +02:00
|
|
|
txNew = hd.createTransaction(
|
|
|
|
hd.getUtxo(),
|
|
|
|
[{ address: '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', value: 25000 }],
|
|
|
|
5,
|
|
|
|
hd._getInternalAddressByIndex(hd.next_free_change_address_index),
|
|
|
|
);
|
|
|
|
tx = bitcoin.Transaction.fromHex(txNew.tx.toHex());
|
2019-06-16 14:41:18 +02:00
|
|
|
assert.strictEqual(tx.ins.length, 1);
|
2019-01-21 14:55:39 +01:00
|
|
|
assert.strictEqual(tx.outs.length, 1);
|
2019-09-14 00:15:59 +02:00
|
|
|
toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script);
|
2019-01-21 14:55:39 +01:00
|
|
|
assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress);
|
2019-08-04 21:33:15 +02:00
|
|
|
|
|
|
|
// testing sendMAX
|
2020-04-22 17:13:18 +02:00
|
|
|
|
|
|
|
const utxo = [
|
2019-08-04 21:33:15 +02:00
|
|
|
{
|
2020-04-22 17:13:18 +02:00
|
|
|
height: 591862,
|
|
|
|
value: 26000,
|
|
|
|
address: '3C5iv2Hp6nfuhkfTZibb7GJPkXj367eurD',
|
2019-08-04 21:33:15 +02:00
|
|
|
vout: 0,
|
2020-04-22 17:13:18 +02:00
|
|
|
txid: '2000000000000000000000000000000000000000000000000000000000000000',
|
2019-08-04 21:33:15 +02:00
|
|
|
amount: 26000,
|
|
|
|
wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr',
|
2020-04-22 17:13:18 +02:00
|
|
|
confirmations: 1,
|
2019-08-04 21:33:15 +02:00
|
|
|
},
|
|
|
|
{
|
2020-04-22 17:13:18 +02:00
|
|
|
height: 591862,
|
|
|
|
value: 26000,
|
|
|
|
address: '3C5iv2Hp6nfuhkfTZibb7GJPkXj367eurD',
|
2019-08-04 21:33:15 +02:00
|
|
|
vout: 0,
|
2020-04-22 17:13:18 +02:00
|
|
|
txid: '1000000000000000000000000000000000000000000000000000000000000000',
|
2019-08-04 21:33:15 +02:00
|
|
|
amount: 26000,
|
|
|
|
wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr',
|
2020-04-22 17:13:18 +02:00
|
|
|
confirmations: 1,
|
2019-08-04 21:33:15 +02:00
|
|
|
},
|
|
|
|
{
|
2020-04-22 17:13:18 +02:00
|
|
|
height: 591862,
|
|
|
|
value: 26000,
|
|
|
|
address: '3C5iv2Hp6nfuhkfTZibb7GJPkXj367eurD',
|
2019-08-04 21:33:15 +02:00
|
|
|
vout: 0,
|
2020-04-22 17:13:18 +02:00
|
|
|
txid: '0000000000000000000000000000000000000000000000000000000000000000',
|
2019-08-04 21:33:15 +02:00
|
|
|
amount: 26000,
|
|
|
|
wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr',
|
2020-04-22 17:13:18 +02:00
|
|
|
confirmations: 1,
|
2019-08-04 21:33:15 +02:00
|
|
|
},
|
|
|
|
];
|
2020-04-22 17:13:18 +02:00
|
|
|
|
|
|
|
txNew = hd.createTransaction(
|
|
|
|
utxo,
|
|
|
|
[{ address: '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK' }],
|
|
|
|
1,
|
|
|
|
hd._getInternalAddressByIndex(hd.next_free_change_address_index),
|
|
|
|
);
|
|
|
|
tx = bitcoin.Transaction.fromHex(txNew.tx.toHex());
|
2019-08-04 21:33:15 +02:00
|
|
|
assert.strictEqual(tx.outs.length, 1);
|
2020-04-22 17:13:18 +02:00
|
|
|
assert.ok(tx.outs[0].value > 77000);
|
2018-08-14 01:02:50 +02:00
|
|
|
});
|
|
|
|
|
2020-06-01 14:54:23 +02:00
|
|
|
it('Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy', async function () {
|
2019-01-29 03:27:07 +01:00
|
|
|
if (!process.env.HD_MNEMONIC_BIP49_MANY_TX) {
|
|
|
|
console.error('process.env.HD_MNEMONIC_BIP49_MANY_TX not set, skipped');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-01 14:54:23 +02:00
|
|
|
const hd = new HDSegwitP2SHWallet();
|
2019-01-29 03:27:07 +01:00
|
|
|
hd.setSecret(process.env.HD_MNEMONIC_BIP49_MANY_TX);
|
|
|
|
assert.ok(hd.validateMnemonic());
|
2020-06-01 14:54:23 +02:00
|
|
|
const start = +new Date();
|
2019-01-29 03:27:07 +01:00
|
|
|
await hd.fetchBalance();
|
2020-06-01 14:54:23 +02:00
|
|
|
const end = +new Date();
|
2019-01-29 03:27:07 +01:00
|
|
|
const took = (end - start) / 1000;
|
|
|
|
took > 15 && console.warn('took', took, "sec to fetch huge HD wallet's balance");
|
2019-05-02 22:33:03 +02:00
|
|
|
assert.strictEqual(hd.getBalance(), 51432);
|
2019-01-29 03:27:07 +01:00
|
|
|
|
|
|
|
await hd.fetchUtxo();
|
|
|
|
assert.ok(hd.utxo.length > 0);
|
2019-04-14 00:21:41 +02:00
|
|
|
assert.ok(hd.utxo[0].txid);
|
|
|
|
assert.ok(hd.utxo[0].vout === 0);
|
|
|
|
assert.ok(hd.utxo[0].amount);
|
2019-01-29 03:27:07 +01:00
|
|
|
|
|
|
|
await hd.fetchTransactions();
|
|
|
|
assert.strictEqual(hd.getTransactions().length, 107);
|
|
|
|
});
|