Completed
Push — master ( 243a5b...493c14 )
by thomas
02:49 queued 38s
created

scribe(ꞌInitialize with check_backup_keyꞌ)   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

3 Functions

Rating   Name   Duplication   Size   Complexity  
A wallet.test.js ➔ ... ➔ it(ꞌallows if the backup key matchesꞌ) 0 20 1
A wallet.test.js ➔ ... ➔ it(ꞌrejects invalid inputsꞌ) 0 13 2
A wallet.test.js ➔ ... ➔ it(ꞌchecks against the stringꞌ) 0 11 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
/**
13
 * @type APIClient
14
 */
15
var client = blocktrail.BlocktrailSDK({
16
    apiKey : process.env.BLOCKTRAIL_SDK_APIKEY || window.BLOCKTRAIL_SDK_APIKEY || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APIKEY",
17
    apiSecret : process.env.BLOCKTRAIL_SDK_APISECRET || window.BLOCKTRAIL_SDK_APISECRET || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APISECRET",
18
    testnet : true
19
});
20
21
var TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC = "give pause forget seed dance crawl situate hole keen",
22
    TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC = "give pause forget seed dance crawl situate hole give",
23
    TRANSACTION_TEST_WALLET_PASSWORD = "password";
24 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
25
var _createTestWallet = function(identifier, passphrase, primaryMnemonic, backupMnemonic, cb) {
26
    var keyIndex = 9999;
27
    var network = client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
28
29
    var primarySeed = bip39.mnemonicToSeed(primaryMnemonic, passphrase);
30
    var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, network);
31
32
    var backupSeed = bip39.mnemonicToSeed(backupMnemonic, "");
33
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(backupSeed, network);
34
    var backupPublicKey = backupPrivateKey.neutered();
35
36
    var checksum = primaryPrivateKey.getAddress();
37
    var primaryPublicKey = primaryPrivateKey.deriveHardened(keyIndex).neutered();
38
39
    client.storeNewWalletV1(
40
        identifier,
41
        [primaryPublicKey.toBase58(), "M/" + keyIndex + "'"],
42
        [backupPublicKey.toBase58(), "M"],
43
        primaryMnemonic,
44
        checksum,
45
        keyIndex,
46
        function(err, result) {
47
            if (err) {
48
                return cb(err);
49
            }
50
51
            var blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
52
                return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], network);
53
            });
54
55
            var wallet = new blocktrail.Wallet(
56
                client,
57
                identifier,
58
                blocktrail.Wallet.WALLET_VERSION_V1,
59
                primaryMnemonic,
60
                null,
61
                null,
62
                {keyIndex: primaryPublicKey},
63
                backupPublicKey,
64
                blocktrailPublicKeys,
65
                keyIndex,
66
                0,
67
                false,
68
                client.testnet,
69
                checksum
70
            );
71
72
            wallet.unlock({
73
                passphrase: passphrase
74
            }, function(err) {
75
                cb(err, wallet);
76
            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
77
        }
78
    );
79
};
80
81
var createDiscoveryTestWallet = function(identifier, passphrase, cb) {
82
    var primaryMnemonic = "give pause forget seed dance crawl situate hole kingdom";
83
    var backupMnemonic = "give pause forget seed dance crawl situate hole course";
84
85
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, cb);
86
};
87
88
var createTransactionTestWallet = function(identifier, cb) {
89
    return _createTestWallet(identifier, TRANSACTION_TEST_WALLET_PASSWORD, TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC, cb);
90
};
91
92
var createRecoveryTestWallet = function(identifier, passphrase, cb) {
93
    var primaryMnemonic = "give pause forget seed dance crawl situate hole join";
94
    var backupMnemonic = "give pause forget seed dance crawl situate hole crater";
95
96
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, cb);
97
};
98
99
describe('Initialize with check_backup_key', function() {
100
    it('rejects invalid inputs', function(cb) {
101
        try {
102
            client.initWallet({
103
                identifier: "unittest-transaction",
104
                password: "password",
105
                check_backup_key: []
106
            });
107
            assert(false);
108
        } catch (e) {
109
            assert.equal("Invalid input, must provide the backup key as a string (the xpub)", e.message);
110
        }
111
        cb();
112
    });
113
114
    it('checks against the string', function(cb) {
115
        client.initWallet({
116
            identifier: "unittest-transaction",
117
            password: "password",
118
            check_backup_key: 'for demonstration purposes only'
119
        }, 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...
120
            assert.ok(err);
121
            assert.equal("Backup key returned from server didn't match our own copy", err.message);
122
            cb();
123
        });
124
    });
125
126
    it('allows if the backup key matches', function(cb) {
127
        // You wouldn't keep your backup seed in your code,
128
        // dump it from the wallet upon generation
129
130
        var backupSeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC, "");
131
        var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(backupSeed, bitcoin.networks.testnet);
132
        var backupPublicKey = backupPrivateKey.neutered();
133
        var xpub = backupPublicKey.toBase58();
134
135
        // Would be saves as a string in code..
136
        client.initWallet({
137
            identifier: "unittest-transaction",
138
            password: "password",
139
            check_backup_key: xpub
140
        }, function(err, _wallet) {
141
            assert.ifError(err);
142
            assert.ok(_wallet);
143
            cb();
144
        });
145
    });
146
});
147
148
/**
149
 * Test operations on v2 and v3 wallets.
150
 * Also tests the default, encouraging to look at this test if it changes again.
151
 */
152
[
153
  blocktrail.Wallet.WALLET_VERSION_V2,
154
  blocktrail.Wallet.WALLET_VERSION_V3,
155
  null /* test our assumed default version */
156
].map(function(walletVersion) {
157
    var assumedDefault = blocktrail.Wallet.WALLET_VERSION_V3;
158
    describe('test new blank wallet, ' + walletVersion, function() {
159
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
160
        var wallet;
161
162
        after(function(cb) {
163
            if (wallet) {
164
                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...
165
                    cb();
166
                });
167
            } else {
168
                cb();
169
            }
170
        });
171
172
        it("shouldn't already exist", function(cb) {
173
            client.initWallet({
174
                identifier: myIdentifier,
175
                readOnly: true
176
            }, function(err, wallet) {
177
                assert.ok(err);
178
                assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
179
180
                cb();
181
            });
182
        });
183
184
        it("should be created", function(cb) {
185
            var progress = [];
186
            var cnf = {
187
                identifier: myIdentifier,
188
                passphrase: "password",
189
                keyIndex: 9999
190
            };
191
192
            var expectedVersion = assumedDefault;
193
            if (walletVersion !== null) {
194
                cnf.walletVersion = walletVersion;
195
                expectedVersion = walletVersion;
196
            }
197
198
            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...
199
                assert.ifError(err);
200
                assert.ok(_wallet);
201
202
                wallet = _wallet;
203
                assert.equal(wallet.walletVersion, expectedVersion);
204
                assert.equal(wallet.identifier, myIdentifier);
205
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
206
207
                assert.deepEqual(progress, [
208
                    blocktrail.CREATE_WALLET_PROGRESS_START,
209
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_SECRET,
210
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_PRIMARY,
211
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_RECOVERY,
212
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
213
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
214
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
215
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
216
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
217
                ]);
218
219
                cb();
220
            })
221
            .progress(function(p) { progress.push(p); });
222
        });
