Completed
Push — master ( a4251b...3c3114 )
by Ruben de
01:08 queued 15s
created

wallet.test.js ➔ ... ➔ wallet.deleteWallet   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
nop 2
1
/* jshint -W101, -W098 */
2
/* global window */
3
var _ = require('lodash');
4
var blocktrail = require('../');
5
var Wallet = blocktrail.Wallet;
6
var assert = require('assert');
7
var crypto = require('crypto');
8
var async = require('async');
9
var bitcoin = require('bitcoinjs-lib');
10
var bip39 = require("bip39");
11
12
var WAIT_FOR_TX_PROCESSED = process.env.BLOCKTRAIL_WAIT_FOR_TX || 300;
13
14
/**
15
 *
16
 * @param network
17
 * @param testnet
18
 * @returns {*}
19
 * @private
20
 */
21
function _createApiClient(network, testnet) {
22
    return blocktrail.BlocktrailSDK({
23
        apiKey : process.env.BLOCKTRAIL_SDK_APIKEY || window.BLOCKTRAIL_SDK_APIKEY || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APIKEY",
24
        apiSecret : process.env.BLOCKTRAIL_SDK_APISECRET || window.BLOCKTRAIL_SDK_APISECRET || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APISECRET",
25
        network: network,
26
        testnet : testnet
27
    });
28
}
29
30
/**
31
 * @type APIClient
32
 */
33
var client = _createApiClient("BTC", true);
34
35
var TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC = "give pause forget seed dance crawl situate hole keen",
36
    TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC = "give pause forget seed dance crawl situate hole give",
37
    TRANSACTION_TEST_WALLET_PASSWORD = "password";
38
39
var _createTestWallet = function(identifier, passphrase, primaryMnemonic, backupMnemonic, segwit, cb) {
40
    var keyIndex = 9999;
41
    var network = client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
42
43
    var primarySeed = bip39.mnemonicToSeed(primaryMnemonic, passphrase);
44
    var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, network);
45
46
    var backupSeed = bip39.mnemonicToSeed(backupMnemonic, "");
47
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(backupSeed, network);
48
    var backupPublicKey = backupPrivateKey.neutered();
49
50
    var checksum = primaryPrivateKey.getAddress();
51
    var primaryPublicKey = primaryPrivateKey.deriveHardened(keyIndex).neutered();
52
53
    client.storeNewWalletV1(
54
        identifier,
55
        [primaryPublicKey.toBase58(), "M/" + keyIndex + "'"],
56
        [backupPublicKey.toBase58(), "M"],
57
        primaryMnemonic,
58
        checksum,
59
        keyIndex,
60
        segwit
61
    ).then(function(result) {
62
        var blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
63
            return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], network);
64
        });
65
66
        var wallet = new blocktrail.Wallet(
67
            client,
68
            identifier,
69
            blocktrail.Wallet.WALLET_VERSION_V1,
70
            primaryMnemonic,
71
            null,
72
            null,
73
            {keyIndex: primaryPublicKey},
74
            backupPublicKey,
75
            blocktrailPublicKeys,
76
            keyIndex,
77
            result.segwit || 0,
78
            client.testnet,
79
            checksum
80
        );
81
82
        wallet.unlock({
83
            passphrase: passphrase
84
        }, function(err) {
85
            cb(err, wallet);
86
        });
87
88
    }, function(err) {
89
        return cb(err);
90
    });
91
};
92
93
var createUpgradeKeyIndexTestWallet = function(identifier, passphrase, cb) {
94
    var primaryMnemonic = "give pause forget seed dance crawl situate hole kingdom";
95
    var backupMnemonic = "give pause forget seed dance crawl situate hole course";
96
97
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, false, cb);
98
};
99
100
var createTransactionTestWallet = function(identifier, segwit, cb) {
101
    return _createTestWallet(
102
        identifier,
103
        TRANSACTION_TEST_WALLET_PASSWORD,
104
        TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC,
105
        TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC,
106
        segwit,
107
        cb
108
    );
109
};
110
111
var createRecoveryTestWallet = function(identifier, passphrase, cb) {
112
    var primaryMnemonic = "give pause forget seed dance crawl situate hole join";
113
    var backupMnemonic = "give pause forget seed dance crawl situate hole crater";
114
115
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, false, cb);
116
};
117
118
describe('Initialize with check_backup_key', function() {
119
    it('rejects invalid inputs', function(cb) {
120
        try {
121
            client.initWallet({
122
                identifier: "unittest-transaction",
123
                password: "password",
124
                check_backup_key: []
125
            });
126
            assert(false);
127
        } catch (e) {
128
            assert.equal("Invalid input, must provide the backup key as a string (the xpub)", e.message);
129
        }
130
        cb();
131
    });
132
133
    it('checks against the string', function(cb) {
134
        client.initWallet({
135
            identifier: "unittest-transaction",
136
            password: "password",
137
            check_backup_key: 'for demonstration purposes only'
138
        }, function(err, _wallet) {
0 ignored issues
show
Unused Code introduced by
The parameter _wallet is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
139
            assert.ok(err);
140
            assert.equal("Backup key returned from server didn't match our own copy", err.message);
141
            cb();
142
        });
143
    });
144
145
    it('allows if the backup key matches', function(cb) {
146
        // You wouldn't keep your backup seed in your code,
147
        // dump it from the wallet upon generation
148
149
        var backupSeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC, "");
150
        var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(backupSeed, bitcoin.networks.testnet);
151
        var backupPublicKey = backupPrivateKey.neutered();
152
        var xpub = backupPublicKey.toBase58();
153
154
        // Would be saves as a string in code..
155
        client.initWallet({
156
            identifier: "unittest-transaction",
157
            password: "password",
158
            check_backup_key: xpub
159
        }, function(err, _wallet) {
160
            assert.ifError(err);
161
            assert.ok(_wallet);
162
            cb();
163
        });
164
    });
165
});
166
167
/**
168
 * Test operations on v2 and v3 wallets.
169
 * Also tests the default, encouraging to look at this test if it changes again.
170
 */
171
[
172
  blocktrail.Wallet.WALLET_VERSION_V2,
173
  blocktrail.Wallet.WALLET_VERSION_V3,
174
  null /* test our assumed default version */
175
].map(function(walletVersion) {
176
    var assumedDefault = blocktrail.Wallet.WALLET_VERSION_V3;
177
    describe('test new blank wallet, ' + walletVersion, function() {
178
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
179
        var wallet;
180
181
        after(function(cb) {
182
            if (wallet) {
183
                wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
184
                    cb();
185
                });
186
            } else {
187
                cb();
188
            }
189
        });
190
191
        it("shouldn't already exist", function(cb) {
192
            client.initWallet({
193
                identifier: myIdentifier,
194
                readOnly: true
195
            }, function(err, wallet) {
196
                assert.ok(err);
197
                assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
198
199
                cb();
200
            });
201
        });
202
203
        it("should be created", function(cb) {
204
            var progress = [];
205
            var cnf = {
206
                identifier: myIdentifier,
207
                passphrase: "password",
208
                keyIndex: 9999
209
            };
210
211
            var expectedVersion = assumedDefault;
212
            if (walletVersion !== null) {
213
                cnf.walletVersion = walletVersion;
214
                expectedVersion = walletVersion;
215
            }
216
217
            client.createNewWallet(cnf, function(err, _wallet, backupInfo) {
0 ignored issues
show
Unused Code introduced by
The parameter backupInfo is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
218
                assert.ifError(err);
219
                assert.ok(_wallet);
220
221
                wallet = _wallet;
222
                assert.equal(wallet.walletVersion, expectedVersion);
223
                assert.equal(wallet.identifier, myIdentifier);
224
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
225
226
                assert.deepEqual(progress, [
227
                    blocktrail.CREATE_WALLET_PROGRESS_START,
228
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_SECRET,
229
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_PRIMARY,
230
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_RECOVERY,
231
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
232
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
233
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
234
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
235
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
236
                ]);
237
238
                cb();
239
            })
240
            .progress(function(p) { progress.push(p); });
241
        });
242
243
        it("should lock", function(cb) {
244
            assert(!wallet.locked);
245
            wallet.lock();
246
            assert(wallet.locked);
247
            cb();
248
        });
249
250
        it("should init", function(cb) {
251
            client.initWallet({
252
                identifier: myIdentifier,
253
                readOnly: true
254
            }, function(err, _wallet) {
255
                assert.ifError(err);
256
                assert.ok(_wallet);
257
258
                wallet = _wallet;
259
260
                cb();
261
            });
262
        });
263
264
        it("should have a 0 balance", function(cb) {
265
            wallet.getBalance(function(err, confirmed, unconfirmed) {
266
                assert.ifError(err);
267
                assert.equal(confirmed, 0);
268
                assert.equal(unconfirmed, 0);
269
270
                cb();
271
            });
272
        });
273
274
        it("shouldn't be able to pay when locked", function(cb) {
275
            wallet.pay({
276
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
277
            }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
278
                assert.ok(!!err && err.message.match(/unlocked/));
279
                assert.ok(err instanceof blocktrail.WalletLockedError);
280
281
                cb();
282
            });
283
        });
284
285
        it("shouldn't be able to upgrade when locked", function(cb) {
286
            wallet.upgradeKeyIndex(10000, function(err) {
287
                assert.ok(!!err && err.message.match(/unlocked/));
288
                assert.ok(err instanceof blocktrail.WalletLockedError);
289
290
                cb();
291
            });
292
        });
293
294
        it("should unlock", function(cb) {
295
            wallet.unlock({password: "password"}, function(err) {
296
                assert.ifError(err);
297
298
                cb();
299
            });
300
        });
301
302
        it("should be able to unlock with secret", function(cb) {
303
            var secret = wallet.secret;
304
305
            wallet.lock();
306
            wallet.unlock({secret: secret}, function(err) {
307
                assert.ifError(err);
308
                cb();
309
            });
310
        });
311
312
        it("shouldn't be able to pay when unlocked (because of no balance)", function(cb) {
313
            wallet.pay({
314
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
315
            }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
316
                assert.ok(!!err && err.message.match(/balance/));
317
318
                cb();
319
            });
320
        });
