Completed
Pull Request — master (#78)
by Ruben de
04:05 queued 01:39
created

  A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

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