223
224
        it("should lock", function(cb) {
225
            assert(!wallet.locked);
226
            wallet.lock();
227
            assert(wallet.locked);
228
            cb();
229
        });
230
231
        it("should init", function(cb) {
232
            client.initWallet({
233
                identifier: myIdentifier,
234
                readOnly: true
235
            }, function(err, _wallet) {
236
                assert.ifError(err);
237
                assert.ok(_wallet);
238
239
                wallet = _wallet;
240
241
                cb();
242
            });
243
        });
244
245
        it("should have a 0 balance", function(cb) {
246
            wallet.getBalance(function(err, confirmed, unconfirmed) {
247
                assert.ifError(err);
248
                assert.equal(confirmed, 0);
249
                assert.equal(unconfirmed, 0);
250
251
                cb();
252
            });
253
        });
254
255
        it("shouldn't be able to pay when locked", function(cb) {
256
            wallet.pay({
257
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
258
            }, 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...
259
                assert.ok(!!err && err.message.match(/unlocked/));
260
                assert.ok(err instanceof blocktrail.WalletLockedError);
261
262
                cb();
263
            });
264
        });
265
266
        it("shouldn't be able to upgrade when locked", function(cb) {
267
            wallet.upgradeKeyIndex(10000, function(err) {
268
                assert.ok(!!err && err.message.match(/unlocked/));
269
                assert.ok(err instanceof blocktrail.WalletLockedError);
270
271
                cb();
272
            });
273
        });
274
275
        it("should unlock", function(cb) {
276
            wallet.unlock({password: "password"}, function(err) {
277
                assert.ifError(err);
278
279
                cb();
280
            });
281
        });
282
283
        it("should be able to unlock with secret", function(cb) {
284
            var secret = wallet.secret;
285
286
            wallet.lock();
287
            wallet.unlock({secret: secret}, function(err) {
288
                assert.ifError(err);
289
                cb();
290
            });
291
        });
292
293
        it("shouldn't be able to pay when unlocked (because of no balance)", function(cb) {
294
            wallet.pay({
295
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
296
            }, 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...
297
                assert.ok(!!err && err.message.match(/balance/));
298
299
                cb();
300
            });
301
        });
302
303
        it("should be able to upgrade when unlocked", function(cb) {
304
            wallet.upgradeKeyIndex(10000, function(err) {
305
                assert.ifError(err);
306
307
                cb();
308
            });
309
        });
310
311
        it("should be able to password change", function(cb) {
312
            wallet.passwordChange("password2", function(err) {
313
                assert.ifError(err);
314
315
                client.initWallet({
316
                    identifier: myIdentifier,
317
                    password: "password2"
318
                }, function(err, _wallet) {
319
                    assert.ifError(err);
320
                    assert.ok(_wallet);
321
322
                    wallet = _wallet;
323
324
                    cb();
325
                });
326
            });
327
        });
328
    });
329
});
330
331
/**
332
 * Test operations on v2 and v3 wallets.
333
 */
334
[
335
    blocktrail.Wallet.WALLET_VERSION_V1,
336
    blocktrail.Wallet.WALLET_VERSION_V2,
337
    blocktrail.Wallet.WALLET_VERSION_V3
338
].map(function(walletVersion) {
339
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
340
341
    describe('test input errors, ' + walletVersion, function() {
342
        it("shouldn't allow primaryPrivateKey in creation", function(cb) {
343
            var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
344
            var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet);
345
346
            client.createNewWallet({
347
                identifier: myIdentifier,
348
                passphrase: "password",
349
                primaryPrivateKey: primaryPrivateKey,
350
                walletVersion: walletVersion,
351
                keyIndex: 9999
352
            }, 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...
353
                assert.ok(!!err, "should error");
354
355
                cb();
356
            });
357
        });
358
359
        it("shouldn't allow unlocking with primaryPrivateKey", function(cb) {
360
            client.createNewWallet({
361
                identifier: "unittest-transaction-inputerr-" + walletVersion,
362
                primarySeed: primarySeed,
363
                walletVersion: walletVersion,
364
                keyIndex: 9999
365
            }).then(function(r) {
366
                var wallet = r[0];
367
                wallet.lock();
368
                return wallet;
369
            }, function(err) {
370
                assert.ok(err.message.match(/already exists/));
371
372
                return client.initWallet({
373
                    identifier: "unittest-transaction-inputerr-" + walletVersion,
374
                    readOnly: true
375
                });
376
            }).then(function(wallet) {
377
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
378
379
                return wallet.unlock({primaryPrivateKey: bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet)})
380
                    .then(function() {
381
                        return;
0 ignored issues
show
Unused Code introduced by
This return has no effect and can be removed.
Loading history...
382
                    }, function(err) {
383
                        return err;
384
                    });
385
            })
386
                .then(function(err) {
387
                    assert.ok(!!err, "should error");
388
                    cb();
389
                })
390
                .done();
391
        });
392
    });
393
});
394
395
/**
396
 * Test upgrade to V3 from V1 and V2
397
 */
398
[
399
    blocktrail.Wallet.WALLET_VERSION_V1,
400
    blocktrail.Wallet.WALLET_VERSION_V2
401
].map(function(walletVersion) {
402
    describe("upgrade to V3 from " + walletVersion, function() {
403
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
404
        var passphrase = "password";
405
        var wallet;
406
407
        after(function(cb) {
408
            if (wallet) {
409
                wallet.deleteWallet(true, function(err, result) {
410
                    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...
411
                    cb();
412
                });
413
            } else {
414
                cb();
415
            }
416
        });
417
418
        it("can upgrade", function() {
419
            var addr;
420
            return client.createNewWallet({
421
                identifier: myIdentifier,
422
                passphrase: passphrase,
423
                walletVersion: walletVersion,
424
                keyIndex: 9999
425
            })
426
                .then(function(r) {
427
                    return r[0];
428
                })
429
                .then(function(_wallet) {
430
                    wallet = _wallet;
431
                    addr = wallet.getAddressByPath("M/9999'/0/0");
432
433
                    return wallet;
434
                })
435
                .then(function(wallet) {
436
                    var progress = [];
437
438
                    return wallet.upgradeToV3(passphrase)
439
                        .progress(function(p) {
440
                            progress.push(p);
441
                        })
442
                        .then(function() {
443
                            assert(progress.length);
444
                            return wallet;
445
                        });
446
                })
447
                .then(function(wallet) {
448
                    assert.equal(addr, wallet.getAddressByPath("M/9999'/0/0"));
449
                });
450
        });
451
452
        it("can unlock with secret", function() {
453
            var secret = wallet.secret;
454
            wallet.lock();
455
            return wallet.unlock({secret: secret});
456
        });
457
458
        it("can init after upgrade", function() {
459
            return client.initWallet({
460
                identifier: myIdentifier,
461
                passphrase: passphrase,
462
                keyIndex: 9999
463
            });
464
        });
465
    });
466
});
467
468
describe('test new blank wallet, v1', function() {
469
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
470
    var wallet;
471
472
    after(function(cb) {
473
        if (wallet) {
474
            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...
475
                cb();
476
            });
477
        } else {
478
            cb();
479
        }
480
    });
481
482
    it("shouldn't already exist", function(cb) {
483
        client.initWallet({
484
            identifier: myIdentifier,
485
            readOnly: true
486
        }, function(err, wallet) {
487
            assert.ok(err);
488
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
489
490
            cb();
491
        });
492
    });