321
322
        it("should be able to upgrade when unlocked", function(cb) {
323
            wallet.upgradeKeyIndex(10000, function(err) {
324
                assert.ifError(err);
325
326
                cb();
327
            });
328
        });
329
330
        it("should be able to password change", function(cb) {
331
            wallet.passwordChange("password2", function(err) {
332
                assert.ifError(err);
333
334
                client.initWallet({
335
                    identifier: myIdentifier,
336
                    password: "password2"
337
                }, function(err, _wallet) {
338
                    assert.ifError(err);
339
                    assert.ok(_wallet);
340
341
                    wallet = _wallet;
342
343
                    cb();
344
                });
345
            });
346
        });
347
348
        [
349
            ['', 'string'],
350
            [false, 'string'],
351
            [true, 'boolean']
352
        ].map(function(fixture) {
353
            var invalidInput = fixture[0];
354
            var type = fixture[1];
355
            it('refuses to derive with invalid chain index variable ' + type, function(cb) {
356
                wallet.getNewAddress(invalidInput, function(err, res) {
0 ignored issues
show
Unused Code introduced by
The parameter res is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
357
                    assert.ok(!!err && err.message.match(/chain index/));
358
                    cb();
359
                });
360
            });
361
        });
362
    });
363
});
364
365
/**
366
 * Test operations on v2 and v3 wallets.
367
 */
368
[
369
    blocktrail.Wallet.WALLET_VERSION_V1,
370
    blocktrail.Wallet.WALLET_VERSION_V2,
371
    blocktrail.Wallet.WALLET_VERSION_V3
372
].map(function(walletVersion) {
373
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
374
375
    describe('test input errors, ' + walletVersion, function() {
376
        it("shouldn't allow primaryPrivateKey in creation", function(cb) {
377
            var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
378
            var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet);
379
380
            client.createNewWallet({
381
                identifier: myIdentifier,
382
                passphrase: "password",
383
                primaryPrivateKey: primaryPrivateKey,
384
                walletVersion: walletVersion,
385
                keyIndex: 9999
386
            }, function(err, wallet) {
0 ignored issues
show
Unused Code introduced by
The parameter wallet is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
387
                assert.ok(!!err, "should error");
388
389
                cb();
390
            });
391
        });
392
393
        it("shouldn't allow unlocking with primaryPrivateKey", function(cb) {
394
            client.createNewWallet({
395
                identifier: "unittest-transaction-inputerr-" + walletVersion,
396
                primarySeed: primarySeed,
397
                walletVersion: walletVersion,
398
                keyIndex: 9999
399
            }).then(function(r) {
400
                var wallet = r[0];
401
                wallet.lock();
402
                return wallet;
403
            }, function(err) {
404
                assert.ok(err.message.match(/already exists/));
405
406
                return client.initWallet({
407
                    identifier: "unittest-transaction-inputerr-" + walletVersion,
408
                    readOnly: true
409
                });
410
            }).then(function(wallet) {
411
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
412
413
                return wallet.unlock({primaryPrivateKey: bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet)})
414
                    .then(function() {
415
                        return;
0 ignored issues
show
Unused Code introduced by
This return has no effect and can be removed.
Loading history...
416
                    }, function(err) {
417
                        return err;
418
                    });
419
            })
420
                .then(function(err) {
421
                    assert.ok(!!err, "should error");
422
                    cb();
423
                })
424
                .done();
425
        });
426
    });
427
});
428
429
/**
430
 * Test upgrade to V3 from V1 and V2
431
 */
432
[
433
    blocktrail.Wallet.WALLET_VERSION_V1,
434
    blocktrail.Wallet.WALLET_VERSION_V2
435
].map(function(walletVersion) {
436
    describe("upgrade to V3 from " + walletVersion, function() {
437
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
438
        var passphrase = "password";
439
        var wallet;
440
441
        after(function(cb) {
442
            if (wallet) {
443
                wallet.deleteWallet(true, function(err, result) {
444
                    console.log(err, result);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
445
                    cb();
446
                });
447
            } else {
448
                cb();
449
            }
450
        });
451
452
        it("can upgrade", function() {
453
            var addr;
454
            return client.createNewWallet({
455
                identifier: myIdentifier,
456
                passphrase: passphrase,
457
                walletVersion: walletVersion,
458
                keyIndex: 9999
459
            })
460
                .then(function(r) {
461
                    return r[0];
462
                })
463
                .then(function(_wallet) {
464
                    wallet = _wallet;
465
                    addr = wallet.getAddressByPath("M/9999'/0/0");
466
467
                    return wallet;
468
                })
469
                .then(function(wallet) {
470
                    var progress = [];
471
472
                    return wallet.upgradeToV3(passphrase)
473
                        .progress(function(p) {
474
                            progress.push(p);
475
                        })
476
                        .then(function() {
477
                            assert(progress.length);
478
                            return wallet;
479
                        });
480
                })
481
                .then(function(wallet) {
482
                    assert.equal(addr, wallet.getAddressByPath("M/9999'/0/0"));
483
                });
484
        });
485
486
        it("can unlock with secret", function() {
487
            var secret = wallet.secret;
488
            wallet.lock();
489
            return wallet.unlock({secret: secret});
490
        });
491
492
        it("can init after upgrade", function() {
493
            return client.initWallet({
494
                identifier: myIdentifier,
495
                passphrase: passphrase,
496
                keyIndex: 9999
497
            });
498
        });
499
    });
500
});
501
502
describe('test new blank wallet, v1', function() {
503
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
504
    var wallet;
505
506
    after(function(cb) {
507
        if (wallet) {
508
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
509
                cb();
510
            });
511
        } else {
512
            cb();
513
        }
514
    });
515
516
    it("shouldn't already exist", function(cb) {
517
        client.initWallet({
518
            identifier: myIdentifier,
519
            readOnly: true
520
        }, function(err, wallet) {
521
            assert.ok(err);
522
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
523
524
            cb();
525
        });
526
    });
527
528
    it("should be created", function(cb) {
529
        var progress = [];
530
531
        client.createNewWallet({
532
                identifier: myIdentifier,
533
                passphrase: "password",
534
                keyIndex: 9999,
535
                walletVersion: blocktrail.Wallet.WALLET_VERSION_V1
536
            }, function(err, _wallet) {
537
                assert.ifError(err);
538
                assert.ok(_wallet);
539
540
                wallet = _wallet;
541
542
                assert.equal(wallet.identifier, myIdentifier);
543
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
544
545
                assert.deepEqual(progress, [
546
                    blocktrail.CREATE_WALLET_PROGRESS_START,
547
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
548
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
549
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
550
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
551
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
552
                ]);
553
554
                cb();
555
            }
556
        ).progress(function(p) { progress.push(p); });
557
    });
558
559
    it("should lock", function(cb) {
560
        assert(!wallet.locked);
561
        wallet.lock();
562
        assert(wallet.locked);
563
        cb();
564
    });
565
566
    it("should init", function(cb) {
567
        client.initWallet({
568
            identifier: myIdentifier,
569
            readOnly: true
570
        }, function(err, _wallet) {
571
            assert.ifError(err);
572
            assert.ok(_wallet);
573
            assert.equal(wallet.walletVersion, 'v1');
574
575
            wallet = _wallet;
576
577
            cb();
578
        });
579
    });
