-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunspent-selector.ts
98 lines (72 loc) · 3.02 KB
/
unspent-selector.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// npx ts-node unspent-selector.ts
// the four things to configure below:
// 1) the source and dest wallets. these are walletId and the address in transaction
// 2) walletPassphrase, 3) accessToken
// 4) feeRate - this is based on the mempool congestion
import { BitGo, Wallet } from 'bitgo';
import { Dimensions, Codes } from '@bitgo/unspents';
import * as _ from 'lodash';
const bitgo = new BitGo({ env: 'prod' });
const coin = 'btc';
const basecoin = bitgo.coin(coin);
/// ----------------------------------------------------
/// CONFIGURATION AREA - check each of these
/// ----------------------------------------------------
// REMOVE THESE UNSPENTS
// CONFIGURE ALL THIS
// set these in private
const accessToken = '';
const walletPassphrase = '';
const walletId = '';
const feeRate = 80 * 1000;
const destAddress = '';
const unspentIdsToRemove = [ '' ];
const secondSendAmount = 8 * 1e8;
const secondSendAddress = '';
const nOutputs = 2;
/// ----------------------------------------------------
/// CONFIGURATION AREA
/// ----------------------------------------------------
async function main() {
bitgo.authenticateWithAccessToken({ accessToken });
const walletInstance = await basecoin.wallets().get({ id: walletId });
let unspents: any[] = (await walletInstance.unspents()).unspents;
// remove unspents
const filteredUnspents = _.filter(unspents, n => !_.some(unspentIdsToRemove, t => t == n.id));
const removedUnspents = _.filter(unspents, n => _.some(unspentIdsToRemove, t => t == n.id));;
console.dir(filteredUnspents);
console.log('total = ' + _.sumBy(unspents, n => n.value) / 1e8);
console.log('value sent = ' + _.sumBy(filteredUnspents, n => n.value) / 1e8);
console.log('value removed = ' + _.sumBy(removedUnspents, n => n.value) / 1e8);
const unspentsDimensions = Dimensions.fromUnspents(filteredUnspents)
// assumes all unspents are p2shp2wsh - basically right for bitgo addrs
// HAVE TO CHANGE THIS TO THE ADDRESS TYPES YOU'RE DRAWING FROM
.plus(Dimensions.fromOutputOnChain(Codes.p2shP2wsh.internal)
.times(nOutputs));
const vSize = unspentsDimensions.getVSize();
// total unspents value
// satoshis per vbyte
const unspentsValue = _.sumBy(filteredUnspents, 'value');
// estimated fee - if this feeRate is not div by 1000, gonna have to floor it since it needs to be an integer
const estimatedFee = unspentsDimensions.getVSize() * _.floor(feeRate / 1000);
const sendAmount = unspentsValue - estimatedFee;
const transaction = await walletInstance.sendMany({
unspents: _.map(filteredUnspents, 'id'),
recipients: [
{
// this should be a precise value without any change outputs now
amount: sendAmount - secondSendAmount,
address: destAddress,
},
{
amount: secondSendAmount,
address: secondSendAddress,
}
],
walletPassphrase,
feeRate,
// work around a bug in sendMany
} as any);
console.log('New Transaction:', JSON.stringify(transaction, null, 4));
};
main().catch((e) => console.error(e));