493
494
    it("should be created", function(cb) {
495
        var progress = [];
496
497
        client.createNewWallet({
498
                identifier: myIdentifier,
499
                passphrase: "password",
500
                keyIndex: 9999,
501
                walletVersion: blocktrail.Wallet.WALLET_VERSION_V1
502
            }, function(err, _wallet) {
503
                assert.ifError(err);
504
                assert.ok(_wallet);
505
506
                wallet = _wallet;
507
508
                assert.equal(wallet.identifier, myIdentifier);
509
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
510
511
                assert.deepEqual(progress, [
512
                    blocktrail.CREATE_WALLET_PROGRESS_START,
513
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
514
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
515
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
516
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
517
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
518
                ]);
519
520
                cb();
521
            }
522
        ).progress(function(p) { progress.push(p); });
523
    });
524
525
    it("should lock", function(cb) {
526
        assert(!wallet.locked);
527
        wallet.lock();
528
        assert(wallet.locked);
529
        cb();
530
    });
531
532
    it("should init", function(cb) {
533
        client.initWallet({
534
            identifier: myIdentifier,
535
            readOnly: true
536
        }, function(err, _wallet) {
537
            assert.ifError(err);
538
            assert.ok(_wallet);
539
            assert.equal(wallet.walletVersion, 'v1');
540
541
            wallet = _wallet;
542
543
            cb();
544
        });
545
    });
546
547
    it("should have a 0 balance", function(cb) {
548
        wallet.getBalance(function(err, confirmed, unconfirmed) {
549
            assert.ifError(err);
550
            assert.equal(confirmed, 0);
551
            assert.equal(unconfirmed, 0);
552
553
            cb();
554
        });
555
    });
556
557
    it("should unlock", function(cb) {
558
        wallet.unlock({password: "password"}, function(err) {
559
            assert.ifError(err);
560
561
            cb();
562
        });
563
    });
564
565
    it("shouldn't be able to password change", function(cb) {
566
        wallet.passwordChange("password2", function(err) {
567
            assert.ok(!!err && err.message.match(/version does not support/));
568
569
            cb();
570
        });
571
    });
572
});
573
574
describe('test new blank wallet, old syntax', function() {
575
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
576
    var wallet;
577
578
    after(function(cb) {
579
        if (wallet) {
580
            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...
581
                cb();
582
            });
583
        } else {
584
            cb();
585
        }
586
    });
587
588
    it("shouldn't already exist", function(cb) {
589
        client.initWallet(myIdentifier, "password", function(err, wallet) {
590
            assert.ok(err);
591
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
592
593
            cb();
594
        });
595
    });
596
597
    it("should be created", function(cb) {
598
        client.createNewWallet(myIdentifier, "password", 9999, function(err, _wallet) {
599
            assert.ifError(err);
600
            assert.ok(_wallet);
601
602
            wallet = _wallet;
603
604
            assert.equal(wallet.identifier, myIdentifier);
605
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
606
            cb();
607
        });
608
    });
609
610
    it("should have a 0 balance", function(cb) {
611
        wallet.getBalance(function(err, confirmed, unconfirmed) {
612
            assert.ifError(err);
613
            assert.equal(confirmed, 0);
614
            assert.equal(unconfirmed, 0);
615
616
            cb();
617
        });
618
    });
619
620
    it("shouldn't be able to pay", function(cb) {
621
        wallet.pay({
622
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
623
        }, 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...
624
            assert.ok(!!err);
625
626
            cb();
627
        });
628
    });
629
});
630
631
describe('test new wallet, without mnemonics', function() {
632
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
633
    var wallet;
634
635
    var primarySeed = bip39.mnemonicToSeed(bip39.generateMnemonic(512), "password");
636
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(bip39.generateMnemonic(512), ""), bitcoin.networks.testnet);
637
    var backupPublicKey = backupPrivateKey.neutered();
638
639
    after(function(cb) {
640
        if (wallet) {
641
            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...
642
                cb();
643
            });
644
        } else {
645
            cb();
646
        }
647
    });
648
649
    it("shouldn't already exist", function(cb) {
650
        client.initWallet({
651
            identifier: myIdentifier
652
        }, function(err, wallet) {
653
            assert.ok(err);
654
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
655
656
            cb();
657
        });
658
    });
659
660
    it("should be created", function(cb) {
661
        client.createNewWallet({
662
                identifier: myIdentifier,
663
                primarySeed: primarySeed,
664
                backupPublicKey: backupPublicKey,
665
                keyIndex: 9999
666
            }, function(err, _wallet) {
667
                assert.ifError(err);
668
                assert.ok(_wallet);
669
670
                wallet = _wallet;
671
672
                assert.equal(wallet.identifier, myIdentifier);
673
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
674
                cb();
675
            }
676
        );
677
    });
678
679
    it("should be initializable", function(cb) {
680
        client.initWallet({
681
                identifier: myIdentifier,
682
                primarySeed: primarySeed,
683
                keyIndex: 9999
684
            }, function(err, _wallet) {
685
                assert.ifError(err);
686
                assert.ok(_wallet);
687
688
                wallet = _wallet;
689
690
                cb();
691
            }
692
        );
693
    });
694
695
    it("should have a 0 balance", function(cb) {
696
        wallet.getBalance(function(err, confirmed, unconfirmed) {
697
            assert.ifError(err);
698
            assert.equal(confirmed, 0);
699
            assert.equal(unconfirmed, 0);
700
701
            cb();
702
        });
703
    });
704
705
    it("shouldn't be able to pay", function(cb) {
706
        wallet.pay({
707
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
708
        }, 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...
709
            assert.ok(!!err);
710
711
            cb();
712
        });
713
    });
714
});
715
716
describe('test wallet, do transaction', function() {
717
    var wallet;
718
719
    it("should exists", function(cb) {
720
        client.initWallet({
721
            identifier: "unittest-transaction",
722
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
723
        }, function(err, _wallet) {
724
            assert.ifError(err);
725
            assert.ok(_wallet);
726
            wallet = _wallet;
727
728
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
729
            assert.equal(wallet.identifier, "unittest-transaction");
730
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
731
            cb();
732
        });
733
    });
734
735
    it("should have the expected addresses", function(cb) {
736
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
737
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
738
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
739
740
        cb();
741
    });
742
743
    it("should have a balance", function(cb) {
744
        this.timeout(0);
745
746
        wallet.getBalance(function(err, confirmed, unconfirmed) {
747
            assert.ok(confirmed + unconfirmed > 0);
748
            assert.ok(confirmed > 0);
749
750
            cb();
751
        });
752
    });
753
754
    it("should return errors when expected", function(cb) {
755
        async.parallel([
756
            function(cb) {
757
                wallet.pay({"": blocktrail.toSatoshi(0.001)}, function(err) {
758
                    assert.ok(!!err);
759
                    assert.equal(err.message, "Invalid address [] (Invalid checksum)");
760
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
761
762
                    cb();
763
                });
764
            },
765
            function(cb) {
766
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA": blocktrail.toSatoshi(0.001)}, function(err) {
767
                    assert.ok(!!err);
768
                    assert.equal(err.message, "Invalid address [2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA] (Invalid checksum)");
769
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
770
771
                    cb();
772
                });
773
            },
774
            function(cb) {
775
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1}, function(err) {
776
                    assert.ok(!!err);
777
                    assert.equal(err.message, "Values should be more than dust (" + blocktrail.DUST + ")");
778
                    assert.ok(err instanceof blocktrail.WalletSendError);
779
780
                    cb();
781
                });
782
            },
783
            function(cb) {
784
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 0}, function(err) {
785
                    assert.ok(!!err);
786
                    assert.equal(err.message, "Values should be non zero");
787
                    assert.ok(err instanceof blocktrail.WalletSendError);
788
789
                    cb();
790
                });
791
            },
