Completed
Pull Request — master (#91)
by thomas
01:09
created

scribe(ꞌtest wallet, bitcoin cash mirrorꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
nc 1
dl 0
loc 48
rs 9.125
nop 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B wallet.test.js ➔ ... ➔ ?!?.map 0 41 1
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 View Code Duplication
    });
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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 createDiscoveryTestWallet = 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: true,  addressType: "base32", description: "can opt into cash address"},
759
        {useCashAddress: false, addressType: "base58", description: "false uses base58 address"}
760
    ].map(function (fixture) {
761
        var useCashAddress = fixture.useCashAddress;
762
        var expectType = fixture.addressType;
763
        var description = fixture.description;
764
765
        var wallet;
766
767
        it(description, function (cb) {
768
            tbccClient.initWallet({
769
                identifier: "unittest-transaction",
770
                passphrase: TRANSACTION_TEST_WALLET_PASSWORD,
771
                useCashAddress: useCashAddress
772
            }, function (err, _wallet) {
773
                assert.ifError(err);
774
                assert.ok(_wallet);
775
                assert.ok(!_wallet.isSegwit());
776
                assert.equal(_wallet.chain, blocktrail.Wallet.CHAIN_BCC_DEFAULT);
777
                wallet = _wallet;
778
779
                assert.equal(useCashAddress, _wallet.useNewCashAddr);
780
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
781
                assert.equal(wallet.identifier, "unittest-transaction");
782
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
783
                cb();
784
            });
785
        });
786
787
        it("derives the right address (" + description + ")", function (cb) {
788
            wallet.getNewAddress(function (err, serverAddress, path) {
789
                assert.ifError(err);
790
                assert.ok(serverAddress);
791
                assert.ok(path);
792
793
                var decoded = wallet.decodeAddress(serverAddress);
794
                assert.ok(decoded);
795
                assert.equal(serverAddress, decoded.address);
796
                assert.equal(expectType, decoded.type);
797
                cb();
798
            });
799
        });
800
    });
801
});
802
803
describe('test wallet, do transaction', function() {
804
    var wallet;
805
806
    it("should exists", function(cb) {
807
        client.initWallet({
808
            identifier: "unittest-transaction",
809
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
810
        }, function(err, _wallet) {
811
            assert.ifError(err);
812
            assert.ok(_wallet);
813
            assert.ok(!_wallet.isSegwit());
814
            assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
815
            wallet = _wallet;
816
817
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
818
            assert.equal(wallet.identifier, "unittest-transaction");
819
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
820
            cb();
821
        });
822
    });
823
824
    it("should have the expected addresses", function(cb) {
825
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
826
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
827
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
828
829
        cb();
830
    });
831
832
    it("should have a balance", function(cb) {
833
        this.timeout(0);
834
835
        wallet.getBalance(function(err, confirmed, unconfirmed) {
836
            assert.ok(confirmed + unconfirmed > 0);
837
            assert.ok(confirmed > 0);
838
839
            cb();
840
        });
841
    });
842
843
    it("should return errors when expected", function(cb) {
844
        async.parallel([
845
            function(cb) {
846
                wallet.pay({"": blocktrail.toSatoshi(0.001)}, function(err) {
847
                    assert.ok(!!err);
848
                    assert.equal(err.message, "Invalid address [] (Invalid checksum)");
849
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
850
851
                    cb();
852
                });
853
            },
854
            function(cb) {
855
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA": blocktrail.toSatoshi(0.001)}, function(err) {
856
                    assert.ok(!!err);
857
                    assert.equal(err.message, "Invalid address [2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA] (Invalid checksum)");
858
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
859
860
                    cb();
861
                });
862
            },
863
            function(cb) {
864
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1}, function(err) {
865
                    assert.ok(!!err);
866
                    assert.equal(err.message, "Values should be more than dust (" + blocktrail.DUST + ")");
867
                    assert.ok(err instanceof blocktrail.WalletSendError);
868
869
                    cb();
870
                });
871
            },
872
            function(cb) {
873
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 0}, function(err) {
874
                    assert.ok(!!err);
875
                    assert.equal(err.message, "Values should be non zero");
876
                    assert.ok(err instanceof blocktrail.WalletSendError);
877
878
                    cb();
879
                });
880
            },
881
            function(cb) {
882
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1.1}, function(err) {
883
                    assert.ok(!!err);
884
                    assert.equal(err.message, "Values should be in Satoshis");
885
                    assert.ok(err instanceof blocktrail.WalletSendError);
886
887
                    cb();
888
                });
889
            }
890
        ], cb);
891
    });
892
893
    it("should be able to build a transaction paying a bech32 address", function(cb) {
894
        var address = "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs";
895
        var wp = "00149bce9399f9eeddad66635d4be171ec8f14decc59";
896
        var pay = {};
897
        pay[address] = blocktrail.toSatoshi(0.001);
898
899
        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...
900
            assert.ifError(err);
901
            assert.ok(tx);
902
            assert.ok(tx.toHex());
903
            assert.equal(wp, tx.outs[0].script.toString('hex'));
904
            cb();
905
        });
906
    });