580
581
    it("should have a 0 balance", function(cb) {
582
        wallet.getBalance(function(err, confirmed, unconfirmed) {
583
            assert.ifError(err);
584
            assert.equal(confirmed, 0);
585
            assert.equal(unconfirmed, 0);
586
587
            cb();
588
        });
589
    });
590
591
    it("should unlock", function(cb) {
592
        wallet.unlock({password: "password"}, function(err) {
593
            assert.ifError(err);
594
595
            cb();
596
        });
597
    });
598
599
    it("shouldn't be able to password change", function(cb) {
600
        wallet.passwordChange("password2", function(err) {
601
            assert.ok(!!err && err.message.match(/version does not support/));
602
603
            cb();
604
        });
605
    });
606
});
607
608
describe('test new blank wallet, old syntax', function() {
609
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
610
    var wallet;
611
612
    after(function(cb) {
613
        if (wallet) {
614
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
615
                cb();
616
            });
617
        } else {
618
            cb();
619
        }
620
    });
621
622
    it("shouldn't already exist", function(cb) {
623
        client.initWallet(myIdentifier, "password", function(err, wallet) {
624
            assert.ok(err);
625
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
626
627
            cb();
628
        });
629
    });
630
631
    it("should be created", function(cb) {
632
        client.createNewWallet(myIdentifier, "password", 9999, function(err, _wallet) {
633
            assert.ifError(err);
634
            assert.ok(_wallet);
635
636
            wallet = _wallet;
637
638
            assert.equal(wallet.identifier, myIdentifier);
639
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
640
            cb();
641
        });
642
    });
643
644
    it("should have a 0 balance", function(cb) {
645
        wallet.getBalance(function(err, confirmed, unconfirmed) {
646
            assert.ifError(err);
647
            assert.equal(confirmed, 0);
648
            assert.equal(unconfirmed, 0);
649
650
            cb();
651
        });
652
    });
653
654
    it("shouldn't be able to pay", function(cb) {
655
        wallet.pay({
656
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
657
        }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
658
            assert.ok(!!err);
659
660
            cb();
661
        });
662
    });
663
});
664
665
describe('test new wallet, without mnemonics', function() {
666
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
667
    var wallet;
668
669
    var primarySeed = bip39.mnemonicToSeed(bip39.generateMnemonic(512), "password");
670
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(bip39.generateMnemonic(512), ""), bitcoin.networks.testnet);
671
    var backupPublicKey = backupPrivateKey.neutered();
672
673
    after(function(cb) {
674
        if (wallet) {
675
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
676
                cb();
677
            });
678
        } else {
679
            cb();
680
        }
681
    });
682
683
    it("shouldn't already exist", function(cb) {
684
        client.initWallet({
685
            identifier: myIdentifier
686
        }, function(err, wallet) {
687
            assert.ok(err);
688
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
689
690
            cb();
691
        });
692
    });
693
694
    it("should be created", function(cb) {
695
        client.createNewWallet({
696
                identifier: myIdentifier,
697
                primarySeed: primarySeed,
698
                backupPublicKey: backupPublicKey,
699
                keyIndex: 9999
700
            }, function(err, _wallet) {
701
                assert.ifError(err);
702
                assert.ok(_wallet);
703
                assert.ok(!_wallet.isSegwit());
704
                assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
705
706
                wallet = _wallet;
707
708
                assert.equal(wallet.identifier, myIdentifier);
709
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
710
                cb();
711
            }
712
        );
713
    });
714
715
    it("should be initializable", function(cb) {
716
        client.initWallet({
717
                identifier: myIdentifier,
718
                primarySeed: primarySeed,
719
                keyIndex: 9999
720
            }, function(err, _wallet) {
721
                assert.ifError(err);
722
                assert.ok(_wallet);
723
                assert.ok(!_wallet.isSegwit());
724
                assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
725
726
                wallet = _wallet;
727
728
                cb();
729
            }
730
        );
731
    });
732
733
    it("should have a 0 balance", function(cb) {
734
        wallet.getBalance(function(err, confirmed, unconfirmed) {
735
            assert.ifError(err);
736
            assert.equal(confirmed, 0);
737
            assert.equal(unconfirmed, 0);
738
739
            cb();
740
        });
741
    });
742
743
    it("shouldn't be able to pay", function(cb) {
744
        wallet.pay({
745
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
746
        }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
747
            assert.ok(!!err);
748
749
            cb();
750
        });
751
    });
752
});
753
754
describe('test wallet, bitcoin cash mirror', function() {
755
    var tbccClient = _createApiClient("BCC", true);
756
757
    [
758
        {useCashAddress: false, addressType: "base58", description: "false uses base58 address"},
759
        {useCashAddress: true,  addressType: "cashaddr", description: "can opt into cash address"}
760
761
    ].map(function(fixture) {
762
        var useCashAddress = fixture.useCashAddress;
763
        var expectType = fixture.addressType;
764
        var description = fixture.description;
765
766
        var wallet;
767
        var address;
768
769
        it(description, function(cb) {
770
            tbccClient.initWallet({
771
                identifier: "unittest-transaction",
772
                passphrase: TRANSACTION_TEST_WALLET_PASSWORD,
773
                useCashAddress: useCashAddress
774
            }, function(err, _wallet) {
775
                assert.ifError(err);
776
                assert.ok(_wallet);
777
                assert.ok(!_wallet.isSegwit());
778
                assert.equal(_wallet.chain, blocktrail.Wallet.CHAIN_BCC_DEFAULT);
779
                wallet = _wallet;
780
781
                assert.equal(useCashAddress, _wallet.useNewCashAddr);
782
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
783
                assert.equal(wallet.identifier, "unittest-transaction");
784
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
785
                cb();
786
            });
787
        });
788
789
        it("derives the right address (" + description + ")", function(cb) {
790
            wallet.getNewAddress(function(err, serverAddress, path) {
791
                assert.ifError(err);
792
                assert.ok(serverAddress);
793
                assert.ok(path);
794
795
                var decoded = wallet.decodeAddress(serverAddress);
796
                assert.ok(decoded);
797
                assert.equal(serverAddress, decoded.address);
798
                assert.equal(expectType, decoded.type);
799
800
                address = serverAddress;
801
                cb();
802
            });
803
        });
804
805
        it("can coin select address (" + expectType + ")", function(cb) {
806
            var pay = {};
807
            pay[address] = 12345;
808
            wallet.coinSelection(pay, function(err, utxos) {
809
                assert.ifError(err);
810
                assert.ok(utxos);
811
                assert.ok(utxos.length > 0);
812
813
                cb();
814
            });
815
        });
816
    });
817
});
818
819
describe('test wallet, do transaction', function() {
820
    var wallet;
821
822
    it("should exists", function(cb) {
823
        client.initWallet({
824
            identifier: "unittest-transaction",
825
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
826
        }, function(err, _wallet) {
827
            assert.ifError(err);
828
            assert.ok(_wallet);
829
            assert.ok(!_wallet.isSegwit());
830
            assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
831
            wallet = _wallet;
832
833
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
834
            assert.equal(wallet.identifier, "unittest-transaction");
835
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
836
            cb();
837
        });
838
    });
839
840
    it("should have the expected addresses", function(cb) {
841
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
842
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
843
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
844
845
        cb();
846
    });
847
848
    it("should have a balance", function(cb) {
849
        this.timeout(0);
850
851
        wallet.getBalance(function(err, confirmed, unconfirmed) {
852
            assert.ok(confirmed + unconfirmed > 0);
853
            assert.ok(confirmed > 0);
854
855
            cb();
856
        });
857
    });
858
859
    it("should return errors when expected", function(cb) {
860
        async.parallel([
861
            function(cb) {
862
                wallet.pay({"": blocktrail.toSatoshi(0.001)}, function(err) {
863
                    assert.ok(!!err);
864
                    assert.equal(err.message, "Invalid address [] (Invalid checksum)");
865
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
866
867
                    cb();
868
                });
869
            },
870
            function(cb) {
871
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA": blocktrail.toSatoshi(0.001)}, function(err) {
872
                    assert.ok(!!err);
873
                    assert.equal(err.message, "Invalid address [2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA] (Invalid checksum)");
874
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
875
876
                    cb();
877
                });
878
            },
879
            function(cb) {
880
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1}, function(err) {
881
                    assert.ok(!!err);
882
                    assert.equal(err.message, "Values should be more than dust (" + blocktrail.DUST + ")");
883
                    assert.ok(err instanceof blocktrail.WalletSendError);
884
885
                    cb();
886
                });
887
            },
888
            function(cb) {
889
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 0}, function(err) {
890
                    assert.ok(!!err);
891
                    assert.equal(err.message, "Values should be non zero");
892
                    assert.ok(err instanceof blocktrail.WalletSendError);
893
894
                    cb();
895
                });
896
            },