792
            function(cb) {
793
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1.1}, function(err) {
794
                    assert.ok(!!err);
795
                    assert.equal(err.message, "Values should be in Satoshis");
796
                    assert.ok(err instanceof blocktrail.WalletSendError);
797
798
                    cb();
799
                });
800
            }
801
        ], cb);
802
    });
803
804
    it("should be able to build a transaction paying a bech32 address", function(cb) {
805
        var address = "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs";
806
        var wp = "00149bce9399f9eeddad66635d4be171ec8f14decc59";
807
        var pay = {};
808
        pay[address] = blocktrail.toSatoshi(0.001);
809
810
        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...
811
            assert.ifError(err);
812
            assert.ok(tx);
813
            assert.ok(tx.toHex());
814
            assert.equal(wp, tx.outs[0].script.toString('hex'));
815
            cb();
816
        });
817
    });
818
819
    it("change should be randomized when building a transaction", function(cb) {
820
        wallet.getNewAddress(function(err, address, path) {
821
            assert.ifError(err);
822
            assert.ok(path.indexOf("M/9999'/0/") === 0);
823
            assert.ok(bitcoin.address.fromBase58Check(address));
824
825
            var pay = {};
826
            pay[address] = blocktrail.toSatoshi(0.001);
827
828
            var changeIdxs = [];
829
            var tryX = 10;
830
831
            async.whilst(
832
                function() { return tryX-- > 0 && _.uniq(changeIdxs).length < 2; },
833
                function(cb) {
834
                    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...
835
                        assert.ifError(err);
836
837
                        tx.outs.forEach(function(output, idx) {
838
                            var addr = bitcoin.address.fromOutputScript(output.script, client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin);
839
840
                            if (addr !== address) {
841
                                changeIdxs.push(idx);
842
                            }
843
                        });
844
845
                        cb();
846
                    });
847
                },
848
                function() {
849
                    assert(_.uniq(changeIdxs).length > 1);
850
851
                    cb();
852
                }
853
            );
854
        });
855
856
        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...
857
            wallet.getNewAddress(function(err, address, path) {
858
                assert.ifError(err);
859
                assert.ok(path.indexOf("M/9999'/0/") === 0);
860
                assert.ok(bitcoin.address.fromBase58Check(address));
861
862
                var pay = {};
863
                pay[address] = blocktrail.toSatoshi(0.001);
864
865
                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...
866
                    assert.ifError(err);
867
                    assert.ok(tx);
868
                    assert.ok(tx.toHex());
869
                });
870
            });
871
        });
872
    });
873
874
    it("should be able to do a payment", function(cb) {
875
        wallet.getNewAddress(function(err, address, path) {
876
            assert.ifError(err);
877
            assert.ok(path.indexOf("M/9999'/", wallet.chain, "/") === 0);
878
            assert.ok(bitcoin.address.fromBase58Check(address));
879
880
            var pay = {};
881
            pay[address] = blocktrail.toSatoshi(0.001);
882
883
            var progress = [];
884
885
            wallet.pay(pay, function(err, txHash) {
886
                assert.ifError(err);
887
                assert.ok(txHash);
888
889
                // change address doesn't always happen ...
890
                if (progress.indexOf(blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS) === -1) {
891
                    progress.splice(2, 0, blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS);
892
                }
893
894
                assert.deepEqual(progress, [
895
                    blocktrail.Wallet.PAY_PROGRESS_START,
896
                    blocktrail.Wallet.PAY_PROGRESS_COIN_SELECTION,
897
                    blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS,
898
                    blocktrail.Wallet.PAY_PROGRESS_SIGN,
899
                    blocktrail.Wallet.PAY_PROGRESS_SEND,
900
                    blocktrail.Wallet.PAY_PROGRESS_DONE
901
                ]);
902
903
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
904
                setTimeout(function() {
905
                    client.transaction(txHash, function(err, tx) {
906
                        assert.ifError(err);
907
                        assert.ok(tx);
908
909
                        cb();
910
                    });
911
                }, 200);
912
            }).progress(function(_progress) {
913
                progress.push(_progress);
914
            });
915
        });
916
    });