907
908
    it("change should be randomized when building a transaction", function(cb) {
909
        wallet.getNewAddress(function(err, address, path) {
910
            assert.ifError(err);
911
            assert.ok(path.indexOf("M/9999'/0/") === 0);
912
            assert.ok(bitcoin.address.fromBase58Check(address));
913
914
            var pay = {};
915
            pay[address] = blocktrail.toSatoshi(0.001);
916
917
            var changeIdxs = [];
918
            var tryX = 10;
919
920
            async.whilst(
921
                function() { return tryX-- > 0 && _.uniq(changeIdxs).length < 2; },
922
                function(cb) {
923
                    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...
924
                        assert.ifError(err);
925
926
                        tx.outs.forEach(function(output, idx) {
927
                            var addr = bitcoin.address.fromOutputScript(output.script, client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin);
928
929
                            if (addr !== address) {
930
                                changeIdxs.push(idx);
931
                            }
932
                        });
933
934
                        cb();
935
                    });
936
                },
937
                function() {
938
                    assert(_.uniq(changeIdxs).length > 1);
939
940
                    cb();
941
                }
942
            );
943
        });
944
945
        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...
946
            wallet.getNewAddress(function(err, address, path) {
947
                assert.ifError(err);
948
                assert.ok(path.indexOf("M/9999'/0/") === 0);
949
                assert.ok(bitcoin.address.fromBase58Check(address));
950
951
                var pay = {};
952
                pay[address] = blocktrail.toSatoshi(0.001);
953
954
                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...
955
                    assert.ifError(err);
956
                    assert.ok(tx);
957
                    assert.ok(tx.toHex());
958
                });
959
            });
960
        });
961
    });
962
963
    it("should be able to do a payment", function(cb) {
964
        wallet.getNewAddress(function(err, address, path) {
965
            assert.ifError(err);
966
            assert.ok(path.indexOf("M/9999'/", wallet.chain, "/") === 0);
967
            assert.ok(bitcoin.address.fromBase58Check(address));
968
969
            var pay = {};
970
            pay[address] = blocktrail.toSatoshi(0.001);
971
972
            var progress = [];
973
974
            wallet.pay(pay, function(err, txHash) {
975
                assert.ifError(err);
976
                assert.ok(txHash);
977
978
                // change address doesn't always happen ...
979
                if (progress.indexOf(blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS) === -1) {
980
                    progress.splice(2, 0, blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS);
981
                }
982
983
                assert.deepEqual(progress, [
984
                    blocktrail.Wallet.PAY_PROGRESS_START,
985
                    blocktrail.Wallet.PAY_PROGRESS_COIN_SELECTION,
986
                    blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS,
987
                    blocktrail.Wallet.PAY_PROGRESS_SIGN,
988
                    blocktrail.Wallet.PAY_PROGRESS_SEND,
989
                    blocktrail.Wallet.PAY_PROGRESS_DONE
990
                ]);
991
992
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
993
                setTimeout(function() {
994
                    client.transaction(txHash, function(err, tx) {
995
                        assert.ifError(err);
996
                        assert.ok(tx);
997
998
                        cb();
999
                    });
1000
                }, WAIT_FOR_TX_PROCESSED);
1001
            }).progress(function(_progress) {
1002
                progress.push(_progress);
1003
            });
1004
        });
1005
    });