897
            function(cb) {
898
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1.1}, function(err) {
899
                    assert.ok(!!err);
900
                    assert.equal(err.message, "Values should be in Satoshis");
901
                    assert.ok(err instanceof blocktrail.WalletSendError);
902
903
                    cb();
904
                });
905
            }
906
        ], cb);
907
    });
908
909
    it("should be able to build a transaction paying a bech32 address", function(cb) {
910
        var address = "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs";
911
        var wp = "00149bce9399f9eeddad66635d4be171ec8f14decc59";
912
        var pay = {};
913
        pay[address] = blocktrail.toSatoshi(0.001);
914
915
        wallet.buildTransaction(pay, null, false, false, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
916
            assert.ifError(err);
917
            assert.ok(tx);
918
            assert.ok(tx.toHex());
919
            assert.equal(wp, tx.outs[0].script.toString('hex'));
920
            cb();
921
        });
922
    });
923
924
    it("change should be randomized when building a transaction", function(cb) {
925
        wallet.getNewAddress(function(err, address, path) {
926
            assert.ifError(err);
927
            assert.ok(path.indexOf("M/9999'/0/") === 0);
928
            assert.ok(bitcoin.address.fromBase58Check(address));
929
930
            var pay = {};
931
            pay[address] = blocktrail.toSatoshi(0.001);
932
933
            var changeIdxs = [];
934
            var tryX = 10;
935
936
            async.whilst(
937
                function() { return tryX-- > 0 && _.uniq(changeIdxs).length < 2; },
938
                function(cb) {
939
                    wallet.buildTransaction(pay, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
940
                        assert.ifError(err);
941
942
                        tx.outs.forEach(function(output, idx) {
943
                            var addr = bitcoin.address.fromOutputScript(output.script, client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin);
944
945
                            if (addr !== address) {
946
                                changeIdxs.push(idx);
947
                            }
948
                        });
949
950
                        cb();
951
                    });
952
                },
953
                function() {
954
                    assert(_.uniq(changeIdxs).length > 1);
955
956
                    cb();
957
                }
958
            );
959
        });
960
961
        it("should be able to build a transaction", function(cb) {
0 ignored issues
show
Unused Code introduced by
The parameter cb is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
962
            wallet.getNewAddress(function(err, address, path) {
963
                assert.ifError(err);
964
                assert.ok(path.indexOf("M/9999'/0/") === 0);
965
                assert.ok(bitcoin.address.fromBase58Check(address));
966
967
                var pay = {};
968
                pay[address] = blocktrail.toSatoshi(0.001);
969
970
                wallet.buildTransaction(pay, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
971
                    assert.ifError(err);
972
                    assert.ok(tx);
973
                    assert.ok(tx.toHex());
974
                });
975
            });
976
        });
977
    });
978
979
    it("should be able to do a payment", function(cb) {
980
        wallet.getNewAddress(function(err, address, path) {
981
            assert.ifError(err);
982
            assert.ok(path.indexOf("M/9999'/", wallet.chain, "/") === 0);
983
            assert.ok(bitcoin.address.fromBase58Check(address));
984
985
            var pay = {};
986
            pay[address] = blocktrail.toSatoshi(0.001);
987
988
            var progress = [];
989
990
            wallet.pay(pay, function(err, txHash) {
991
                assert.ifError(err);
992
                assert.ok(txHash);
993
994
                // change address doesn't always happen ...
995
                if (progress.indexOf(blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS) === -1) {
996
                    progress.splice(2, 0, blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS);
997
                }
998
999
                assert.deepEqual(progress, [
1000
                    blocktrail.Wallet.PAY_PROGRESS_START,
1001
                    blocktrail.Wallet.PAY_PROGRESS_COIN_SELECTION,
1002
                    blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS,
1003
                    blocktrail.Wallet.PAY_PROGRESS_SIGN,
1004
                    blocktrail.Wallet.PAY_PROGRESS_SEND,
1005
                    blocktrail.Wallet.PAY_PROGRESS_DONE
1006
                ]);
1007
1008
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1009
                setTimeout(function() {
1010
                    client.transaction(txHash, function(err, tx) {
1011
                        assert.ifError(err);
1012
                        assert.ok(tx);
1013
1014
                        cb();
1015
                    });
1016
                }, WAIT_FOR_TX_PROCESSED);
1017
            }).progress(function(_progress) {
1018
                progress.push(_progress);
1019
            });
1020
        });
1021
    });