917
});
918
919
describe('test wallet with segwit chain', function() {
920
    var wallet;
921
922
    it("should exist and be setup", function(cb) {
923
        client.initWallet({
924
            identifier: "unittest-transaction",
925
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
926
        }, function(err, _wallet) {
927
            assert.ifError(err);
928
            assert.ok(_wallet);
929
            assert.equal(_wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
930
            assert.equal(_wallet.identifier, "unittest-transaction");
931
            assert.equal(_wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
932
933
            if (_wallet.isSegwit()) {
934
                assert.equal(blocktrail.Wallet.CHAIN_BTC_SEGWIT, _wallet.chain);
935
            } else {
936
                assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
937
            }
938
939
            wallet = _wallet;
940
            cb();
941
        });
942
    });
943
944
    it("getNewAddress produces P2SH addresses", function(cb) {
945
        wallet.getNewAddress(function(err, address, path) {
946
            assert.ifError(err);
947
            if (wallet.isSegwit()) {
948
                assert.ok(path.indexOf("M/9999'/2/") === 0);
949
            } else {
950
                assert.ok(path.indexOf("M/9999'/0/") === 0);
951
            }
952
953
            assert.ok(bitcoin.address.fromBase58Check(address));
954
955
            cb();
956
        });
957
    });
958
959
    it("getWalletScriptByPath produces P2SH addresses, and returns witnessScript", function(cb) {
960
        var eAddress = "2N3j4Vx3D9LPumjtRbRe2RJpwVocvCCkHKh";
961
962
        assert.equal(wallet.getAddressByPath("M/9999'/2/0"), eAddress);
963
964
        var walletScript = wallet.getWalletScriptByPath("M/9999'/2/0");
965
        assert.equal(walletScript.address, eAddress);
966
        assert.ok(walletScript.witnessScript);
967
        assert.ok(walletScript.redeemScript);
968
        cb();
969
    });
970
});
971
972
describe('test wallet, do transaction, segwit spend', function() {
973
    var wallets = [];
974
    after(function(cb) {
975
        if (wallets.length > 0) {
976
            wallets.map(function(wallet) {
977
                wallet.deleteWallet(true);
978
            });
979
        }
980
        cb();
981
    });
982
983
    var unitTestWallet;
984
    var identifier = crypto.randomBytes(12).toString('hex');
985
    var segwitWallet;
986
    var receiveAddr;
987
    var receiveBackAddr;
988
    it("should setup the funding wallet", function(cb) {
989
        client.initWallet({
990
            identifier: "unittest-transaction",
991
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
992
        }, function(err, _wallet) {
993
            assert.ifError(err);
994
            assert.ok(_wallet);
995
996
            _wallet.getNewAddress(function(err, address, path) {
997
                assert.ifError(err);
998
                assert.ok(address);
999
                assert.ok(path);
1000
1001
                unitTestWallet = _wallet;
1002
                receiveBackAddr = address;
1003
                cb();
1004
            });
1005
        });
1006
    });
1007
1008
    it("should make the receiving segwit wallet ", function(cb) {
1009
        createTransactionTestWallet(identifier, function(err, newWallet) {
1010
            wallets.push(newWallet);
1011
            assert.ifError(err);
1012
            newWallet.getNewAddress(function(err, address, path) {
1013
                assert.ifError(err);
1014
                assert.ok(bitcoin.address.fromBase58Check(address));
1015
1016
                if (newWallet.isSegwit()) {
1017
                    assert.ok(path.indexOf("M/9999'/2/") === 0);
1018
                } else {
1019
                    assert.ok(path.indexOf("M/9999'/0/") === 0);
1020
                }
1021
1022
                var checkScript = newWallet.getWalletScriptByPath(path);
1023
                assert.ok(checkScript.address = address);
1024
                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...
1025
                if (newWallet.isSegwit()) {
1026
                    assert.ok(checkScript.witnessScript instanceof Buffer);
1027
                }
1028
1029
                segwitWallet = newWallet;
1030
                receiveAddr = address;
1031
                cb();
1032
            });
1033
        });
1034
    });
1035
1036
    var paymentHash;
1037
    it("should receive funds from unitTestWallet", function(cb) {
1038
        var pay = {};
1039
        pay[receiveAddr] = 30000;
1040
        unitTestWallet.pay(pay, null, true, function(err, txid) {
1041
            assert.ifError(err);
1042
            assert.ok(txid);
1043
            paymentHash = txid;
0 ignored issues
show
Unused Code introduced by
The variable paymentHash seems to be never used. Consider removing it.
Loading history...
1044
            cb();
1045
        });
1046
    });
1047
1048
    it("should return to unitTestWallet", function(cb) {
1049
        var pay = {};
1050
        pay[receiveBackAddr] = 20000;
1051
        segwitWallet.pay(pay, null, true, function(err, txid) {
1052
            assert.ifError(err);
1053
            assert.ok(txid);
1054
1055
            client.transaction(txid, function(err, tx) {
1056
                assert.ifError(err);
1057
                assert.ok(tx);
1058
                cb();
1059
            });
1060
        });
1061
    });
1062
});
1063
describe('test wallet, do transaction, without mnemonics', function() {
1064
    var wallet;
1065
1066
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
1067
1068
    it("should exists", function(cb) {
1069
        client.initWallet({
1070
                identifier: "unittest-transaction",
1071
                primarySeed: primarySeed,
1072
                primaryMnemonic: false // explicitly set false because we're reusing unittest-transaction which has a mnemonic stored
1073
            }, function(err, _wallet) {
1074
                assert.ifError(err);
1075
                assert.ok(_wallet);
1076
1077
                wallet = _wallet;
1078
1079
                assert.equal(wallet.identifier, "unittest-transaction");
1080
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1081
                cb();
1082
            }
1083
        );
1084
    });
1085
1086
    it("should have the expected addresses", function(cb) {
1087
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
1088
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
1089
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
1090
1091
        cb();
1092
    });
1093
1094
    it("should have a balance", function(cb) {
1095
        this.timeout(0);
1096
1097
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1098
            assert.ok(confirmed + unconfirmed > 0);
1099
            assert.ok(confirmed > 0);
1100
1101
            cb();
1102
        });
1103
    });
1104
1105
    it("should be able to do a payment", function(cb) {
1106
        wallet.getNewAddress(function(err, address, path) {
1107
            assert.ifError(err);
1108
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1109
            assert.ok(bitcoin.address.fromBase58Check(address));
1110
1111
            var pay = {};
1112
            pay[address] = blocktrail.toSatoshi(0.001);
1113
1114
            wallet.pay(pay, function(err, txHash) {
1115
                assert.ifError(err);
1116
                assert.ok(txHash);
1117
1118
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1119
                setTimeout(function() {
1120
                    client.transaction(txHash, function(err, tx) {
1121
                        assert.ifError(err);
1122
                        assert.ok(tx);
1123
1124
                        cb();
1125
                    });
1126
                }, 200);
1127
            });
1128
        });
1129
    });
1130
});
1131
1132
describe('test wallet, do opreturn transaction', function() {
1133
    var wallet;
1134
1135
    it("should exists", function(cb) {
1136
        client.initWallet({
1137
            identifier: "unittest-transaction",
1138
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1139
        }, function(err, _wallet) {
1140
            assert.ifError(err);
1141
            assert.ok(_wallet);
1142
1143
            wallet = _wallet;
1144
1145
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1146
            assert.equal(wallet.identifier, "unittest-transaction");
1147
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1148
            cb();
1149
        });
1150
    });
1151
1152
    it("should be able to do a payment with opreturn output", function(cb) {
1153
        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...
1154
            assert.ifError(err);
1155
1156
            var pay = {};
1157
            pay[address] = blocktrail.toSatoshi(0.001);
1158
            pay[blocktrail.Wallet.OP_RETURN] = "BLOCKTRAILTESTDATA";
1159
1160
            wallet.pay(pay, function(err, txHash) {
1161
                assert.ifError(err);
1162
                assert.ok(txHash);
1163
1164
1165
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1166
                setTimeout(function() {
1167
                    client.transaction(txHash, function(err, tx) {
1168
                        assert.ifError(err);
1169
                        assert.ok(tx);
1170
1171
                        var hasOpreturn;
1172
                        tx.outputs.forEach(function(output) {
1173
                            if (output.type === 'op_return') {
1174
                                hasOpreturn = true;
1175
1176
                                assert.equal(output.script_hex, "6a12424c4f434b545241494c5445535444415441");
1177
                            }
1178
                        });
1179
                        assert.ok(hasOpreturn);
1180
1181
                        cb();
1182
                    });
1183
                }, 200);
1184
            });
1185
        });
1186
    });
1187
});
1188
1189
describe('test wallet, do forcefee transaction', function() {
1190
    var wallet;
1191
1192
    it("should exists", function(cb) {
1193
        client.initWallet({
1194
            identifier: "unittest-transaction",
1195
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1196
        }, function(err, _wallet) {
1197
            assert.ifError(err);
1198
            assert.ok(_wallet);
1199
1200
            wallet = _wallet;
1201
1202
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1203
            assert.equal(wallet.identifier, "unittest-transaction");
1204
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1205
            cb();
1206
        });
1207
    });
1208
1209
    it("should be able to do a payment with forced fee", function(cb) {
1210
        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...
1211
            assert.ifError(err);
1212
1213
            var pay = {};
1214
            pay[address] = blocktrail.toSatoshi(0.01);
1215
            var forceFee = blocktrail.toSatoshi(0.00054321);
1216
1217
            wallet.pay(pay, null, false, true, blocktrail.Wallet.FEE_STRATEGY_FORCE_FEE, null, {
1218
                forcefee: forceFee,
1219
                checkFee: false
1220
            }, function(err, txHash) {
1221
                assert.ifError(err);
1222
                assert.ok(txHash);
1223
1224
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1225
                setTimeout(function() {
1226
                    client.transaction(txHash, function(err, tx) {
1227
                        assert.ifError(err);
1228
                        // this could very occasionally fail if change < DUST because then it's added to fee, so adjusted check for that
1229
                        assert.ok(tx['total_fee'] >= forceFee && tx['total_fee'] <= forceFee + blocktrail.DUST,
1230
                            "fee [" + tx['total_fee'] + "] should be equal to forced fee [" +  forceFee + "] for tx [" + txHash + "]");
1231
1232
                        cb();
1233
                    });
1234
                }, 200);
1235
            });
1236
        });
1237
    });