1006
});
1007
1008
describe('test wallet with segwit chain', function() {
1009
    var wallet;
1010
1011
    it("should exist and be setup", function(cb) {
1012
        client.initWallet({
1013
            identifier: "unittest-transaction-sw",
1014
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1015
        }, function(err, _wallet) {
1016
            assert.ifError(err);
1017
            assert.ok(_wallet);
1018
            assert.equal(_wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1019
            assert.equal(_wallet.identifier, "unittest-transaction-sw");
1020
            assert.equal(_wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1021
            assert.ok(_wallet.isSegwit());
1022
            assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
1023
            assert.equal(blocktrail.Wallet.CHAIN_BTC_SEGWIT, _wallet.changeChain);
1024
1025
            wallet = _wallet;
1026
            cb();
1027
        });
1028
    });
1029
1030
    it("getNewAddress produces plain P2SH addresses", function(cb) {
1031
        wallet.getNewAddress(function(err, address, path) {
1032
            assert.ifError(err);
1033
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1034
1035
            assert.ok(bitcoin.address.fromBase58Check(address));
1036
1037
            cb();
1038
        });
1039
    });
1040
1041
    it("getNewAddress produces segwit P2SH addresses for change chain", function(cb) {
1042
        wallet.getNewAddress(wallet.changeChain, function(err, address, path) {
1043
            assert.ifError(err);
1044
            assert.ok(path.indexOf("M/9999'/2/") === 0);
1045
1046
            assert.ok(bitcoin.address.fromBase58Check(address));
1047
1048
            cb();
1049
        });
1050
    });
1051
1052
    it("getWalletScriptByPath produces P2SH addresses, and returns witnessScript", function(cb) {
1053
        var eAddress = "2N3j4Vx3D9LPumjtRbRe2RJpwVocvCCkHKh";
1054
1055
        assert.equal(wallet.getAddressByPath("M/9999'/2/0"), eAddress);
1056
1057
        var walletScript = wallet.getWalletScriptByPath("M/9999'/2/0");
1058
        assert.equal(walletScript.address, eAddress);
1059
        assert.ok(walletScript.witnessScript);
1060
        assert.ok(walletScript.redeemScript);
1061
        cb();
1062
    });
1063
});
1064
1065
describe('test wallet, do transaction, segwit spend', function() {
1066
    var wallets = [];
1067
    after(function(cb) {
1068
        if (wallets.length > 0) {
1069
            wallets.map(function(wallet) {
1070
                wallet.deleteWallet(true);
1071
            });
1072
        }
1073
        cb();
1074
    });
1075
1076
    var unitTestWallet;
1077
    var identifier = crypto.randomBytes(12).toString('hex');
1078
    var segwitWallet;
1079
    var receiveAddr;
1080
    var receiveBackAddr;
1081
    it("should setup the funding wallet", function(cb) {
1082
        client.initWallet({
1083
            identifier: "unittest-transaction",
1084
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1085
        }, function(err, _wallet) {
1086
            assert.ifError(err);
1087
            assert.ok(_wallet);
1088
1089
            _wallet.getNewAddress(function(err, address, path) {
1090
                assert.ifError(err);
1091
                assert.ok(address);
1092
                assert.ok(path);
1093
1094
                unitTestWallet = _wallet;
1095
                receiveBackAddr = address;
1096
                cb();
1097
            });
1098
        });
1099
    });
1100
1101
    it("should make the receiving segwit wallet", function(cb) {
1102
        createTransactionTestWallet(identifier, true, function(err, newWallet) {
1103
            wallets.push(newWallet);
1104
            assert.ifError(err);
1105
            newWallet.getNewAddress(newWallet.changeChain, function(err, address, path) {
1106
                assert.ifError(err);
1107
                assert.ok(bitcoin.address.fromBase58Check(address));
1108
                assert.ok(newWallet.isSegwit());
1109
                assert.ok(path.indexOf("M/9999'/2/") === 0);
1110
1111
                var checkScript = newWallet.getWalletScriptByPath(path);
1112
                assert.ok(checkScript.address = address);
1113
                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...
1114
                assert.ok(checkScript.witnessScript instanceof Buffer);
1115
1116
                segwitWallet = newWallet;
1117
                receiveAddr = address;
1118
                cb();
1119
            });
1120
        });
1121
    });
1122
1123
    var paymentHash;
1124
    it("should receive funds from unitTestWallet", function(cb) {
1125
        var pay = {};
1126
        pay[receiveAddr] = 30000;
1127
        unitTestWallet.pay(pay, null, true, function(err, txid) {
1128
            assert.ifError(err);
1129
            assert.ok(txid);
1130
            paymentHash = txid;
0 ignored issues
show
Unused Code introduced by
The variable paymentHash seems to be never used. Consider removing it.
Loading history...
1131
            cb();
1132
        });
1133
    });
1134
1135
    it("should return to unitTestWallet", function(cb) {
1136
        var pay = {};
1137
        pay[receiveBackAddr] = 20000;
1138
        segwitWallet.pay(pay, null, true, function(err, txid) {
1139
            assert.ifError(err);
1140
            assert.ok(txid);
1141
1142
            setTimeout(function() {
1143
                client.transaction(txid, function(err, tx) {
1144
                    assert.ifError(err);
1145
                    assert.ok(tx);
1146
                    cb();
1147
                });
1148
            }, WAIT_FOR_TX_PROCESSED);
1149
        });
1150
    });
1151
});
1152
describe('test wallet, do transaction, without mnemonics', function() {
1153
    var wallet;
1154
1155
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
1156
1157
    it("should exists", function(cb) {
1158
        client.initWallet({
1159
                identifier: "unittest-transaction",
1160
                primarySeed: primarySeed,
1161
                primaryMnemonic: false // explicitly set false because we're reusing unittest-transaction which has a mnemonic stored
1162
            }, function(err, _wallet) {
1163
                assert.ifError(err);
1164
                assert.ok(_wallet);
1165
1166
                wallet = _wallet;
1167
1168
                assert.equal(wallet.identifier, "unittest-transaction");
1169
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1170
                cb();
1171
            }
1172
        );
1173
    });
1174
1175
    it("should have the expected addresses", function(cb) {
1176
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
1177
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
1178
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
1179
1180
        cb();
1181
    });
1182
1183
    it("should have a balance", function(cb) {
1184
        this.timeout(0);
1185
1186
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1187
            assert.ok(confirmed + unconfirmed > 0);
1188
            assert.ok(confirmed > 0);
1189
1190
            cb();
1191
        });
1192
    });
1193
1194
    it("should be able to do a payment", function(cb) {
1195
        wallet.getNewAddress(function(err, address, path) {
1196
            assert.ifError(err);
1197
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1198
            assert.ok(bitcoin.address.fromBase58Check(address));
1199
1200
            var pay = {};
1201
            pay[address] = blocktrail.toSatoshi(0.001);
1202
1203
            wallet.pay(pay, function(err, txHash) {
1204
                assert.ifError(err);
1205
                assert.ok(txHash);
1206
1207
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1208
                setTimeout(function() {
1209
                    client.transaction(txHash, function(err, tx) {
1210
                        assert.ifError(err);
1211
                        assert.ok(tx);
1212
1213
                        cb();
1214
                    });
1215
                }, WAIT_FOR_TX_PROCESSED);
1216
            });
1217
        });
1218
    });
1219
});
1220
1221
describe('test wallet, do opreturn transaction', function() {
1222
    var wallet;
1223
1224
    it("should exists", function(cb) {
1225
        client.initWallet({
1226
            identifier: "unittest-transaction",
1227
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1228
        }, function(err, _wallet) {
1229
            assert.ifError(err);
1230
            assert.ok(_wallet);
1231
1232
            wallet = _wallet;
1233
1234
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1235
            assert.equal(wallet.identifier, "unittest-transaction");
1236
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1237
            cb();
1238
        });
1239
    });
1240
1241
    it("should be able to do a payment with opreturn output", function(cb) {
1242
        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...
1243
            assert.ifError(err);
1244
1245
            var pay = {};
1246
            pay[address] = blocktrail.toSatoshi(0.001);
1247
            pay[blocktrail.Wallet.OP_RETURN] = "BLOCKTRAILTESTDATA";
1248
1249
            wallet.pay(pay, function(err, txHash) {
1250
                assert.ifError(err);
1251
                assert.ok(txHash);
1252
1253
1254
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1255
                setTimeout(function() {
1256
                    client.transaction(txHash, function(err, tx) {
1257
                        assert.ifError(err);
1258
                        assert.ok(tx);
1259
1260
                        var hasOpreturn;
1261
                        tx.outputs.forEach(function(output) {
1262
                            if (output.type === 'op_return') {
1263
                                hasOpreturn = true;
1264
1265
                                assert.equal(output.script_hex, "6a12424c4f434b545241494c5445535444415441");
1266
                            }
1267
                        });
1268
                        assert.ok(hasOpreturn);
1269
1270
                        cb();
1271
                    });
1272
                }, WAIT_FOR_TX_PROCESSED);
1273
            });
1274
        });
1275
    });
