-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmsgp_tx.js
More file actions
125 lines (102 loc) · 4.26 KB
/
Copy pathmsgp_tx.js
File metadata and controls
125 lines (102 loc) · 4.26 KB
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
const fetch = require('node-fetch');
const bsv = require ('bsv')
const RECEIVER_PRIVATEKEY = new bsv.PrivKey().fromWif('**************!!!!!!!!!!!!********************')
const SENDER_PRIVATEKEY = new bsv.PrivKey().fromWif('**************!!!!!!!!!!!!********************')
const DUST = 547 //satoshis
bsv.Constants.Mainnet.TxBuilder.dust = DUST
async function getUtxoWoc(address){
const apiRequest = "https://api.whatsonchain.com/v1/bsv/main/address/"+address+"/unspent"
const response = await fetch(apiRequest, { method: 'GET', headers: {} });
const json = await response.json();
let utxos = []
for (var i = 0; i < json.length; i++) {
const tx = json[i]
const apiRequest2 = `https://api.whatsonchain.com/v1/bsv/main/tx/hash/${tx.tx_hash}`
const response2 = await fetch(apiRequest2, { method: 'GET', headers: {} });
const json2 = await response2.json();
for (var a = 0; a < json2.vout.length; a++) {
const output = json2.vout[a]
if(output.scriptPubKey.type == 'pubkeyhash'){
utxos.push({
"txId": json2.txid,
"satoshis" : output.value*100000000,
"outputIndex" : a,
"address" : output.scriptPubKey.addresses[0],
"script" : output.scriptPubKey,
})
}
}
}
return utxos
}
async function generateTx(channelId,senderKeyPair,receiverPubkey,payload,sigHashFlag='41',opreturn=true){
const address = new bsv.Address().fromPubKey(senderKeyPair.pubKey).toString()
const PROTOCOL_PREFIX = '6d736770' //hex
const PROTOCOL_TYPE = '00000001' //hex
const sequence = parseInt((Date.now()/1000).toFixed(0)).toString(16) // unixtimestamp/seconds
const utxos = await getUtxoWoc( address )
const builder = new bsv.TxBuilder()
for (var i = 0; i < utxos.length; i++) {
const utxo = utxos[i]
const fundTxOut = new bsv.TxOut().fromProperties(
bsv.Bn().fromNumber(utxo.satoshis),
bsv.Address.fromString( address ).toTxOutScript()
)
const fundTxHashBuf = Buffer.from(utxo.txId, 'hex').reverse()
builder.inputFromPubKeyHash(fundTxHashBuf, utxo.outputIndex, fundTxOut)
}
let txInBuf = []
if(sigHashFlag='41'){
builder.txIns.forEach((txIn)=>{
txInBuf.push(txIn.toBuffer())
})
} else {
// others
console.log("wrong sighashflag");
}
const txInsBuf = Buffer.concat(txInBuf);
const payloadBuf = Buffer.from(payload,'hex')
const preimageBuf = Buffer.concat([txInsBuf,payloadBuf])
const msgpHash = bsv.Hash.sha256(preimageBuf)
const senderSig = bsv.Ecdsa.sign(msgpHash, senderKeyPair)
console.log(`Signature: ${senderSig.toString('hex')} SigCheck: ${bsv.Ecdsa.verify(msgpHash, senderSig, senderKeyPair.pubKey)}`)
const dataBuf = Buffer.from([senderKeyPair.pubKey,sigHashFlag,senderSig,sequence,payload].join(''),'hex')
const encDataBuf = bsv.Ecies.electrumEncrypt(dataBuf,receiverPubkey,null)
const decDataBuf = bsv.Ecies.electrumDecrypt(encDataBuf,RECEIVER_PRIVATEKEY)
console.log("\nENC:",encDataBuf.toString('hex'),encDataBuf.length);
console.log("DEC:",decDataBuf.toString('hex'),decDataBuf.length);
const protodata = [PROTOCOL_PREFIX,PROTOCOL_TYPE,channelId,encDataBuf.toString('hex')].join('')
// Add output to address
let amount
let script
let outScript
if(opreturn){
script = new bsv.Script().fromAsmString(`OP_FALSE OP_RETURN ${protodata}`)
amount = 0
} else {
outScript = bsv.Address.fromString( address ).toTxOutScript().toAsmString()
script = new bsv.Script().fromAsmString(`${protodata} OP_DROP ${outScript}`)
amount = DUST
}
builder.outputToScript(bsv.Bn().fromNumber(amount), script)
// Set change address
builder.setChangeAddress(bsv.Address.fromString( address ))
builder.build()
builder.signWithKeyPairs([senderKeyPair])
return builder.tx
}
async function main() {
const receiverPubkey = new bsv.PubKey().fromString('02dcec5ff54316e25c27ec754c8750e163834a4d4aee6f20c57185f40606fa4057')
const channelId = bsv.Hash.sha256(receiverPubkey.toBuffer()).toString('hex')
const senderKeyPair = new bsv.KeyPair().fromPrivKey(SENDER_PRIVATEKEY)
const payload = 'aaffaaffaaffaaff' //hex
const tx = await generateTx(channelId,senderKeyPair,receiverPubkey,payload,'41',true)
console.log(`\nTXHex: ${tx.toHex()}`)
}
(async () => {
try {
main();
} catch (e) {
console.log(e);
}
})();