1238
});
1239
1240
describe('test wallet discovery and upgrade key index', function() {
1241
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1242
    var wallet;
1243
1244
    after(function(cb) {
1245
        if (wallet) {
1246
            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...
1247
                cb();
1248
            });
1249
        } else {
1250
            cb();
1251
        }
1252
    });
1253
1254
    it("should be created", function(cb) {
1255
        createDiscoveryTestWallet(myIdentifier, "password", function(err, _wallet) {
1256
            assert.ifError(err);
1257
            assert.ok(_wallet);
1258
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1259
            wallet = _wallet;
1260
1261
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1262
            assert.equal(wallet.identifier, myIdentifier);
1263
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1264
1265
            cb();
1266
        });
1267
    });
1268
1269
    it("should have the expected addresses", function(cb) {
1270
        async.series([
1271
            function(cb) {
1272
                wallet.getNewAddress(function(err, address, path) {
1273
                    assert.ifError(err);
1274
                    assert.equal(path, "M/9999'/0/0");
1275
                    assert.equal(address, "2Mtfn5S9tVWnnHsBQixCLTsCAPFHvfhu6bM");
1276
1277
                    cb();
1278
                });
1279
            },
1280
            function(cb) {
1281
                wallet.getNewAddress(function(err, address, path) {
1282
                    assert.ifError(err);
1283
                    assert.equal(path, "M/9999'/0/1");
1284
                    assert.equal(address, "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1285
1286
                    cb();
1287
                });
1288
            },
1289
            function(cb) {
1290
                assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1291
                assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2N1kM5xeDaCN9Weog3mbyxjpryNZcirnkB7");
1292
1293
                cb();
1294
            }
1295
        ], cb);
1296
    });
1297
1298
    it("should have a balance after discovery", function(cb) {
1299
        this.timeout(0);
1300
1301
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1302
            assert.ok(confirmed + unconfirmed > 0);
1303
1304
            cb();
1305
        });
1306
    });
1307
1308
    it("should be upgraded and have expected addresses", function(cb) {
1309
        // set upgrade
1310
        wallet.upgradeToKeyIndex = 10000;
1311
        // lock
1312
        wallet.lock();
1313
        // unlock should upgrade
1314
        wallet.unlock({
1315
            passphrase: "password"
1316
        }).then(function() {
1317
            assert.equal(wallet.getBlocktrailPublicKey("M/10000'").toBase58(), "tpubD9m9hziKhYQExWgzMUNXdYMNUtourv96sjTUS9jJKdo3EDJAnCBJooMPm6vGSmkNTNAmVt988dzNfNY12YYzk9E6PkA7JbxYeZBFy4XAaCp");
1318
1319
            assert.equal(wallet.getAddressByPath("M/10000'/0/0"), "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1320
1321
            wallet.getNewAddress(function(err, address, path) {
1322
                assert.ifError(err);
1323
                assert.equal(path, "M/10000'/0/0");
1324
                assert.equal(address, "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1325
1326
                cb();
1327
            });
1328
        });
1329
    });
1330
});
1331
1332
describe('test wallet with bad password', function() {
1333
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1334
    var wallet;
1335
1336
    after(function(cb) {
1337
        if (wallet) {
1338
            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...
1339
                cb();
1340
            });
1341
        } else {
1342
            cb();
1343
        }
1344
    });
1345
1346
    it("should be created", function(cb) {
1347
        createDiscoveryTestWallet(myIdentifier, "badpassword", function(err, _wallet) {
1348
            assert.ifError(err);
1349
            assert.ok(_wallet);
1350
1351
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1352
            wallet = _wallet;
1353
1354
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1355
            assert.equal(wallet.identifier, myIdentifier);
1356
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1357
1358
            cb();
1359
        });
1360
    });
1361
1362
    it("should have the expected addresses (different from with the correct password)", function(cb) {
1363
        async.series([
1364
            function(cb) {
1365
                wallet.getNewAddress(function(err, address, path) {
1366
                    assert.ifError(err);
1367
                    assert.equal(path, "M/9999'/0/0");
1368
                    assert.equal(address, "2N9SGrV4NKRjdACYvHLPpy2oiPrxTPd44rg");
1369
1370
                    cb();
1371
                });
1372
            },
1373
            function(cb) {
1374
                wallet.getNewAddress(function(err, address, path) {
1375
                    assert.ifError(err);
1376
                    assert.equal(path, "M/9999'/0/1");
1377
                    assert.equal(address, "2NDq3DRy9E3YgHDA3haPJj3FtUS6V93avkf");
1378
1379
                    cb();
1380
                });
1381
            }
1382
        ], cb);
1383
    });
1384
1385
    it("shouldn't have a balance after discovery", function(cb) {
1386
        this.timeout(0);
1387
1388
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1389
            assert.ok(confirmed + unconfirmed === 0);
1390
1391
            cb();
1392
        });
1393
    });
1394
});
1395
1396
describe('test wallet webhook', function() {
1397
    // this.timeout(0); // disable, can take long
1398
1399
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1400
    var wallet;
1401
1402
    after(function(cb) {
1403
        if (wallet) {
1404
            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...
1405
                cb();
1406
            });
1407
        } else {
1408
            cb();
1409
        }
1410
    });
1411
1412
    it("shouldn't already exist", function(cb) {
1413
        client.initWallet({
1414
            identifier: myIdentifier,
1415
            passphrase: "password"
1416
        }, function(err, wallet) {
1417
            assert.ok(err);
1418
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
1419
1420
            cb();
1421
        });
1422
    });
1423
1424
    it("should be created", function(cb) {
1425
        client.createNewWallet({
1426
            identifier: myIdentifier,
1427
            passphrase: "password",
1428
            keyIndex: 9999
1429
        }, function(err, _wallet) {
1430
            assert.ifError(err);
1431
            assert.ok(_wallet);
1432
1433
            wallet = _wallet;
1434
1435
            assert.equal(wallet.identifier, myIdentifier);
1436
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1437
            cb();
1438
        });
1439
    });
1440
1441
    it("should have a 0 balance", function(cb) {
1442
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1443
            assert.ifError(err);
1444
            assert.equal(confirmed, 0);
1445
            assert.equal(unconfirmed, 0);
1446
1447
            cb();
1448
        });
1449
    });
1450
1451
    it("should be able to create a webhook", function(cb) {
1452
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", function(err, webhook) {
1453
            assert.ifError(err);
1454
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1455
            assert.equal(webhook['identifier'], "WALLET-" + myIdentifier);
1456
1457
            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...
1458
                assert.ifError(err);
1459
1460
                cb();
1461
            });
1462
        });
1463
    });