1276
});
1277
1278
describe('test wallet, do forcefee transaction', function() {
1279
    var wallet;
1280
1281
    it("should exists", function(cb) {
1282
        client.initWallet({
1283
            identifier: "unittest-transaction",
1284
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1285
        }, function(err, _wallet) {
1286
            assert.ifError(err);
1287
            assert.ok(_wallet);
1288
1289
            wallet = _wallet;
1290
1291
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1292
            assert.equal(wallet.identifier, "unittest-transaction");
1293
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1294
            cb();
1295
        });
1296
    });
1297
1298
    it("should be able to do a payment with forced fee", function(cb) {
1299
        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...
1300
            assert.ifError(err);
1301
1302
            var pay = {};
1303
            pay[address] = blocktrail.toSatoshi(0.01);
1304
            var forceFee = blocktrail.toSatoshi(0.00054321);
1305
1306
            wallet.pay(pay, null, false, true, blocktrail.Wallet.FEE_STRATEGY_FORCE_FEE, null, {
1307
                forcefee: forceFee,
1308
                checkFee: false
1309
            }, function(err, txHash) {
1310
                assert.ifError(err);
1311
                assert.ok(txHash);
1312
1313
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1314
                setTimeout(function() {
1315
                    client.transaction(txHash, function(err, tx) {
1316
                        assert.ifError(err);
1317
                        // this could very occasionally fail if change < DUST because then it's added to fee, so adjusted check for that
1318
                        assert.ok(tx['total_fee'] >= forceFee && tx['total_fee'] <= forceFee + blocktrail.DUST,
1319
                            "fee [" + tx['total_fee'] + "] should be equal to forced fee [" +  forceFee + "] for tx [" + txHash + "]");
1320
1321
                        cb();
1322
                    });
1323
                }, WAIT_FOR_TX_PROCESSED);
1324
            });
1325
        });
1326
    });
1327
});
1328
1329
describe('test wallet discovery and upgrade key index', function() {
1330
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1331
    var wallet;
1332
1333
    after(function(cb) {
1334
        if (wallet) {
1335
            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...
1336
                cb();
1337
            });
1338
        } else {
1339
            cb();
1340
        }
1341
    });
1342
1343
    it("should be created", function(cb) {
1344
        createDiscoveryTestWallet(myIdentifier, "password", function(err, _wallet) {
1345
            assert.ifError(err);
1346
            assert.ok(_wallet);
1347
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1348
            wallet = _wallet;
1349
1350
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1351
            assert.equal(wallet.identifier, myIdentifier);
1352
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1353
1354
            cb();
1355
        });
1356
    });
