forked from bigearth/bitbox-cli
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added e2e test for sendRawTransaction single call
- Loading branch information
1 parent
9ccbc21
commit ede9b46
Showing
4 changed files
with
215 additions
and
2 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "sendrawtransaction", | ||
"version": "1.0.0", | ||
"description": "e2e test - Send two transactions in parallel.", | ||
"main": "sendrawtransaction.js", | ||
"scripts": { | ||
"test": "echo no tests yet", | ||
"start": "node sendrawtransaction.js" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Bitcoin-com/bitbox-javascript-sdk.git" | ||
}, | ||
"keywords": [ | ||
"bitbox", | ||
"bch", | ||
"bitcoin", | ||
"bitcoin cash", | ||
"bitcoin.com", | ||
"javascript" | ||
], | ||
"author": "Chris Troutner <[email protected]>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/Bitcoin-com/bitbox-javascript-sdk/issues" | ||
}, | ||
"homepage": "https://github.com/Bitcoin-com/bitbox-javascript-sdk/blob/master/README.md" | ||
} |
184 changes: 184 additions & 0 deletions
184
test/e2e/send-raw-transaction-single/sendrawtransaction.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
This is an end-to-end test adapted from the send-bch example. It's purpose | ||
is to test the sendRawTransaction endpoint. | ||
This version tests the single send call. | ||
Instructions: | ||
- Ensure the address in the wallet.json file has some tBCH. | ||
- Ensure the address in the wallet.json file has a UTXOs between 0.1 and | ||
0.001 tBCH | ||
- This test will generate a single transaction from a UTXOs and broadcast it | ||
using the sendrawtransaction single GET endpoint. | ||
*/ | ||
|
||
// Replace the address below with the address you want to send the BCH to. | ||
const RECV_ADDR1 = `bchtest:qzfn2mly05t6fjsh5kjj0dqq0jjtct27ng089dgg05` | ||
const SATOSHIS_TO_SEND = 1000 | ||
|
||
// Instantiate BITBOX. | ||
const bitboxLib = "../../../lib/bitbox-sdk" | ||
const BITBOXSDK = require(bitboxLib).default | ||
const BITBOX = new BITBOXSDK({ restURL: "https://trest.bitcoin.com/v2/" }) | ||
//const BITBOX = new BITBOXSDK({ restURL: "http://localhost:3000/v2/" }) | ||
|
||
const util = require("util") | ||
|
||
// Open the wallet generated with create-wallet. | ||
try { | ||
var walletInfo = require(`./wallet.json`) | ||
} catch (err) { | ||
console.log( | ||
`Could not open wallet.json. Generate a wallet with create-wallet first.` | ||
) | ||
process.exit(0) | ||
} | ||
|
||
const SEND_ADDR = walletInfo.cashAddress | ||
const SEND_MNEMONIC = walletInfo.mnemonic | ||
|
||
async function testSend() { | ||
try { | ||
const hex1 = await buildTx1(RECV_ADDR1) | ||
//const hex2 = await buildTx2(RECV_ADDR2) | ||
|
||
console.log(`hex1: ${hex1}\n\n`) | ||
//console.log(`hex2: ${hex2}\n\n`) | ||
|
||
const broadcast = await BITBOX.RawTransactions.sendRawTransaction(hex1) | ||
|
||
console.log(`Transaction IDs: ${JSON.stringify(broadcast, null, 2)}`) | ||
console.log(`Should return a TXID string.`) | ||
} catch (err) { | ||
console.log(`Error in testSend: `, err) | ||
} | ||
} | ||
testSend() | ||
|
||
// Build a TX hex with the largest UTXO. | ||
async function buildTx1(recAddr) { | ||
try { | ||
// Get the balance of the sending address. | ||
const balance = await getBCHBalance(SEND_ADDR, false) | ||
console.log(`balance: ${JSON.stringify(balance, null, 2)}`) | ||
console.log(`Balance of sending address ${SEND_ADDR} is ${balance} BCH.`) | ||
|
||
// Exit if the balance is zero. | ||
if (balance <= 0.0) { | ||
console.log(`Balance of sending address is zero. Exiting.`) | ||
process.exit(0) | ||
} | ||
|
||
const SEND_ADDR_LEGACY = BITBOX.Address.toLegacyAddress(SEND_ADDR) | ||
const RECV_ADDR_LEGACY = BITBOX.Address.toLegacyAddress(recAddr) | ||
console.log(`Sender Legacy Address: ${SEND_ADDR_LEGACY}`) | ||
console.log(`Receiver Legacy Address: ${RECV_ADDR_LEGACY}`) | ||
|
||
const balance2 = await getBCHBalance(recAddr, false) | ||
//console.log(`Balance of recieving address ${recAddr} is ${balance2} BCH.`) | ||
|
||
const u = await BITBOX.Address.utxo(SEND_ADDR) | ||
//console.log(`u: ${JSON.stringify(u, null, 2)}`) | ||
const utxo = findBiggestUtxo(u.utxos) | ||
console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`) | ||
|
||
// instance of transaction builder | ||
const transactionBuilder = new BITBOX.TransactionBuilder("testnet") | ||
|
||
const satoshisToSend = SATOSHIS_TO_SEND | ||
const originalAmount = utxo.satoshis | ||
const vout = utxo.vout | ||
const txid = utxo.txid | ||
|
||
// add input with txid and index of vout | ||
transactionBuilder.addInput(txid, vout) | ||
|
||
// get byte count to calculate fee. paying 1.2 sat/byte | ||
const byteCount = BITBOX.BitcoinCash.getByteCount( | ||
{ P2PKH: 1 }, | ||
{ P2PKH: 2 } | ||
) | ||
console.log(`byteCount: ${byteCount}`) | ||
const satoshisPerByte = 1.0 | ||
const txFee = Math.floor(satoshisPerByte * byteCount) | ||
console.log(`txFee: ${txFee}`) | ||
|
||
// amount to send back to the sending address. | ||
// It's the original amount - 1 sat/byte for tx size | ||
const remainder = originalAmount - satoshisToSend - txFee | ||
|
||
// add output w/ address and amount to send | ||
transactionBuilder.addOutput(recAddr, satoshisToSend) | ||
transactionBuilder.addOutput(SEND_ADDR, remainder) | ||
|
||
// Generate a change address from a Mnemonic of a private key. | ||
const change = changeAddrFromMnemonic(SEND_MNEMONIC) | ||
|
||
// Generate a keypair from the change address. | ||
const keyPair = BITBOX.HDNode.toKeyPair(change) | ||
|
||
// Sign the transaction with the HD node. | ||
let redeemScript | ||
transactionBuilder.sign( | ||
0, | ||
keyPair, | ||
redeemScript, | ||
transactionBuilder.hashTypes.SIGHASH_ALL, | ||
originalAmount | ||
) | ||
|
||
// build tx | ||
const tx = transactionBuilder.build() | ||
// output rawhex | ||
const hex = tx.toHex() | ||
|
||
return hex | ||
} catch (err) { | ||
console.log(`Error in buildTx().`) | ||
throw err | ||
} | ||
} | ||
|
||
// Generate a change address from a Mnemonic of a private key. | ||
function changeAddrFromMnemonic(mnemonic) { | ||
// root seed buffer | ||
const rootSeed = BITBOX.Mnemonic.toSeed(mnemonic) | ||
|
||
// master HDNode | ||
const masterHDNode = BITBOX.HDNode.fromSeed(rootSeed, "testnet") | ||
|
||
// HDNode of BIP44 account | ||
const account = BITBOX.HDNode.derivePath(masterHDNode, "m/44'/145'/0'") | ||
|
||
// derive the first external change address HDNode which is going to spend utxo | ||
const change = BITBOX.HDNode.derivePath(account, "0/0") | ||
|
||
return change | ||
} | ||
|
||
// Get the balance in BCH of a BCH address. | ||
async function getBCHBalance(addr, verbose) { | ||
try { | ||
const result = await BITBOX.Address.details(addr) | ||
|
||
if (verbose) console.log(result) | ||
|
||
const bchBalance = result | ||
|
||
return bchBalance.balance | ||
} catch (err) { | ||
console.error(`Error in getBCHBalance: `, err) | ||
console.log(`addr: ${addr}`) | ||
throw err | ||
} | ||
} | ||
|
||
// Returns the utxo with the biggest balance from an array of utxos. | ||
function findBiggestUtxo(utxos) { | ||
// Sort the utxos by the amount of satoshis, largest first. | ||
utxos.sort(function(a, b) { | ||
return b.satoshis - a.satoshis | ||
}) | ||
|
||
return utxos[0] | ||
} |