1464
1465
    it("should be able to create a webhook with custom identifier", function(cb) {
1466
        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1467
1468
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1469
            assert.ifError(err);
1470
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1471
            assert.equal(webhook['identifier'], myWebhookIdentifier);
1472
1473
            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...
1474
                assert.ifError(err);
1475
1476
                wallet.getNewAddress(function(err, address1) {
1477
                    assert.ifError(err);
1478
1479
                    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...
1480
                        assert.ifError(err);
1481
1482
                        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1483
1484
                        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1485
                            assert.ifError(err);
1486
                            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1487
                            assert.equal(webhook['identifier'], myWebhookIdentifier);
1488
1489
                            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1490
                                assert.ifError(err);
1491
                                assert.ok(_.includes(_.map(result['data'], 'address'), address1));
1492
1493
                                wallet.getNewAddress(function(err, address2) {
1494
                                    assert.ifError(err);
1495
1496
                                    client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1497
                                        assert.ifError(err);
1498
                                        assert.ok(_.includes(_.map(result['data'], 'address'), address2));
1499
1500
                                        wallet.deleteWallet(function(err, result) {
1501
                                            assert.ifError(err);
1502
                                            assert.ok(result);
1503
1504
                                            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...
1505
                                                assert.ok(err);
1506
1507
                                                cb();
1508
                                            });
1509
                                        });
1510
                                    });
1511
                                });
1512
                            });
1513
                        });
1514
                    });
1515
1516
                });
1517
            });
1518
        });
1519
    });
1520
});
1521
1522
describe("Wallet.getAddressAndType", function() {
1523
    var fixtures = [
1524
        {
1525
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1526
            network: bitcoin.networks.testnet,
1527
            type: "bech32",
1528
            valid: true
1529
        },
1530
        {
1531
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1532
            network: bitcoin.networks.testnet,
1533
            type: "bech32",
1534
            valid: true
1535
        },
1536
        {
1537
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1538
            network: bitcoin.networks.testnet,
1539
            type: "base58",
1540
            valid: true
1541
        },
1542
        {
1543
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1544
            network: bitcoin.networks.testnet,
1545
            type: "base58",
1546
            valid: true
1547
        },
1548
        {
1549
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1550
            network: bitcoin.networks.bitcoin,
1551
            type: "base58",
1552
            valid: true
1553
        },
1554
        {
1555
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1556
            network: bitcoin.networks.bitcoin,
1557
            type: "base58",
1558
            valid: true
1559
        },
1560
        {
1561
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1562
            network: bitcoin.networks.bitcoin,
1563
            type: "bech32",
1564
            valid: true
1565
        },
1566
        {
1567
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1568
            network: bitcoin.networks.bitcoin,
1569
            type: "bech32",
1570
            valid: true
1571
        },
1572
        {
1573
            address: "16uf9UUBbUHdVAnETGZQnvXZcf9NPU1QR6",
1574
            network: bitcoin.networks.testnet,
1575
            type: "base58",
1576
            error: "Address invalid on this network",
1577
            valid: false
1578
        },
1579
        {
1580
            address: "3CgSFohdEqd7pSxbDAJeJo6X5Qm2tBbby9",
1581
            network: bitcoin.networks.testnet,
1582
            type: "base58",
1583
            error: "Address invalid on this network",
1584
            valid: false
1585
        },
1586
        {
1587
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1588
            network: bitcoin.networks.testnet,
1589
            type: "bech32",
1590
            error: "Address invalid on this network",
1591
            valid: false
1592
        },
1593
        {
1594
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1595
            network: bitcoin.networks.testnet,
1596
            type: "bech32",
1597
            error: "Address invalid on this network",
1598
            valid: false
1599
        },
1600
        {
1601
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1602
            network: bitcoin.networks.bitcoincash,
1603
            error: "Non-base58 character",
1604
            type: "bech32",
1605
            valid: false
1606
        },
1607
        {
1608
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1609
            network: bitcoin.networks.bitcoincash,
1610
            error: "Non-base58 character",
1611
            type: "bech32",
1612
            valid: false
1613
        },
1614
        {
1615
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1616
            network: bitcoin.networks.bitcoincashtestnet,
1617
            error: "Non-base58 character",
1618
            type: "bech32",
1619
            valid: false
1620
        },
1621
        {
1622
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1623
            network: bitcoin.networks.bitcoincashtestnet,
1624
            error: "Non-base58 character",
1625
            type: "bech32",
1626
            valid: false
1627
        },
1628
        {
1629
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1630
            network: bitcoin.networks.bitcoin,
1631
            error: "Address invalid on this network",
1632
            type: "bech32",
1633
            valid: false
1634
        },
1635
        {
1636
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1637
            network: bitcoin.networks.bitcoin,
1638
            error: "Address invalid on this network",
1639
            type: "bech32",
1640
            valid: false
1641
        },
1642
        {
1643
            address: "bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42",
1644
            network: bitcoin.networks.testnet,
1645
            error: "Address invalid on this network",
1646
            type: "bech32",
1647
            valid: false
1648
        },
1649
        {
1650
            address: "bc1qn08f8x0eamw66enrt497zu0v3u2danzewuxrmr",
1651
            network: bitcoin.networks.testnet,
1652
            error: "Address invalid on this network",
1653
            type: "bech32",
1654
            valid: false
1655
        }
1656
    ];
1657
1658
    fixtures.map(function(fixture) {
1659
        var description =
1660
            (fixture.valid ? "parses" : "fails to parse") +
1661
            " a " + fixture.type + " address: " + fixture.address;
1662
1663
        it(description, function(cb) {
1664
            var addrAndType;
1665
            var err;
1666
            try {
1667
                addrAndType = Wallet.getAddressAndType(fixture.address, fixture.network);
1668
            } catch (e) {
1669
                err = e;
1670
            }
1671
1672
            if (fixture.valid) {
1673
                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...
1674
                assert.ok(Object.keys(addrAndType).indexOf("address") !== -1);
1675
                assert.ok(Object.keys(addrAndType).indexOf("decoded") !== -1);
1676
                assert.ok(Object.keys(addrAndType).indexOf("type") !== -1);
1677
                assert.equal(addrAndType.type, fixture.type);
1678
                assert.equal(addrAndType.address, fixture.address);
1679
            } else {
1680
                assert.ok(typeof err === "object");
1681
                assert.ok(typeof addrAndType === "undefined");
1682
                if (Object.keys(fixture).indexOf("error") !== -1) {
1683
                    assert.equal(err.message, fixture.error);
1684
                }
1685
            }
1686
            cb();
1687
        });
1688
    });
1689
});
1690
1691
describe("Wallet.convertPayToOutputs", function() {
1692
    var network = bitcoin.networks.testnet;
1693
    var fixtures = [
1694
        {
1695
            description: "p2wpkh",
1696
            network: bitcoin.networks.testnet,
1697
            value: 12345,
1698
            address: "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1699
            script: "00149bce9399f9eeddad66635d4be171ec8f14decc59"
1700
        },
1701
        {
1702
            description: "p2wsh",
1703
            network: bitcoin.networks.testnet,
1704
            value: 12345,
1705
            address: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1706
            script: "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
1707
        },
1708
        {
1709
            description: "p2pkh",
1710
            network: bitcoin.networks.testnet,
1711
            value: 12345,
1712
            address: "muinVykhtZyonxQxk8zBptX6Lmri91bdNG",
1713
            script: "76a9149bce9399f9eeddad66635d4be171ec8f14decc5988ac"
1714
        },
1715
        {
1716
            description: "p2sh",
1717
            network: bitcoin.networks.testnet,
1718
            value: 12345,
1719
            address: "2N7T4CD6CEuNHJoGKpoJH3YexqektXjyy6L",
1720
            script: "a9149bce9399f9eeddad66635d4be171ec8f14decc5987"
1721
        }
1722
    ];
1723
1724
    fixtures.map(function(fixture, i) {
1725
1726
        it(fixture.description + " converted to script, " + i, function(cb) {
1727
            var test = function(outputs) {
1728
                assert.ok(Array.isArray(outputs));
1729
                assert.equal(outputs[0].value, fixture.value);
1730
                assert.equal(outputs[0].scriptPubKey, fixture.script);
1731
                assert.equal(outputs[0].address, null);
1732
            };
1733
1734
            // should accept some input of ours
1735
            var pay = [{
1736
                scriptPubKey: fixture.script,
1737
                value: fixture.value
1738
            }];
1739
1740
            var outputs = Wallet.convertPayToOutputs(pay, network);
1741
            test(outputs);
1742
1743
            pay = {};
1744
            pay[fixture.address] = fixture.value;
1745
1746
            // should deal with simple mapping form
1747
            outputs = Wallet.convertPayToOutputs(pay, network);
1748
            test(outputs);
1749
1750
            // repeating the procedure should pass the same test
1751
            outputs = Wallet.convertPayToOutputs(outputs, network);
1752
            test(outputs);
1753
1754
            cb();
1755
        });
1756
    });
1757
});
1758
1759
describe('test wallet coin selection forms', function() {
1760
    var wallet;
1761
1762
    it("BTC testnet wallet should exist", function(cb) {
1763
        client.initWallet({
1764
            identifier: "unittest-transaction",
1765
            passphrase: "password"
1766
        }, function(err, _wallet) {
1767
            assert.ifError(err);
1768
            assert.ok(_wallet);
1769
1770
            wallet = _wallet;
1771
1772
            client.allWallets({page: 1}, function(err, wallets) {
1773
                assert.ifError(err);
1774
1775
                assert.ok(wallets['data'].length > 0);
1776
1777
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1778
                assert.equal(wallet.identifier, "unittest-transaction");
1779
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1780
1781
                cb();
1782
            });
1783
        });
1784
    });
1785
1786
    it("shouldnt coin select for wrong network", function(cb) {
1787
        var pay = {};
1788
        pay["bc1qqy36hngpyw4u6qfr40xszgate5qj827dqy36hngpyw4u6qfr40xsp3an42"] = 10000;
1789
        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...
1790
            assert.ok(err);
1791
            cb();
1792
        });
1793
    });