1357
1358
    it("should have the expected addresses", function(cb) {
1359
        async.series([
1360
            function(cb) {
1361
                wallet.getNewAddress(function(err, address, path) {
1362
                    assert.ifError(err);
1363
                    assert.equal(path, "M/9999'/0/0");
1364
                    assert.equal(address, "2Mtfn5S9tVWnnHsBQixCLTsCAPFHvfhu6bM");
1365
1366
                    cb();
1367
                });
1368
            },
1369
            function(cb) {
1370
                wallet.getNewAddress(function(err, address, path) {
1371
                    assert.ifError(err);
1372
                    assert.equal(path, "M/9999'/0/1");
1373
                    assert.equal(address, "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1374
1375
                    cb();
1376
                });
1377
            },
1378
            function(cb) {
1379
                assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1380
                assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2N1kM5xeDaCN9Weog3mbyxjpryNZcirnkB7");
1381
1382
                cb();
1383
            }
1384
        ], cb);
1385
    });
1386
1387
    it("should have a balance after discovery", function(cb) {
1388
        this.timeout(0);
1389
1390
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1391
            assert.ok(confirmed + unconfirmed > 0);
1392
1393
            cb();
1394
        });
1395
    });
1396
1397
    it("should be upgraded and have expected addresses", function(cb) {
1398
        // set upgrade
1399
        wallet.upgradeToKeyIndex = 10000;
1400
        // lock
1401
        wallet.lock();
1402
        // unlock should upgrade
1403
        wallet.unlock({
1404
            passphrase: "password"
1405
        }).then(function() {
1406
            assert.equal(wallet.getBlocktrailPublicKey("M/10000'").toBase58(), "tpubD9m9hziKhYQExWgzMUNXdYMNUtourv96sjTUS9jJKdo3EDJAnCBJooMPm6vGSmkNTNAmVt988dzNfNY12YYzk9E6PkA7JbxYeZBFy4XAaCp");
1407
1408
            assert.equal(wallet.getAddressByPath("M/10000'/0/0"), "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1409
1410
            wallet.getNewAddress(function(err, address, path) {
1411
                assert.ifError(err);
1412
                assert.equal(path, "M/10000'/0/0");
1413
                assert.equal(address, "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1414
1415
                cb();
1416
            });
1417
        });
1418
    });
1419
});
1420
1421
describe('test wallet with bad password', function() {
1422
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1423
    var wallet;
1424
1425
    after(function(cb) {
1426
        if (wallet) {
1427
            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...
1428
                cb();
1429
            });
1430
        } else {
1431
            cb();
1432
        }
1433
    });
1434
1435
    it("should be created", function(cb) {
1436
        createDiscoveryTestWallet(myIdentifier, "badpassword", function(err, _wallet) {
1437
            assert.ifError(err);
1438
            assert.ok(_wallet);
1439
1440
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1441
            wallet = _wallet;
1442
1443
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1444
            assert.equal(wallet.identifier, myIdentifier);
1445
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1446
1447
            cb();
1448
        });
1449
    });
1450
1451
    it("should have the expected addresses (different from with the correct password)", function(cb) {
1452
        async.series([
1453
            function(cb) {
1454
                wallet.getNewAddress(function(err, address, path) {
1455
                    assert.ifError(err);
1456
                    assert.equal(path, "M/9999'/0/0");
1457
                    assert.equal(address, "2N9SGrV4NKRjdACYvHLPpy2oiPrxTPd44rg");
1458
1459
                    cb();
1460
                });
1461
            },
1462
            function(cb) {
1463
                wallet.getNewAddress(function(err, address, path) {
1464
                    assert.ifError(err);
1465
                    assert.equal(path, "M/9999'/0/1");
1466
                    assert.equal(address, "2NDq3DRy9E3YgHDA3haPJj3FtUS6V93avkf");
1467
1468
                    cb();
1469
                });
1470
            }
1471
        ], cb);
1472
    });
1473
1474
    it("shouldn't have a balance after discovery", function(cb) {
1475
        this.timeout(0);
1476
1477
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1478
            assert.ok(confirmed + unconfirmed === 0);
1479
1480
            cb();
1481
        });
1482
    });
1483
});
1484
1485
describe('test wallet webhook', function() {
1486
    // this.timeout(0); // disable, can take long
1487
1488
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1489
    var wallet;
1490
1491
    after(function(cb) {
1492
        if (wallet) {
1493
            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...
1494
                cb();
1495
            });
1496
        } else {
1497
            cb();
1498
        }
1499
    });
1500
1501
    it("shouldn't already exist", function(cb) {
1502
        client.initWallet({
1503
            identifier: myIdentifier,
1504
            passphrase: "password"
1505
        }, function(err, wallet) {
1506
            assert.ok(err);
1507
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
1508
1509
            cb();
1510
        });
1511
    });
1512
1513
    it("should be created", function(cb) {
1514
        client.createNewWallet({
1515
            identifier: myIdentifier,
1516
            passphrase: "password",
1517
            keyIndex: 9999
1518
        }, function(err, _wallet) {
1519
            assert.ifError(err);
1520
            assert.ok(_wallet);
1521
1522
            wallet = _wallet;
1523
1524
            assert.equal(wallet.identifier, myIdentifier);
1525
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1526
            cb();
1527
        });
1528
    });
1529
1530
    it("should have a 0 balance", function(cb) {
1531
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1532
            assert.ifError(err);
1533
            assert.equal(confirmed, 0);
1534
            assert.equal(unconfirmed, 0);
1535
1536
            cb();
1537
        });
