Multiple receivers in sendTx
- Can now send to more than one receiver
- receiverID, amount is replaced as receivers (object) format: {id1:amt1, id2:amt2}
- Updated UI for the same
This commit is contained in:
parent
44bd69c7c8
commit
1e9cb164ad
27
index.html
27
index.html
@ -81,15 +81,20 @@
|
|||||||
<input type="number" class="form-control" name="balance" placeholder="Check Balance" disabled>
|
<input type="number" class="form-control" name="balance" placeholder="Check Balance" disabled>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<template class="receiver-template">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-addon"><i>Receiver</i></span>
|
<span class="input-group-addon"><i>Receiver</i></span>
|
||||||
<input type="text" class="form-control" name="receiver" placeholder="Receiver ID">
|
<input type="text" class="form-control" name="receiver" placeholder="Receiver ID">
|
||||||
</div>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-addon"><i>Amount</i></span>
|
<span class="input-group-addon"><i>Amount</i></span>
|
||||||
<input type="number" class="form-control" name="amount" placeholder="Amount" min="0" step="0.01">
|
<input type="number" class="form-control" name="amount" placeholder="Amount" min="0" step="0.01">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button class="btn btn-default" name="rm-receiver" type="button">X</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="receiver-container"></div>
|
||||||
|
<button type="button" name="add-receiver" class="btn btn-default"><b>+</b></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-addon"><i>Fee</i></span>
|
<span class="input-group-addon"><i>Fee</i></span>
|
||||||
@ -193,15 +198,23 @@
|
|||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
.finally(_ => sendForm['check-balance'].disabled = false)
|
.finally(_ => sendForm['check-balance'].disabled = false)
|
||||||
}
|
}
|
||||||
|
let receiver_template = sendForm.getElementsByClassName('receiver-template')[0],
|
||||||
|
receiver_container = sendForm.getElementsByClassName('receiver-container')[0];
|
||||||
|
sendForm['add-receiver'].onclick = evt => {
|
||||||
|
receiver_container.appendChild(receiver_template.content.cloneNode(true));
|
||||||
|
let clone = receiver_container.lastElementChild;
|
||||||
|
clone.getElementsByTagName("button")[0].onclick = evt => receiver_container.removeChild(clone);
|
||||||
|
};
|
||||||
|
sendForm['add-receiver'].click();
|
||||||
sendForm['submit'].onclick = evt => {
|
sendForm['submit'].onclick = evt => {
|
||||||
let sender = sendForm["sender"].value,
|
let sender = sendForm["sender"].value,
|
||||||
receiver = sendForm["receiver"].value,
|
receivers = {},
|
||||||
amount = parseFloat(sendForm["amount"].value),
|
|
||||||
fee = parseFloat(sendForm["fee"].value);
|
fee = parseFloat(sendForm["fee"].value);
|
||||||
console.debug(sender, receiver, amount, fee)
|
for (let i = 0; i < sendForm["receiver"].length; i++)
|
||||||
|
receivers[sendForm["receiver"][i].value] = parseFloat(sendForm["amount"][i].value);
|
||||||
let privKey = prompt("Enter Private Key:");
|
let privKey = prompt("Enter Private Key:");
|
||||||
sendForm['submit'].disabled = true;
|
sendForm['submit'].disabled = true;
|
||||||
btc_api.sendTx(sender, privKey, receiver, amount, fee).then(result => {
|
btc_api.sendTx(sender, privKey, receivers, fee).then(result => {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
alert("transaction id: " + result.txid);
|
alert("transaction id: " + result.txid);
|
||||||
}).catch(error => console.error(error)).finally(_ => sendForm['submit'].disabled = false)
|
}).catch(error => console.error(error)).finally(_ => sendForm['submit'].disabled = false)
|
||||||
|
|||||||
40
lib_btc.js
40
lib_btc.js
@ -2549,7 +2549,7 @@
|
|||||||
})();
|
})();
|
||||||
})(typeof global !== "undefined" ? global : window);
|
})(typeof global !== "undefined" ? global : window);
|
||||||
|
|
||||||
(function(EXPORTS) { //btc_api v1.0.3
|
(function(EXPORTS) { //btc_api v1.0.4
|
||||||
const btc_api = EXPORTS;
|
const btc_api = EXPORTS;
|
||||||
|
|
||||||
const URL = "https://chain.so/api/v2/";
|
const URL = "https://chain.so/api/v2/";
|
||||||
@ -2604,6 +2604,8 @@
|
|||||||
coinjs.compressed = true;
|
coinjs.compressed = true;
|
||||||
|
|
||||||
const verifyKey = btc_api.verifyKey = function(addr, key) {
|
const verifyKey = btc_api.verifyKey = function(addr, key) {
|
||||||
|
if (!addr || !key)
|
||||||
|
return undefined;
|
||||||
switch (coinjs.addressDecode(addr).type) {
|
switch (coinjs.addressDecode(addr).type) {
|
||||||
case "standard":
|
case "standard":
|
||||||
return btc_api.address(key) === addr;
|
return btc_api.address(key) === addr;
|
||||||
@ -2638,7 +2640,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btc_api.sendTx = function(senderID, senderPrivKey, receiverID, amount, fee) {
|
btc_api.sendTx = function(senderID, senderPrivKey, receivers, fee) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!verifyKey(senderID, senderPrivKey))
|
if (!verifyKey(senderID, senderPrivKey))
|
||||||
return reject("Invalid privateKey");
|
return reject("Invalid privateKey");
|
||||||
@ -2646,17 +2648,18 @@
|
|||||||
senderPrivKey = coinjs.privkey2wif(key);
|
senderPrivKey = coinjs.privkey2wif(key);
|
||||||
let redeemScript = getRedeemScript(senderID, senderPrivKey);
|
let redeemScript = getRedeemScript(senderID, senderPrivKey);
|
||||||
getBalance(senderID).then(balance => {
|
getBalance(senderID).then(balance => {
|
||||||
if (balance < amount + fee)
|
let total_amount = 0;
|
||||||
|
for (let r in receivers)
|
||||||
|
total_amount += receivers[r];
|
||||||
|
total_amount = parseFloat(total_amount.toFixed(8));
|
||||||
|
if (balance < total_amount + fee)
|
||||||
return reject("Insufficient Balance");
|
return reject("Insufficient Balance");
|
||||||
//coinjs.compressed = true; //true if WIF?
|
var tx = coinjs.transaction();
|
||||||
var r = coinjs.transaction();
|
|
||||||
//var wif = coinjs.privkey2wif(privKeyHex); //privateKey: Hex to WIF
|
|
||||||
//var address1 = coinjs.scripthash2address(address0); //receiver: Hash to Hex
|
|
||||||
getUTXO(senderID).then(result => {
|
getUTXO(senderID).then(result => {
|
||||||
let utxos = result.data.txs.reverse();
|
let utxos = result.data.txs.reverse();
|
||||||
console.debug(balance, utxos);
|
console.debug(balance, utxos);
|
||||||
var input_total = 0;
|
var input_total = 0;
|
||||||
for (let i = 0; i < utxos.length && input_total < amount + fee; i++) {
|
for (let i = 0; i < utxos.length && input_total < total_amount + fee; i++) {
|
||||||
input_total += parseFloat(utxos[i].value);
|
input_total += parseFloat(utxos[i].value);
|
||||||
let script = utxos[i].script_hex;
|
let script = utxos[i].script_hex;
|
||||||
if (redeemScript) { //redeemScript for segwit/bech32
|
if (redeemScript) { //redeemScript for segwit/bech32
|
||||||
@ -2666,18 +2669,21 @@
|
|||||||
s.writeBytes(coinjs.numToBytes((utxos[i].value * 100000000).toFixed(0), 8));
|
s.writeBytes(coinjs.numToBytes((utxos[i].value * 100000000).toFixed(0), 8));
|
||||||
script = Crypto.util.bytesToHex(s.buffer);
|
script = Crypto.util.bytesToHex(s.buffer);
|
||||||
}
|
}
|
||||||
r.addinput(utxos[i].txid, utxos[i].output_no, script, 0xffffffff /*sequence*/ );
|
tx.addinput(utxos[i].txid, utxos[i].output_no, script, 0xffffffff /*sequence*/ );
|
||||||
}
|
}
|
||||||
r.addoutput(receiverID, amount);
|
if (input_total < total_amount + fee)
|
||||||
let change = parseFloat((input_total - (amount + fee)).toFixed(8));
|
return reject("Insufficient Balance (UTXO)")
|
||||||
|
for (let r in receivers)
|
||||||
|
tx.addoutput(r, receivers[r]);
|
||||||
|
let change = parseFloat((input_total - (total_amount + fee)).toFixed(8));
|
||||||
if (change)
|
if (change)
|
||||||
r.addoutput(senderID, change);
|
tx.addoutput(senderID, change);
|
||||||
console.debug(input_total, amount, fee, change);
|
console.debug(input_total, total_amount, fee, change);
|
||||||
console.debug("Unsigned:", r.serialize());
|
console.debug("Unsigned:", tx.serialize());
|
||||||
r.sign(senderPrivKey, 1 /*sighashtype*/ ); //Sign the tx using private key WIF
|
tx.sign(senderPrivKey, 1 /*sighashtype*/ ); //Sign the tx using private key WIF
|
||||||
console.debug("Signed:", r.serialize());
|
console.debug("Signed:", tx.serialize());
|
||||||
debugger;
|
debugger;
|
||||||
broadcast(r.serialize())
|
broadcast(tx.serialize())
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error));
|
.catch(error => reject(error));
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user