1794
1795
    var fixtures = [
1796
        {"tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs": 10000},
1797
        {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7": 10000},
1798
        [
1799
            {
1800
                "address": "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs",
1801
                "value": 10000
1802
            },
1803
            {
1804
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1805
                "value": 10000
1806
            }
1807
        ],
1808
        [
1809
            {
1810
                "scriptPubKey": "00149bce9399f9eeddad66635d4be171ec8f14decc59",
1811
                "value": 10000
1812
            },
1813
            {
1814
                "address": "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
1815
                "value": 10000
1816
            }
1817
        ]
1818
    ];
1819
1820
    fixtures.map(function(fixture) {
1821
        var type = "object";
1822
        if (Array.isArray(fixture)) {
1823
            type = "outputs array";
1824
        }
1825
        it("should coin select for " + type, function(cb) {
1826
            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...
1827
                assert.ifError(err);
1828
                cb();
1829
            });
1830
        });
1831
    });
1832
});
1833
1834
describe('test wallet list transactions and addresses', function() {
1835
    var wallet;
1836
1837
    it("should exists", function(cb) {
1838
        client.initWallet({
1839
            identifier: "unittest-transaction",
1840
            passphrase: "password"
1841
        }, function(err, _wallet) {
1842
            assert.ifError(err);
1843
            assert.ok(_wallet);
1844
1845
            wallet = _wallet;
1846
1847
            client.allWallets({page: 1}, function(err, wallets) {
1848
                assert.ifError(err);
1849
1850
                assert.ok(wallets['data'].length > 0);
1851
1852
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1853
                assert.equal(wallet.identifier, "unittest-transaction");
1854
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1855
1856
                cb();
1857
            });
1858
        });
1859
    });
1860
1861
    it("should list expected transactions", function(cb) {
1862
        wallet.transactions({page: 1, limit: 23}, function(err, transactions) {
1863
            assert.ifError(err);
1864
            assert.ok(transactions['data']);
1865
            assert.ok(transactions['total']);
1866
            assert.ok(transactions['data'].length === 23);
1867
            assert.ok(transactions['data'][0]['hash'], "2cb21783635a5f22e9934b8c3262146b42d251dfb14ee961d120936a6c40fe89");
1868
1869
            cb();
1870
        });
1871
    });
1872
1873
    it("should list expected addresses", function(cb) {
1874
        wallet.addresses({page: 1, limit: 23}, function(err, addresses) {
1875
            assert.ifError(err);
1876
            assert.ok(addresses['data']);
1877
            assert.ok(addresses['total']);
1878
            assert.ok(addresses['data'].length === 23);
1879
            assert.ok(addresses['data'][0]['address'], "2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS");
1880
1881
            cb();
1882
        });
1883
    });
1884
1885
    it("should list UTXOs", function(cb) {
1886
        wallet.utxos({page: 0, limit: 23}, function(err, addresses) {
1887
            assert.ifError(err);
1888
            assert.ok(addresses['data']);
1889
            assert.ok(addresses['total']);
1890
            assert.ok(addresses['data'].length === 23);
1891
1892
            cb();
1893
        });
1894
    });
1895
});
1896
1897
describe("size estimation", function() {
1898
1899
    it("should estimate proper size for 1 input 1 output TX", function() {
1900
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1901
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
1902
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1903
1904
        assert.equal(347, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1905
    });
1906
1907
    it("should estimate proper size for 99 inputs 1 output TX", function() {
1908
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1909
        for (var i = 0; i < 99; i++) {
1910
            txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', i);
1911
        }
1912
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1913
1914
        assert.equal(29453, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1915
    });
1916
1917
    it("should estimate proper size for 1 input 99 outputs TX", function() {
1918
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1919
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
1920
        for (var i = 0; i < 99; i++) {
1921
            txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1922
        }
1923
1924
        assert.equal(3679, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1925
    });
1926
});
1927
1928
describe("APIClient", function() {
1929
    it("resolvePrimaryPrivateKeyFromOptions", function(cb) {
1930
        client.resolvePrimaryPrivateKeyFromOptions({
1931
            passphrase: "password",
1932
            primaryMnemonic: "give pause forget seed dance crawl situate hole keen"
1933
        }, function(err, options) {
1934
            assert.ifError(err);
1935
            assert.ok(options.primaryPrivateKey);
1936
            assert.ok(options.primaryPrivateKey instanceof bitcoin.HDNode);
1937
            assert.equal("tprv8ZgxMBicQKsPeR93md5eVTbLDgQ8kfV4CDNtrVXv5p29KXtx7VHKFQThGkFgC61sYeeeaVH1yFv4thcvxS9cYdFrYwTNmkGhkQEJycSzAhE", options.primaryPrivateKey.toBase58());
1938
1939
            cb();
1940
1941
        });
1942
    });
1943
});
1944