1538
    });
1539
1540
    it("should be able to create a webhook", function(cb) {
1541
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", function(err, webhook) {
1542
            assert.ifError(err);
1543
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1544
            assert.equal(webhook['identifier'], "WALLET-" + myIdentifier);
1545
1546
            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...
1547
                assert.ifError(err);
1548
1549
                cb();
1550
            });
1551
        });
1552
    });
1553
1554
    it("should be able to create a webhook with custom identifier", function(cb) {
1555
        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1556
1557
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1558
            assert.ifError(err);
1559
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1560
            assert.equal(webhook['identifier'], myWebhookIdentifier);
1561
1562
            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...
1563
                assert.ifError(err);
1564
1565
                wallet.getNewAddress(function(err, address1) {
1566
                    assert.ifError(err);
1567
1568
                    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...
1569
                        assert.ifError(err);
1570
1571
                        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1572
1573
                        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1574
                            assert.ifError(err);
1575
                            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1576
                            assert.equal(webhook['identifier'], myWebhookIdentifier);
1577
1578
                            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1579
                                assert.ifError(err);
1580
                                assert.ok(_.includes(_.map(result['data'], 'address'), address1));
1581
1582
                                wallet.getNewAddress(function(err, address2) {
1583
                                    assert.ifError(err);
1584
1585
                                    client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1586
                                        assert.ifError(err);
1587
                                        assert.ok(_.includes(_.map(result['data'], 'address'), address2));
1588
1589
                                        wallet.deleteWallet(function(err, result) {
1590
                                            assert.ifError(err);
1591
                                            assert.ok(result);
1592
1593
                                            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...
1594
                                                assert.ok(err);
1595
1596
                                                cb();
1597
                                            });
1598
                                        });
1599
                                    });
1600
                                });
1601
                            });
1602
                        });
1603
                    });
1604
1605
                });
1606
            });
1607
        });
1608
    });