1022
});
1023
1024
describe('test wallet with segwit chain', function() {
1025
    var wallet;
1026
1027
    it("should exist and be setup", function(cb) {
1028
        client.initWallet({
1029
            identifier: "unittest-transaction-sw",
1030
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1031
        }, function(err, _wallet) {
1032
            assert.ifError(err);
1033
            assert.ok(_wallet);
1034
            assert.equal(_wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1035
            assert.equal(_wallet.identifier, "unittest-transaction-sw");
1036
            assert.equal(_wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1037
            assert.ok(_wallet.isSegwit());
1038
            assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
1039
            assert.equal(blocktrail.Wallet.CHAIN_BTC_SEGWIT, _wallet.changeChain);
1040
1041
            wallet = _wallet;
1042
            cb();
1043
        });
1044
    });
1045
1046
    it("getNewAddress produces plain P2SH addresses", function(cb) {
1047
        wallet.getNewAddress(function(err, address, path) {
1048
            assert.ifError(err);
1049
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1050
1051
            assert.ok(bitcoin.address.fromBase58Check(address));
1052
1053
            cb();
1054
        });
1055
    });
1056
1057
    it("getNewAddress produces segwit P2SH addresses for change chain", function(cb) {
1058
        wallet.getNewAddress(wallet.changeChain, function(err, address, path) {
1059
            assert.ifError(err);
1060
            assert.ok(path.indexOf("M/9999'/2/") === 0);
1061
1062
            assert.ok(bitcoin.address.fromBase58Check(address));
1063
1064
            cb();
1065
        });
1066
    });
1067
1068
    it("getWalletScriptByPath produces P2SH addresses, and returns witnessScript", function(cb) {
1069
        var eAddress = "2N3j4Vx3D9LPumjtRbRe2RJpwVocvCCkHKh";
1070
1071
        assert.equal(wallet.getAddressByPath("M/9999'/2/0"), eAddress);
1072
1073
        var walletScript = wallet.getWalletScriptByPath("M/9999'/2/0");
1074
        assert.equal(walletScript.address, eAddress);
1075
        assert.ok(walletScript.witnessScript);
1076
        assert.ok(walletScript.redeemScript);
1077
        cb();
1078
    });
1079
});
1080
1081
describe('test wallet, do transaction, segwit spend', function() {
1082
    var wallets = [];
1083
    after(function(cb) {
1084
        if (wallets.length > 0) {
1085
            wallets.map(function(wallet) {
1086
                wallet.deleteWallet(true);
1087
            });
1088
        }
1089
        cb();
1090
    });
1091
1092
    var unitTestWallet;
1093
    var identifier = crypto.randomBytes(12).toString('hex');
1094
    var segwitWallet;
1095
    var receiveAddr;
1096
    var receiveBackAddr;
1097
    it("should setup the funding wallet", function(cb) {
1098
        client.initWallet({
1099
            identifier: "unittest-transaction",
1100
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1101
        }, function(err, _wallet) {
1102
            assert.ifError(err);
1103
            assert.ok(_wallet);
1104
1105
            _wallet.getNewAddress(function(err, address, path) {
1106
                assert.ifError(err);
1107
                assert.ok(address);
1108
                assert.ok(path);
1109
1110
                unitTestWallet = _wallet;
1111
                receiveBackAddr = address;
1112
                cb();
1113
            });
1114
        });
1115
    });
1116
1117
    it("should make the receiving segwit wallet", function(cb) {
1118
        createTransactionTestWallet(identifier, true, function(err, newWallet) {
1119
            wallets.push(newWallet);
1120
            assert.ifError(err);
1121
            newWallet.getNewAddress(newWallet.changeChain, function(err, address, path) {
1122
                assert.ifError(err);
1123
                assert.ok(bitcoin.address.fromBase58Check(address));
1124
                assert.ok(newWallet.isSegwit());
1125
                assert.ok(path.indexOf("M/9999'/2/") === 0);
1126
1127
                var checkScript = newWallet.getWalletScriptByPath(path);
1128
                assert.ok(checkScript.address = address);
1129
                assert.ok(checkScript.redeemScript instanceof Buffer);
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
1130
                assert.ok(checkScript.witnessScript instanceof Buffer);
1131
1132
                segwitWallet = newWallet;
1133
                receiveAddr = address;
1134
                cb();
1135
            });
1136
        });
1137
    });
1138
1139
    var paymentHash;
1140
    it("should receive funds from unitTestWallet", function(cb) {
1141
        var pay = {};
1142
        pay[receiveAddr] = 30000;
1143
        unitTestWallet.pay(pay, null, true, function(err, txid) {
1144
            assert.ifError(err);
1145
            assert.ok(txid);
1146
            paymentHash = txid;
0 ignored issues
show
Unused Code introduced by
The variable paymentHash seems to be never used. Consider removing it.
Loading history...
1147
            cb();
1148
        });
1149
    });
1150
1151
    it("should return to unitTestWallet", function(cb) {
1152
        var pay = {};
1153
        pay[receiveBackAddr] = 20000;
1154
        segwitWallet.pay(pay, null, true, function(err, txid) {
1155
            assert.ifError(err);
1156
            assert.ok(txid);
1157
1158
            setTimeout(function() {
1159
                client.transaction(txid, function(err, tx) {
1160
                    assert.ifError(err);
1161
                    assert.ok(tx);
1162
                    cb();
1163
                });
1164
            }, WAIT_FOR_TX_PROCESSED);
1165
        });
1166
    });
1167
});
1168
describe('test wallet, do transaction, without mnemonics', function() {
1169
    var wallet;
1170
1171
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
1172
1173
    it("should exists", function(cb) {
1174
        client.initWallet({
1175
                identifier: "unittest-transaction",
1176
                primarySeed: primarySeed,
1177
                primaryMnemonic: false // explicitly set false because we're reusing unittest-transaction which has a mnemonic stored
1178
            }, function(err, _wallet) {
1179
                assert.ifError(err);
1180
                assert.ok(_wallet);
1181
1182
                wallet = _wallet;
1183
1184
                assert.equal(wallet.identifier, "unittest-transaction");
1185
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1186
                cb();
1187
            }
1188
        );
1189
    });
1190
1191
    it("should have the expected addresses", function(cb) {
1192
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
1193
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
1194
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
1195
1196
        cb();
1197
    });
1198
1199
    it("should have a balance", function(cb) {
1200
        this.timeout(0);
1201
1202
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1203
            assert.ok(confirmed + unconfirmed > 0);
1204
            assert.ok(confirmed > 0);
1205
1206
            cb();
1207
        });
1208
    });
1209
1210
    it("should be able to do a payment", function(cb) {
1211
        wallet.getNewAddress(function(err, address, path) {
1212
            assert.ifError(err);
1213
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1214
            assert.ok(bitcoin.address.fromBase58Check(address));
1215
1216
            var pay = {};
1217
            pay[address] = blocktrail.toSatoshi(0.001);
1218
1219
            wallet.pay(pay, function(err, txHash) {
1220
                assert.ifError(err);
1221
                assert.ok(txHash);
1222
1223
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1224
                setTimeout(function() {
1225
                    client.transaction(txHash, function(err, tx) {
1226
                        assert.ifError(err);
1227
                        assert.ok(tx);
1228
1229
                        cb();
1230
                    });
1231
                }, WAIT_FOR_TX_PROCESSED);
1232
            });
1233
        });
1234
    });
1235
});
1236
1237
describe('test wallet, do opreturn transaction', function() {
1238
    var wallet;
1239
1240
    it("should exists", function(cb) {
1241
        client.initWallet({
1242
            identifier: "unittest-transaction",
1243
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1244
        }, function(err, _wallet) {
1245
            assert.ifError(err);
1246
            assert.ok(_wallet);
1247
1248
            wallet = _wallet;
1249
1250
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1251
            assert.equal(wallet.identifier, "unittest-transaction");
1252
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1253
            cb();
1254
        });
1255
    });
1256
1257
    it("should be able to do a payment with opreturn output", function(cb) {
1258
        wallet.getNewAddress(function(err, address, path) {
0 ignored issues
show
Unused Code introduced by
The parameter path is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1259
            assert.ifError(err);
1260
1261
            var pay = {};
1262
            pay[address] = blocktrail.toSatoshi(0.001);
1263
            pay[blocktrail.Wallet.OP_RETURN] = "BLOCKTRAILTESTDATA";
1264
1265
            wallet.pay(pay, function(err, txHash) {
1266
                assert.ifError(err);
1267
                assert.ok(txHash);
1268
1269
1270
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1271
                setTimeout(function() {
1272
                    client.transaction(txHash, function(err, tx) {
1273
                        assert.ifError(err);
1274
                        assert.ok(tx);
1275
1276
                        var hasOpreturn;
1277
                        tx.outputs.forEach(function(output) {
1278
                            if (output.type === 'op_return') {
1279
                                hasOpreturn = true;
1280
1281
                                assert.equal(output.script_hex, "6a12424c4f434b545241494c5445535444415441");
1282
                            }
1283
                        });
1284
                        assert.ok(hasOpreturn);
1285
1286
                        cb();
1287
                    });
1288
                }, WAIT_FOR_TX_PROCESSED);
1289
            });
1290
        });
1291
    });
1292
});
1293
1294
describe('test wallet, do forcefee transaction', function() {
1295
    var wallet;
1296
1297
    it("should exists", function(cb) {
1298
        client.initWallet({
1299
            identifier: "unittest-transaction",
1300
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1301
        }, function(err, _wallet) {
1302
            assert.ifError(err);
1303
            assert.ok(_wallet);
1304
1305
            wallet = _wallet;
1306
1307
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1308
            assert.equal(wallet.identifier, "unittest-transaction");
1309
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1310
            cb();
1311
        });
1312
    });
1313
1314
    it("should be able to do a payment with forced fee", function(cb) {
1315
        wallet.getNewAddress(function(err, address, path) {
0 ignored issues
show
Unused Code introduced by
The parameter path is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1316
            assert.ifError(err);
1317
1318
            var pay = {};
1319
            pay[address] = blocktrail.toSatoshi(0.01);
1320
            var forceFee = blocktrail.toSatoshi(0.00054321);
1321
1322
            wallet.pay(pay, null, false, true, blocktrail.Wallet.FEE_STRATEGY_FORCE_FEE, null, {
1323
                forcefee: forceFee,
1324
                checkFee: false
1325
            }, function(err, txHash) {
1326
                assert.ifError(err);
1327
                assert.ok(txHash);
1328
1329
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1330
                setTimeout(function() {
1331
                    client.transaction(txHash, function(err, tx) {
1332
                        assert.ifError(err);
1333
                        // this could very occasionally fail if change < DUST because then it's added to fee, so adjusted check for that
1334
                        assert.ok(tx['total_fee'] >= forceFee && tx['total_fee'] <= forceFee + blocktrail.DUST,
1335
                            "fee [" + tx['total_fee'] + "] should be equal to forced fee [" +  forceFee + "] for tx [" + txHash + "]");
1336
1337
                        cb();
1338
                    });
1339
                }, WAIT_FOR_TX_PROCESSED);
1340
            });
1341
        });
1342
    });
1343
});
1344
1345
describe('test wallet upgrade key index', function() {
1346
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1347
    var wallet;
1348
1349
    after(function(cb) {
1350
        if (wallet) {
1351
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1352
                cb();
1353
            });
1354
        } else {
1355
            cb();
1356
        }
1357
    });
1358
1359
    it("should be created", function(cb) {
1360
        createUpgradeKeyIndexTestWallet(myIdentifier, "password", function(err, _wallet) {
1361
            assert.ifError(err);
1362
            assert.ok(_wallet);
1363
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1364
            wallet = _wallet;
1365
1366
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1367
            assert.equal(wallet.identifier, myIdentifier);
1368
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1369
1370
            cb();
1371
        });
1372
    });
