-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbtcBasic.js
136 lines (116 loc) · 4.35 KB
/
btcBasic.js
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
const _ = require('lodash')
const bitcoin = require('bitcoinjs-lib');
const BigNumber = require('bignumber.js');
const coinSelect = require('coinselect')
const axios = require('axios')
const config = require('./configLoad');
class btcBasic{
constructor(chain){
this.config = config[chain]
}
get = async (url) => {
return (await axios.get(this.config.URL + url)).data
}
post = async (url, data) => {
return (await axios.post(this.config.URL + url, data)).data
}
getAddressUtxo = async (address) => {
const result = await this.get(`/address/${address}?unspent=true&limit=1000`)
return this.utxoMapper(result)
}
utxoMapper = (utxos) => {
utxos = utxos.map(utxo => {
const out = {}
const amount = new BigNumber(utxo.value).div(1e8).toNumber()
_.set(out, 'address', utxo.address)
_.set(out, 'txid', utxo.mintTxid)
_.set(out, 'txId', utxo.mintTxid)
_.set(out, 'vout', utxo.mintIndex)
_.set(out, 'scriptPubKey', utxo.script)
_.set(out, 'amount', amount)
_.set(out, 'satoshis', utxo.value)
_.set(out, 'height', utxo.mintHeight)
_.set(out, 'confirmations', utxo.confirmations)
return _.assign(utxo, out)
})
return utxos
}
getfeeRate = async() => {
const result = await this.get('/fee/7')
return result.feerate
}
sendTx = async(rawtx) =>{
let result
try {
result = await this.post('/tx/send', { rawTx: rawtx })
} catch (err) {
console.log(err)
throw new Error('broadcast tx failed ')}
return result
}
async getUtxos() {
const froms = _.map(this.config.KEYPAIR,'ADDRESS')
const utxoSet = new Set();
for (const address of froms) {
const utxos = await this.getAddressUtxo(address)
utxos.forEach(utxo => {
utxoSet.add(JSON.stringify(utxo))
});
}
const uniqueUTXOs = Array.from(utxoSet).map(utxoString => JSON.parse(utxoString))
return uniqueUTXOs
}
network = () => {
return bitcoin.networks.testnet
}
genAddressByRandom = () => {
const network = this.network()
const keyPair = bitcoin.ECPair.makeRandom({ network })
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network })
console.log(`Address: ${address},PrivateKey: ${keyPair.toWIF()}`)
return address
}
async sendBTC(address,amount){
const feePrice = await this.getfeeRate()
const feeRate = new BigNumber(feePrice).times(1e8).dividedBy(100).integerValue(BigNumber.ROUND_DOWN).toNumber()
const value = new BigNumber(amount).times(1e8).toNumber()
let targets = [{
address,
value
}]
//const froms
// 扩展成50个output
// targets = Array(12).fill().map(() => targets).flat();
const utxos = await this.getUtxos()
const {inputs, outputs, fee} = coinSelect(utxos,targets,feeRate)
if (inputs && outputs){
//build tx
const filledOutputs = outputs.map(output => {
if (!output.address) {
output.address = inputs[0].address; // 在这里设置默认值
}
return output;
})
const network = this.network()
const tx = new bitcoin.TransactionBuilder(network)
inputs.forEach((e)=>tx.addInput(e.txid,e.vout))
filledOutputs.forEach((e)=>tx.addOutput(e.address,e.value))
//sign tx
const froms = this.config.KEYPAIR
let signer,priKey
for (let i =0;i<inputs.length;i++){
priKey = _.find(froms, function(o) { return o.ADDRESS == inputs[i].address})
signer = bitcoin.ECPair.fromWIF(priKey.PRIKEY, network)
tx.sign(i,signer)
}
//send tx
const rawtx = tx.build().toHex()
const hash = await this.sendTx(rawtx)
console.log(`Transfer ${amount} BTC to ${address}. Transaction Hash: ${hash.txid}`);
} else {
console.log(inputs, outputs, fee)
throw new Error('not enough utxos!!!')
}
}
}
module.exports = btcBasic