1609
});
1610
1611
describe("Wallet.getAddressAndType", function() {
1612
    var fixtures = [
1613
        {
1614
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1615
            network: bitcoin.networks.testnet,
1616
            type: "bech32",
1617
            valid: true
1618
        },
1619
        {
1620
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1621
            network: bitcoin.networks.testnet,
1622
            type: "bech32",
1623
            valid: true
1624
        },
1625
        {
1626
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1627
            network: bitcoin.networks.testnet,
1628
            type: "base58",
1629
            valid: true
1630
        },
1631
        {
1632
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1633
            network: bitcoin.networks.testnet,
1634
            type: "base58",
1635
            valid: true
1636
        },
1637
        {
1638
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1639
            network: bitcoin.networks.bitcoin,
1640
            type: "base58",
1641
            valid: true
1642
        },
1643
        {
1644
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1645
            network: bitcoin.networks.bitcoin,
1646
            type: "base58",
1647
            valid: true
1648
        },
1649
        {
1650
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1651
            network: bitcoin.networks.bitcoin,
1652
            type: "bech32",
1653
            valid: true
1654
        },
1655
        {
1656
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1657
            network: bitcoin.networks.bitcoin,
1658
            type: "bech32",
1659
            valid: true
1660
        },
1661
        {
1662
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1663
            network: bitcoin.networks.testnet,
1664
            type: "base58",
1665
            error: "Address invalid on this network",
1666
            valid: false
1667
        },
1668
        {
1669
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1670
            network: bitcoin.networks.testnet,
1671
            type: "base58",
1672
            error: "Address invalid on this network",
1673
            valid: false
1674
        },
1675
        {
1676
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1677
            network: bitcoin.networks.testnet,
1678
            type: "bech32",
1679
            error: "Address invalid on this network",
1680
            valid: false
1681
        },
1682
        {
1683
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1684
            network: bitcoin.networks.testnet,
1685
            type: "bech32",
1686
            error: "Address invalid on this network",
1687
            valid: false
1688
        },
1689
        {
1690
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1691
            network: bitcoin.networks.bitcoincash,
1692
            error: "Non-base58 character",
1693
            type: "bech32",
1694
            valid: false
1695
        },
1696
        {
1697
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1698
            network: bitcoin.networks.bitcoincash,
1699
            error: "Non-base58 character",
1700
            type: "bech32",
1701
            valid: false
1702
        },
1703
        {
1704
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1705
            network: bitcoin.networks.bitcoincashtestnet,
1706
            error: "Non-base58 character",
1707
            type: "bech32",
1708
            valid: false
1709
        },
1710
        {
1711
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1712
            network: bitcoin.networks.bitcoincashtestnet,
1713
            error: "Non-base58 character",
1714
            type: "bech32",
1715
            valid: false
1716
        },
1717
        {
1718
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1719
            network: bitcoin.networks.bitcoin,
1720
            error: "Address invalid on this network",
1721
            type: "bech32",
1722
            valid: false
1723
        },
1724
        {
1725
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1726
            network: bitcoin.networks.bitcoin,
1727
            error: "Address invalid on this network",
1728
            type: "bech32",
1729
            valid: false
1730
        },
1731
        {
1732
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1733
            network: bitcoin.networks.testnet,
1734
            error: "Address invalid on this network",
1735
            type: "bech32",
1736
            valid: false
1737
        },
1738
        {
1739
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1740
            network: bitcoin.networks.testnet,
1741
            error: "Address invalid on this network",
1742
            type: "bech32",
1743
            valid: false
1744
        }
1745
    ];
1746
1747
    fixtures.map(function(fixture) {
1748
        var description =
1749
            (fixture.valid ? "parses" : "fails to parse") +
1750
            " a " + fixture.type + " address: " + fixture.address;
1751
1752
        it(description, function(cb) {
1753
            var addrAndType;
1754
            var err;
1755
            try {
1756
                addrAndType = Wallet.getAddressAndType(fixture.address, fixture.network);
1757
            } catch (e) {
1758
                err = e;
1759
            }
1760
1761
            if (fixture.valid) {
1762
                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...
1763
                assert.ok(Object.keys(addrAndType).indexOf("address") !== -1);
1764
                assert.ok(Object.keys(addrAndType).indexOf("decoded") !== -1);
1765
                assert.ok(Object.keys(addrAndType).indexOf("type") !== -1);
1766
                assert.equal(addrAndType.type, fixture.type);
1767
                assert.equal(addrAndType.address, fixture.address);
1768
            } else {
1769
                assert.ok(typeof err === "object");
1770
                assert.ok(typeof addrAndType === "undefined");
1771
                if (Object.keys(fixture).indexOf("error") !== -1) {
1772
                    assert.equal(err.message, fixture.error);
1773
                }
1774
            }
1775
            cb();
1776
        });
1777
    });
1778
});
1779
1780
describe("Wallet.convertPayToOutputs", function() {
1781
    var fixtures = [
1782
        {
1783
            description: "p2wpkh",
1784
            network: bitcoin.networks.testnet,
1785
            cashaddr: false,
1786
            value: 12345,
1787
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1788
            script: "00149bce9399f9eeddad66635d4be171ec8f14decc59"
1789
        },
1790
        {
1791
            description: "p2wsh",
1792
            network: bitcoin.networks.testnet,
1793
            value: 12345,
1794
            cashaddr: false,
1795
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1796
            script: "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
1797
        },
1798
        {
1799
            description: "p2pkh",
1800
            network: bitcoin.networks.testnet,
1801
            value: 12345,
1802
            cashaddr: false,
1803
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1804
            script: "76a9149bce9399f9eeddad66635d4be171ec8f14decc5988ac"
1805
        },
1806
        {
1807
            description: "p2sh",
1808
            network: bitcoin.networks.testnet,
1809
            value: 12345,
1810
            cashaddr: false,
1811
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1812
            script: "a9149bce9399f9eeddad66635d4be171ec8f14decc5987"
1813
        },
1814
        {
1815
            description: "p2sh",
1816
            network: bitcoin.networks.bitcoincash,
1817
            value: 12345,
1818
            cashaddr: true,
1819
            address: "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq",
1820
            script: "a91476a04053bda0a88bda5177b86a15c3b29f55987387"
1821
        }
1822
    ];
1823
1824
    fixtures.map(function(fixture, i) {
1825
        var network = fixture.network;
1826
        it(fixture.description + " converted to script, " + i, function(cb) {
1827
            var test = function(outputs) {
1828
                assert.ok(Array.isArray(outputs));
1829
                assert.equal(outputs[0].value, fixture.value);
1830
                assert.equal(outputs[0].scriptPubKey, fixture.script);
1831
                assert.equal(outputs[0].address, null);
1832
            };
1833
1834
            // should accept some input of ours
1835
            var pay = [{
1836
                scriptPubKey: fixture.script,
1837
                value: fixture.value
1838
            }];
1839
1840
            var outputs = Wallet.convertPayToOutputs(pay, network, fixture.cashaddr);
1841
            test(outputs);
1842
1843
            pay = {};
1844
            pay[fixture.address] = fixture.value;
1845
1846
            // should deal with simple mapping form
1847
            outputs = Wallet.convertPayToOutputs(pay, network, fixture.cashaddr);
1848
            test(outputs);
1849
1850
            // repeating the procedure should pass the same test
1851
            outputs = Wallet.convertPayToOutputs(outputs, network, fixture.cashaddr);
1852
            test(outputs);
1853
1854
            cb();
1855
        });
1856
    });
1857
});
1858
1859
describe('test wallet coin selection forms', function() {
1860
    var wallet;
1861
1862
    it("BTC testnet wallet should exist", function(cb) {
1863
        client.initWallet({
1864
            identifier: "unittest-transaction",
1865
            passphrase: "password"
1866
        }, function(err, _wallet) {
1867
            assert.ifError(err);
1868
            assert.ok(_wallet);
1869
1870
            wallet = _wallet;
1871
1872
            client.allWallets({page: 1}, function(err, wallets) {
1873
                assert.ifError(err);
1874
1875
                assert.ok(wallets['data'].length > 0);
1876
1877
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1878
                assert.equal(wallet.identifier, "unittest-transaction");
1879
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1880
1881
                cb();
1882
            });
1883
        });
1884
    });
1885
1886
    it("shouldnt coin select for wrong network", function(cb) {
1887
        var pay = {};
1888
        pay["bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42"] = 10000;
1889
        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...
1890
            assert.ok(err);
1891
            cb();
1892
        });
1893
    });