1373
1374
    it("should have the expected addresses", function(cb) {
1375
        async.series([
1376
            function(cb) {
1377
                wallet.getNewAddress(function(err, address, path) {
1378
                    assert.ifError(err);
1379
                    assert.equal(path, "M/9999'/0/0");
1380
                    assert.equal(address, "2Mtfn5S9tVWnnHsBQixCLTsCAPFHvfhu6bM");
1381
1382
                    cb();
1383
                });
1384
            },
1385
            function(cb) {
1386
                wallet.getNewAddress(function(err, address, path) {
1387
                    assert.ifError(err);
1388
                    assert.equal(path, "M/9999'/0/1");
1389
                    assert.equal(address, "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1390
1391
                    cb();
1392
                });
1393
            },
1394
            function(cb) {
1395
                assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1396
                assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2N1kM5xeDaCN9Weog3mbyxjpryNZcirnkB7");
1397
1398
                cb();
1399
            }
1400
        ], cb);
1401
    });
1402
1403
    it("should be upgraded and have expected addresses", function(cb) {
1404
        // set upgrade
1405
        wallet.upgradeToKeyIndex = 10000;
1406
        // lock
1407
        wallet.lock();
1408
        // unlock should upgrade
1409
        wallet.unlock({
1410
            passphrase: "password"
1411
        }).then(function() {
1412
            assert.equal(wallet.getBlocktrailPublicKey("M/10000'").toBase58(), "tpubD9m9hziKhYQExWgzMUNXdYMNUtourv96sjTUS9jJKdo3EDJAnCBJooMPm6vGSmkNTNAmVt988dzNfNY12YYzk9E6PkA7JbxYeZBFy4XAaCp");
1413
1414
            assert.equal(wallet.getAddressByPath("M/10000'/0/0"), "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1415
1416
            wallet.getNewAddress(function(err, address, path) {
1417
                assert.ifError(err);
1418
                assert.equal(path, "M/10000'/0/0");
1419
                assert.equal(address, "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1420
1421
                cb();
1422
            });
1423
        });
1424
    });
1425
});
1426
1427
describe('test wallet with bad password', function() {
1428
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1429
    var wallet;
1430
1431
    after(function(cb) {
1432
        if (wallet) {
1433
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1434
                cb();
1435
            });
1436
        } else {
1437
            cb();
1438
        }
1439
    });
1440
1441
    it("should be created", function(cb) {
1442
        createUpgradeKeyIndexTestWallet(myIdentifier, "badpassword", function(err, _wallet) {
1443
            assert.ifError(err);
1444
            assert.ok(_wallet);
1445
1446
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1447
            wallet = _wallet;
1448
1449
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1450
            assert.equal(wallet.identifier, myIdentifier);
1451
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1452
1453
            cb();
1454
        });
1455
    });
1456
1457
    it("should have the expected addresses (different from with the correct password)", function(cb) {
1458
        async.series([
1459
            function(cb) {
1460
                wallet.getNewAddress(function(err, address, path) {
1461
                    assert.ifError(err);
1462
                    assert.equal(path, "M/9999'/0/0");
1463
                    assert.equal(address, "2N9SGrV4NKRjdACYvHLPpy2oiPrxTPd44rg");
1464
1465
                    cb();
1466
                });
1467
            },
1468
            function(cb) {
1469
                wallet.getNewAddress(function(err, address, path) {
1470
                    assert.ifError(err);
1471
                    assert.equal(path, "M/9999'/0/1");
1472
                    assert.equal(address, "2NDq3DRy9E3YgHDA3haPJj3FtUS6V93avkf");
1473
1474
                    cb();
1475
                });
1476
            }
1477
        ], cb);
1478
    });
1479
});
1480
1481
describe('test wallet webhook', function() {
1482
    // this.timeout(0); // disable, can take long
1483
1484
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1485
    var wallet;
1486
1487
    after(function(cb) {
1488
        if (wallet) {
1489
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1490
                cb();
1491
            });
1492
        } else {
1493
            cb();
1494
        }
1495
    });
1496
1497
    it("shouldn't already exist", function(cb) {
1498
        client.initWallet({
1499
            identifier: myIdentifier,
1500
            passphrase: "password"
1501
        }, function(err, wallet) {
1502
            assert.ok(err);
1503
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
1504
1505
            cb();
1506
        });
1507
    });
1508
1509
    it("should be created", function(cb) {
1510
        client.createNewWallet({
1511
            identifier: myIdentifier,
1512
            passphrase: "password",
1513
            keyIndex: 9999
1514
        }, function(err, _wallet) {
1515
            assert.ifError(err);
1516
            assert.ok(_wallet);
1517
1518
            wallet = _wallet;
1519
1520
            assert.equal(wallet.identifier, myIdentifier);
1521
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1522
            cb();
1523
        });
1524
    });
1525
1526
    it("should have a 0 balance", function(cb) {
1527
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1528
            assert.ifError(err);
1529
            assert.equal(confirmed, 0);
1530
            assert.equal(unconfirmed, 0);
1531
1532
            cb();
1533
        });
1534
    });
1535
1536
    it("should be able to create a webhook", function(cb) {
1537
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", function(err, webhook) {
1538
            assert.ifError(err);
1539
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1540
            assert.equal(webhook['identifier'], "WALLET-" + myIdentifier);
1541
1542
            wallet.deleteWebhook(function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1543
                assert.ifError(err);
1544
1545
                cb();
1546
            });
1547
        });
1548
    });
1549
1550
    it("should be able to create a webhook with custom identifier", function(cb) {
1551
        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1552
1553
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1554
            assert.ifError(err);
1555
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1556
            assert.equal(webhook['identifier'], myWebhookIdentifier);
1557
1558
            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1559
                assert.ifError(err);
1560
1561
                wallet.getNewAddress(function(err, address1) {
1562
                    assert.ifError(err);
1563
1564
                    wallet.deleteWebhook(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1565
                        assert.ifError(err);
1566
1567
                        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1568
1569
                        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1570
                            assert.ifError(err);
1571
                            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1572
                            assert.equal(webhook['identifier'], myWebhookIdentifier);
1573
1574
                            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1575
                                assert.ifError(err);
1576
                                assert.ok(_.includes(_.map(result['data'], 'address'), address1));
1577
1578
                                wallet.getNewAddress(function(err, address2) {
1579
                                    assert.ifError(err);
1580
1581
                                    client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1582
                                        assert.ifError(err);
1583
                                        assert.ok(_.includes(_.map(result['data'], 'address'), address2));
1584
1585
                                        wallet.deleteWallet(function(err, result) {
1586
                                            assert.ifError(err);
1587
                                            assert.ok(result);
1588
1589
                                            client.deleteWebhook(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1590
                                                assert.ok(err);
1591
1592
                                                cb();
1593
                                            });
1594
                                        });
1595
                                    });
1596
                                });
1597
                            });
1598
                        });
1599
                    });
1600
1601
                });
1602
            });
1603
        });
1604
    });
