1
|
|
|
var _ = require('lodash'); |
2
|
|
|
var blocktrail = require('../'); |
3
|
|
|
var q = require('q'); |
4
|
|
|
var crypto = require('crypto'); |
5
|
|
|
var async = require('async'); |
6
|
|
|
var bitcoin = require('bitcoinjs-lib'); |
7
|
|
|
var bip39 = require("bip39"); |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* @type APIClient |
11
|
|
|
*/ |
12
|
|
|
var client = blocktrail.BlocktrailSDK({ |
13
|
|
|
apiKey : process.env.BLOCKTRAIL_SDK_APIKEY || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APIKEY", |
14
|
|
|
apiSecret : process.env.BLOCKTRAIL_SDK_APISECRET || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APISECRET", |
15
|
|
|
testnet : true |
16
|
|
|
}); |
17
|
|
|
|
18
|
|
|
// aggregate TXs will try to have N outputs |
19
|
|
|
var SPLITNOUTS = 5; |
20
|
|
|
// don't go below MINVALUE when trying to send |
21
|
|
|
var MINVALUE = 10000; |
22
|
|
|
// don't glo below MINSPLITVALUE for outputs (nouts will be rounded down to match this) |
23
|
|
|
var MINSPLITVALUE = 10000; |
24
|
|
|
var ONEBTC = 1e8; |
25
|
|
|
|
26
|
|
|
client.initWallet({ |
27
|
|
|
identifier: "unittest-transaction", |
28
|
|
|
password: "password" |
29
|
|
|
}) |
30
|
|
|
.then(function(wallet) { |
31
|
|
|
// @DBEUG |
32
|
|
|
// return wallet.utxos().then(function(utxos) { |
33
|
|
|
// console.log(utxos); |
34
|
|
|
// }); |
35
|
|
|
|
36
|
|
|
return wallet.maxSpendable(false).then(function(maxSpendable) { |
37
|
|
|
console.log(maxSpendable); |
|
|
|
|
38
|
|
|
|
39
|
|
|
// get the address to aggregate the coins to |
40
|
|
|
var addr = wallet.getAddressByPath("M/9999'/0/0"); |
41
|
|
|
console.log(addr); |
42
|
|
|
|
43
|
|
|
var splitSend = function(value) { |
44
|
|
|
var pay = []; |
45
|
|
|
var splitValue = Math.max(MINSPLITVALUE, Math.floor(value / SPLITNOUTS)).toFixed(0); |
46
|
|
|
var nouts = Math.floor(value / splitValue); |
47
|
|
|
|
48
|
|
|
for (var i = 0; i < nouts; i++) { |
49
|
|
|
pay.push({address: addr, value: splitValue}); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
return wallet.pay(pay, null, false, false, blocktrail.Wallet.FEE_STRATEGY_MIN_RELAY_FEE, false, {allowZeroConfSelf: false}).then(function(txId) { |
53
|
|
|
console.log(txId); |
|
|
|
|
54
|
|
|
}); |
55
|
|
|
}; |
56
|
|
|
|
57
|
|
|
// start at 20 BTC, * 0.5 every time we can't send such a large amount anymore |
58
|
|
|
var value = 20 * ONEBTC; |
59
|
|
|
// track retries |
60
|
|
|
var retries = 0; |
61
|
|
|
|
62
|
|
|
var keepSpending = function() { |
63
|
|
|
return wallet.getBalance().then(function(b) { |
64
|
|
|
console.log(b); |
|
|
|
|
65
|
|
|
|
66
|
|
|
// do a split send |
67
|
|
|
return splitSend(Math.min(b[0], value)) |
68
|
|
|
.then(function() { |
69
|
|
|
// keep sending for as long as possible |
70
|
|
|
return keepSpending() |
71
|
|
|
.then(function() { |
72
|
|
|
// reset retries on success |
73
|
|
|
retries = 0; |
74
|
|
|
}); |
75
|
|
|
}, function(e) { |
76
|
|
|
console.error(e.message || e); |
77
|
|
|
|
78
|
|
|
// if TX is too big (or MrSign times out cuz TX is too big to sign) |
79
|
|
|
if (e.message.match(/too big/) || e.message.match(/MrSign/)) { |
80
|
|
|
// if value reaches <= MINVALUE then we're done(ish) |
81
|
|
|
if (value <= MINVALUE) { |
82
|
|
|
retries++; |
83
|
|
|
|
84
|
|
|
// retry 3 more times, otherwise done |
85
|
|
|
if (retries >= 3) { |
86
|
|
|
throw new Error("DONE"); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
// keep trying |
90
|
|
|
return keepSpending(); |
91
|
|
|
} else { |
92
|
|
|
// halve the value and try again |
93
|
|
|
value *= 0.5; |
94
|
|
|
console.log('too big, new value:', blocktrail.toBTC(value)); |
|
|
|
|
95
|
|
|
|
96
|
|
|
return keepSpending(); |
97
|
|
|
} |
98
|
|
|
} else if (e.message.match(/too low/)) { |
99
|
|
|
// halve the value and try again |
100
|
|
|
value *= 0.5; |
101
|
|
|
console.log('too big, new value:', blocktrail.toBTC(value)); |
102
|
|
|
|
103
|
|
|
return keepSpending(); |
104
|
|
|
} else if (e.message.match(/All usable unspent/)) { |
105
|
|
|
// halve the value and try again, but with a timeout |
106
|
|
|
value *= 0.5; |
107
|
|
|
console.log('too big, new value:', blocktrail.toBTC(value)); |
108
|
|
|
|
109
|
|
|
var deferred = q.defer(); |
110
|
|
|
|
111
|
|
|
setTimeout(function() { |
112
|
|
|
deferred.resolve(); |
113
|
|
|
}, 11000); |
114
|
|
|
|
115
|
|
|
return deferred.promise.then(function() { |
116
|
|
|
return keepSpending(); |
117
|
|
|
}); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
throw e; |
121
|
|
|
}); |
122
|
|
|
}); |
123
|
|
|
}; |
124
|
|
|
|
125
|
|
|
return keepSpending(); |
126
|
|
|
}); |
127
|
|
|
}) |
128
|
|
|
.catch(function(e) { |
129
|
|
|
console.error(e); |
130
|
|
|
}); |
131
|
|
|
|