1894
1895
    var fixtures = [
1896
        {"tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs": 10000},
1897
        {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7": 10000},
1898
        [
1899
            {
1900
                "address": "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1901
                "value": 10000
1902
            },
1903
            {
1904
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1905
                "value": 10000
1906
            }
1907
        ],
1908
        [
1909
            {
1910
                "scriptPubKey": "00149bce9399f9eeddad66635d4be171ec8f14decc59",
1911
                "value": 10000
1912
            },
1913
            {
1914
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1915
                "value": 10000
1916
            }
1917
        ]
1918
    ];
1919
1920
    fixtures.map(function(fixture) {
1921
        var type = "object";
1922
        if (Array.isArray(fixture)) {
1923
            type = "outputs array";
1924
        }
1925
        it("should coin select for " + type, function(cb) {
1926
            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...
1927
                assert.ifError(err);
1928
                cb();
1929
            });
1930
        });
1931
    });
1932
});
1933
1934
describe('test wallet list transactions and addresses', function() {
1935
    var wallet;
1936
1937
    it("should exists", function(cb) {
1938
        client.initWallet({
1939
            identifier: "unittest-transaction",
1940
            passphrase: "password"
1941
        }, function(err, _wallet) {
1942
            assert.ifError(err);
1943
            assert.ok(_wallet);
1944
1945
            wallet = _wallet;
1946
1947
            client.allWallets({page: 1}, function(err, wallets) {
1948
                assert.ifError(err);
1949
1950
                assert.ok(wallets['data'].length > 0);
1951
1952
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1953
                assert.equal(wallet.identifier, "unittest-transaction");
1954
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1955
1956
                cb();
1957
            });
1958
        });
1959
    });
1960
1961
    it("should list expected transactions", function(cb) {
1962
        wallet.transactions({page: 1, limit: 23}, function(err, transactions) {
1963
            assert.ifError(err);
1964
            assert.ok(transactions['data']);
1965
            assert.ok(transactions['total']);
1966
            assert.ok(transactions['data'].length === 23);
1967
            assert.ok(transactions['data'][0]['hash'], "2cb21783635a5f22e9934b8c3262146b42d251dfb14ee961d120936a6c40fe89");
1968
1969
            cb();
1970
        });
1971
    });
1972
1973
    it("should list expected addresses", function(cb) {
1974
        wallet.addresses({page: 1, limit: 23}, function(err, addresses) {
1975
            assert.ifError(err);
1976
            assert.ok(addresses['data']);
1977
            assert.ok(addresses['total']);
1978
            assert.ok(addresses['data'].length === 23);
1979
            assert.ok(addresses['data'][0]['address'], "2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS");
1980
1981
            cb();
1982
        });
1983
    });
1984
1985
    it("should list UTXOs", function(cb) {
1986
        wallet.utxos({page: 0, limit: 23}, function(err, addresses) {
1987
            assert.ifError(err);
1988
            assert.ok(addresses['data']);
1989
            assert.ok(addresses['total']);
1990
            assert.ok(addresses['data'].length === 23);
1991
1992
            cb();
1993
        });
1994
    });
1995
});
1996
1997
describe("size estimation", function() {
1998
1999
    it("should estimate proper size for 1 input 1 output TX", function() {
2000
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2001
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
2002
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2003
2004
        assert.equal(347, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2005
    });
2006
2007
    it("should estimate proper size for 99 inputs 1 output TX", function() {
2008
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2009
        for (var i = 0; i < 99; i++) {
2010
            txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', i);
2011
        }
2012
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2013
2014
        assert.equal(29453, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2015
    });
2016
2017
    it("should estimate proper size for 1 input 99 outputs TX", function() {
2018
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
2019
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
2020
        for (var i = 0; i < 99; i++) {
2021
            txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
2022
        }
2023
2024
        assert.equal(3679, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
2025
    });
2026
});
2027
2028
describe("APIClient", function() {
2029
    it("resolvePrimaryPrivateKeyFromOptions", function(cb) {
2030
        client.resolvePrimaryPrivateKeyFromOptions({
2031
            passphrase: "password",
2032
            primaryMnemonic: "give pause forget seed dance crawl situate hole keen"
2033
        }, function(err, options) {
2034
            assert.ifError(err);
2035
            assert.ok(options.primaryPrivateKey);
2036
            assert.ok(options.primaryPrivateKey instanceof bitcoin.HDNode);
2037
            assert.equal("tprv8ZgxMBicQKsPeR93md5eVTbLDgQ8kfV4CDNtrVXv5p29KXtx7VHKFQThGkFgC61sYeeeaVH1yFv4thcvxS9cYdFrYwTNmkGhkQEJycSzAhE", options.primaryPrivateKey.toBase58());
2038
2039
            cb();
2040
2041
        });
2042
    });
2043
});
2044