1605
});
1606
1607
describe("Wallet.getAddressAndType", function() {
1608
    var fixtures = [
1609
        {
1610
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1611
            network: bitcoin.networks.testnet,
1612
            type: "bech32",
1613
            valid: true
1614
        },
1615
        {
1616
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1617
            network: bitcoin.networks.testnet,
1618
            type: "bech32",
1619
            valid: true
1620
        },
1621
        {
1622
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1623
            network: bitcoin.networks.testnet,
1624
            type: "base58",
1625
            valid: true
1626
        },
1627
        {
1628
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1629
            network: bitcoin.networks.testnet,
1630
            type: "base58",
1631
            valid: true
1632
        },
1633
        {
1634
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1635
            network: bitcoin.networks.bitcoin,
1636
            type: "base58",
1637
            valid: true
1638
        },
1639
        {
1640
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1641
            network: bitcoin.networks.bitcoin,
1642
            type: "base58",
1643
            valid: true
1644
        },
1645
        {
1646
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1647
            network: bitcoin.networks.bitcoin,
1648
            type: "bech32",
1649
            valid: true
1650
        },
1651
        {
1652
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1653
            network: bitcoin.networks.bitcoin,
1654
            type: "bech32",
1655
            valid: true
1656
        },
1657
        {
1658
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1659
            network: bitcoin.networks.testnet,
1660
            type: "base58",
1661
            error: "Address invalid on this network",
1662
            valid: false
1663
        },
1664
        {
1665
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1666
            network: bitcoin.networks.testnet,
1667
            type: "base58",
1668
            error: "Address invalid on this network",
1669
            valid: false
1670
        },
1671
        {
1672
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1673
            network: bitcoin.networks.testnet,
1674
            type: "bech32",
1675
            error: "Address invalid on this network",
1676
            valid: false
1677
        },
1678
        {
1679
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1680
            network: bitcoin.networks.testnet,
1681
            type: "bech32",
1682
            error: "Address invalid on this network",
1683
            valid: false
1684
        },
1685
        {
1686
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1687
            network: bitcoin.networks.bitcoincash,
1688
            error: "Non-base58 character",
1689
            type: "bech32",
1690
            valid: false
1691
        },
1692
        {
1693
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1694
            network: bitcoin.networks.bitcoincash,
1695
            error: "Non-base58 character",
1696
            type: "bech32",
1697
            valid: false
1698
        },
1699
        {
1700
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1701
            network: bitcoin.networks.bitcoincashtestnet,
1702
            error: "Non-base58 character",
1703
            type: "bech32",
1704
            valid: false
1705
        },
1706
        {
1707
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1708
            network: bitcoin.networks.bitcoincashtestnet,
1709
            error: "Non-base58 character",
1710
            type: "bech32",
1711
            valid: false
1712
        },
1713
        {
1714
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1715
            network: bitcoin.networks.bitcoin,
1716
            error: "Address invalid on this network",
1717
            type: "bech32",
1718
            valid: false
1719
        },
1720
        {
1721
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1722
            network: bitcoin.networks.bitcoin,
1723
            error: "Address invalid on this network",
1724
            type: "bech32",
1725
            valid: false
1726
        },
1727
        {
1728
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1729
            network: bitcoin.networks.testnet,
1730
            error: "Address invalid on this network",
1731
            type: "bech32",
1732
            valid: false
1733
        },
1734
        {
1735
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1736
            network: bitcoin.networks.testnet,
1737
            error: "Address invalid on this network",
1738
            type: "bech32",
1739
            valid: false
1740
        }
1741
    ];
1742
1743
    fixtures.map(function(fixture) {
1744
        var description =
1745
            (fixture.valid ? "parses" : "fails to parse") +
1746
            " a " + fixture.type + " address: " + fixture.address;
1747
1748
        it(description, function(cb) {
1749
            var addrAndType;
1750
            var err;
1751
            try {
1752
                addrAndType = Wallet.getAddressAndType(fixture.address, fixture.network);
1753
            } catch (e) {
1754
                err = e;
1755
            }
1756
1757
            if (fixture.valid) {
1758
                assert.ifError(err);
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths. Are you sure ifError handles undefined variables?
Loading history...
1759
                assert.ok(Object.keys(addrAndType).indexOf("address") !== -1);
1760
                assert.ok(Object.keys(addrAndType).indexOf("decoded") !== -1);
1761
                assert.ok(Object.keys(addrAndType).indexOf("type") !== -1);
1762
                assert.equal(addrAndType.type, fixture.type);
1763
                assert.equal(addrAndType.address, fixture.address);
1764
            } else {
1765
                assert.ok(typeof err === "object");
1766
                assert.ok(typeof addrAndType === "undefined");
1767
                if (Object.keys(fixture).indexOf("error") !== -1) {
1768
                    assert.equal(err.message, fixture.error);
1769
                }
1770
            }
1771
            cb();
1772
        });
1773
    });
1774
});
1775
1776
describe("Wallet.convertPayToOutputs", function() {
1777
    var fixtures = [
1778
        {
1779
            description: "p2wpkh",
1780
            network: bitcoin.networks.testnet,
1781
            cashaddr: false,
1782
            value: 12345,
1783
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1784
            script: "00149bce9399f9eeddad66635d4be171ec8f14decc59"
1785
        },
1786
        {
1787
            description: "p2wsh",
1788
            network: bitcoin.networks.testnet,
1789
            value: 12345,
1790
            cashaddr: false,
1791
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1792
            script: "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
1793
        },
1794
        {
1795
            description: "p2pkh",
1796
            network: bitcoin.networks.testnet,
1797
            value: 12345,
1798
            cashaddr: false,
1799
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1800
            script: "76a9149bce9399f9eeddad66635d4be171ec8f14decc5988ac"
1801
        },
1802
        {
1803
            description: "p2sh",
1804
            network: bitcoin.networks.testnet,
1805
            value: 12345,
1806
            cashaddr: false,
1807
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1808
            script: "a9149bce9399f9eeddad66635d4be171ec8f14decc5987"
1809
        },
1810
        {
1811
            description: "p2sh cashaddr",
1812
            network: bitcoin.networks.bitcoincash,
1813
            value: 12345,
1814
            cashaddr: true,
1815
            address: "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq",
1816
            script: "a91476a04053bda0a88bda5177b86a15c3b29f55987387"
1817
        }
1818
    ];
1819
1820
    fixtures.map(function(fixture) {
1821
        var network = fixture.network;
1822
        var payScriptOutputs = [{
1823
            scriptPubKey: fixture.script,
1824
            value: fixture.value
1825
        }];
1826
        var payAddressOutputs = [{
1827
            address: fixture.address,
1828
            value: fixture.value
1829
        }];
1830
        var payKeyedObject = {};
1831
        payKeyedObject[fixture.address] = fixture.value;
1832
        var payFlatArray = [
1833
            [fixture.address, fixture.value]
1834
        ];
1835
        [
1836
            {
1837
                desc: "deals with script outputs",
1838
                pay: payScriptOutputs
1839
            },
1840
            {
1841
                desc: "deals with address outputs",
1842
                pay: payAddressOutputs
1843
            },
1844
            {
1845
                desc: "deals with object keyed by address",
1846
                pay: payKeyedObject
1847
            },
1848
            {
1849
                desc: "deals with a flat output array",
1850
                pay: payFlatArray
1851
            }
1852
        ].map(function(f) {
1853
            it(fixture.description + " converted to script, " + f.desc, function(cb) {
1854
                var test = function(outputs) {
1855
                    assert.ok(Array.isArray(outputs));
1856
                    assert.equal(outputs[0].value, fixture.value);
1857
                    assert.equal(outputs[0].scriptPubKey, fixture.script);
1858
                    assert.equal(outputs[0].address, null);
1859
                };
1860
1861
                // should accept some input of ours
1862
                var outputs = Wallet.convertPayToOutputs(f.pay, network, fixture.cashaddr);
1863
                test(outputs);
1864
1865
                // repeating the procedure should pass the same test
1866
                var outputs2 = Wallet.convertPayToOutputs(outputs, network, fixture.cashaddr);
1867
                test(outputs2);
1868
1869
                outputs.map(function(output, i) {
1870
                    assert.equal(outputs[i].scriptPubKey, outputs2[i].scriptPubKey);
1871
                    assert.equal(outputs[i].value, outputs2[i].value);
1872
                });
1873
1874
                cb();
1875
            });
1876
        });
1877
    });
1878
});
1879
1880
describe('test wallet coin selection forms', function() {
1881
    var wallet;
1882
1883
    it("BTC testnet wallet should exist", function(cb) {
1884
        client.initWallet({
1885
            identifier: "unittest-transaction",
1886
            passphrase: "password"
1887
        }, function(err, _wallet) {
1888
            assert.ifError(err);
1889
            assert.ok(_wallet);
1890
1891
            wallet = _wallet;
1892
1893
            client.allWallets({page: 1}, function(err, wallets) {
1894
                assert.ifError(err);
1895
1896
                assert.ok(wallets['data'].length > 0);
1897
1898
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1899
                assert.equal(wallet.identifier, "unittest-transaction");
1900
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1901
1902
                cb();
1903
            });
1904
        });
1905
    });
1906
1907
    it("shouldnt coin select for wrong network", function(cb) {
1908
        var pay = {};
1909
        pay["bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42"] = 10000;
1910
        wallet.coinSelection(pay, function(err, res) {
0 ignored issues
show
Unused Code introduced by
The parameter res is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1911
            assert.ok(err);
1912
            cb();
1913
        });
1914
    });
1915
1916
    var fixtures = [
1917
        {"tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs": 10000},
1918
        {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7": 10000},
1919
        [
1920
            {
1921
                "address": "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1922
                "value": 10000
1923
            },
1924
            {
1925
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1926
                "value": 10000
1927
            }
1928
        ],
1929
        [
1930
            {
1931
                "scriptPubKey": "00149bce9399f9eeddad66635d4be171ec8f14decc59",
1932
                "value": 10000
1933
            },
1934
            {
1935
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1936
                "value": 10000
1937
            }
1938
        ]
1939
    ];
1940
1941
    fixtures.map(function(fixture) {
1942
        var type = "object";
1943
        if (Array.isArray(fixture)) {
1944
            type = "outputs array";
1945
        }
1946
        it("should coin select for " + type, function(cb) {
1947
            wallet.coinSelection(fixture, false, function(err, res) {
0 ignored issues
show
Unused Code introduced by
The parameter res is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1948
                assert.ifError(err);
1949
                cb();
1950
            });
1951
        });
1952
    });
1953
});
1954
1955
describe('test wallet list transactions and addresses', function() {
1956
    var wallet;
1957
1958
    it("should exists", function(cb) {
1959
        client.initWallet({
1960
            identifier: "unittest-transaction",
1961
            passphrase: "password"
1962
        }, function(err, _wallet) {
1963
            assert.ifError(err);
1964
            assert.ok(_wallet);
1965
1966
            wallet = _wallet;
1967
1968
            client.allWallets({page: 1}, function(err, wallets) {
1969
                assert.ifError(err);
1970
1971
                assert.ok(wallets['data'].length > 0);
1972
1973
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1974
                assert.equal(wallet.identifier, "unittest-transaction");
1975
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1976
1977
                cb();
1978
            });
1979
        });
1980
    });
1981
1982
    it("should list expected transactions", function(cb) {
1983
        wallet.transactions({page: 1, limit: 23}, function(err, transactions) {
1984
            assert.ifError(err);
1985
            assert.ok(transactions['data']);
1986
            assert.ok(transactions['total']);
1987
            assert.ok(transactions['data'].length === 23);
1988
            assert.ok(transactions['data'][0]['hash'], "2cb21783635a5f22e9934b8c3262146b42d251dfb14ee961d120936a6c40fe89");
1989
1990
            cb();
1991
        });
1992
    });
1993
1994
    it("should list expected addresses", function(cb) {
1995
        wallet.addresses({page: 1, limit: 23}, function(err, addresses) {
1996
            assert.ifError(err);
1997
            assert.ok(addresses['data']);
1998
            assert.ok(addresses['total']);
1999
            assert.ok(addresses['data'].length === 23);
2000
            assert.ok(addresses['data'][0]['address'], "2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS");
2001
2002
            cb();
2003
        });
2004
    });
2005
2006
    it("should list UTXOs", function(cb) {
2007
        wallet.utxos({page: 0, limit: 23}, function(err, addresses) {
2008
            assert.ifError(err);
2009
            assert.ok(addresses['data']);
2010
            assert.ok(addresses['total']);
2011
            assert.ok(addresses['data'].length === 23);
2012
2013
            cb();
2014
        });
2015
    });
2016
});
2017
2018
describe("size estimation", function() {
2019
2020
    it("should estimate proper size for 1 input 1 output TX", function() {
2021
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2022
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
2023
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2024
2025
        assert.equal(347, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2026
    });
2027
2028
    it("should estimate proper size for 99 inputs 1 output TX", function() {
2029
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2030
        for (var i = 0; i < 99; i++) {
2031
            txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', i);
2032
        }
2033
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2034
2035
        assert.equal(29453, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2036
    });
2037
2038
    it("should estimate proper size for 1 input 99 outputs TX", function() {
2039
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2040
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
2041
        for (var i = 0; i < 99; i++) {
2042
            txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2043
        }
2044
2045
        assert.equal(3679, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2046
    });
2047
});
2048
2049
describe("APIClient", function() {
2050
    it("resolvePrimaryPrivateKeyFromOptions", function(cb) {
2051
        client.resolvePrimaryPrivateKeyFromOptions({
2052
            passphrase: "password",
2053
            primaryMnemonic: "give pause forget seed dance crawl situate hole keen"
2054
        }, function(err, options) {
2055
            assert.ifError(err);
2056
            assert.ok(options.primaryPrivateKey);
2057
            assert.ok(options.primaryPrivateKey instanceof bitcoin.HDNode);
2058
            assert.equal("tprv8ZgxMBicQKsPeR93md5eVTbLDgQ8kfV4CDNtrVXv5p29KXtx7VHKFQThGkFgC61sYeeeaVH1yFv4thcvxS9cYdFrYwTNmkGhkQEJycSzAhE", options.primaryPrivateKey.toBase58());
2059
2060
            cb();
2061
2062
        });
2063
    });
2064
});
2065
2066
describe("bitcoin cash address switching", function() {
2067
    describe("APIClient.getLegacyBitcoinCashAddress", function() {
2068
        describe("doesnt work with BTC", function() {
2069
            it("fails", function(cb) {
2070
                var tbtcNetwork = _createApiClient("BTC", true);
2071
                var err;
2072
                try {
2073
                    tbtcNetwork.getLegacyBitcoinCashAddress("1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu");
2074
                } catch (e) {
2075
                    err = e;
2076
                }
2077
2078
                assert.ok(err);
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths. Are you sure ok handles undefined variables?
Loading history...
2079
                assert.ok("Cash addresses only work on bitcoin cash" === err.message);
2080
                cb();
2081
            });
2082
        });
2083
2084
        function testLegacyFromCashAddress(network, testnet, legacy, cash) {
2085
            var bccNetwork = _createApiClient(network, testnet);
2086
2087
            it("returns base58 address if that was given", function(cb) {
2088
                assert.ok(legacy === bccNetwork.getLegacyBitcoinCashAddress(legacy));
2089
                cb();
2090
            });
2091
            it("returns legacy address for cashaddress", function(cb) {
2092
                assert.ok(legacy === bccNetwork.getLegacyBitcoinCashAddress(cash));
2093
                cb();
2094
            });
2095
        }
2096
2097
        describe ("works with BCC testnet (P2SH)", function() {
2098
            testLegacyFromCashAddress("BCC", true, "2N44ThNe8NXHyv4bsX8AoVCXquBRW94Ls7W", "bchtest:ppm2qsznhks23z7629mms6s4cwef74vcwvhanqgjxu");
2099
        });
2100
        describe ("works with BCC (P2SH)", function() {
2101
            testLegacyFromCashAddress("BCC", false, "3LDsS579y7sruadqu11beEJoTjdFiFCdX4", "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e");
2102
        });
2103
        describe ("works with BCC (P2PKH)", function() {
2104
            testLegacyFromCashAddress("BCC", false, "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu", "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a");
2105
        });
2106
    });
2107
2108
2109
    describe("APIClient.getCashAddressFromLegacyAddress", function() {
2110
        describe("doesnt work with BTC", function() {
2111
            it("fails", function(cb) {
2112
                var tbtcNetwork = _createApiClient("BTC", true);
2113
                var err;
2114
                try {
2115
                    tbtcNetwork.getCashAddressFromLegacyAddress("1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu");
2116
                } catch (e) {
2117
                    err = e;
2118
                }
2119
2120
                assert.ok(err);
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths. Are you sure ok handles undefined variables?
Loading history...
2121
                assert.ok("Cash addresses only work on bitcoin cash" === err.message);
2122
                cb();
2123
            });
2124
        });
2125
2126
        function testCashFromLegacyAddress(network, testnet, cash, legacy) {
2127
            var bccNetwork = _createApiClient(network, testnet);
2128
2129
            it("returns cash address if that was given", function(cb) {
2130
                assert.ok(cash === bccNetwork.getCashAddressFromLegacyAddress(cash));
2131
                cb();
2132
            });
2133
2134
            it("returns cash address for base58 address", function(cb) {
2135
                assert.ok(cash === bccNetwork.getCashAddressFromLegacyAddress(legacy));
2136
                cb();
2137
            });
2138
        }
2139
2140
        describe ("works with BCC testnet (P2SH)", function() {
2141
            testCashFromLegacyAddress("BCC", true, "bchtest:ppm2qsznhks23z7629mms6s4cwef74vcwvhanqgjxu", "2N44ThNe8NXHyv4bsX8AoVCXquBRW94Ls7W");
2142
        });
2143
2144
        describe ("works with BCC (P2SH)", function() {
2145
            testCashFromLegacyAddress("BCC", false, "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e", "3LDsS579y7sruadqu11beEJoTjdFiFCdX4");
2146
        });
2147
2148
        describe ("works with BCC (P2PKH)", function() {
2149
            testCashFromLegacyAddress("BCC", false, "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a", "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu");
2150
        });
2151
    });
2152
2153
    var wallet;
2154
2155
    describe("wallet send", function() {
2156
        /**
2157
         * @type APIClient
2158
         */
2159
        var tbccClient = _createApiClient("BCC", true);
2160
        var legacyAddress;
2161
        var cashAddress;
2162
        it("should exists", function(cb) {
2163
            tbccClient.initWallet({
2164
                identifier: "unittest-transaction",
2165
                passphrase: "password",
2166
                useCashAddress: true
2167
            }, function(err, _wallet) {
2168
                assert.ifError(err);
2169
                assert.ok(_wallet);
2170
2171
                wallet = _wallet;
2172
                cb();
2173
            });
2174
        });
2175
2176
        it("generates an address", function(cb) {
2177
            wallet.getNewAddress(function(err, result) {
2178
                assert.ifError(err);
2179
                legacyAddress = tbccClient.getLegacyBitcoinCashAddress(result);
2180
                cashAddress = result;
2181
                cb();
2182
            });
2183
        });
2184
2185
        it("sends to legacy address", function(cb) {
2186
            var pay = {};
2187
            pay[legacyAddress] = 100000;
2188
            wallet.pay(pay, null, false, false, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
2189
                assert.ifError(err);
2190
                cb();
2191
            });
2192
        });
2193
2194
        it("sends to casah address", function(cb) {
2195
            var pay = {};
2196
            pay[cashAddress] = 100000;
2197
            wallet.pay(pay, null, false, false, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
2198
                assert.ifError(err);
2199
                cb();
2200
            });
2201
        });
2202
    });
2203
});
2204