Skip to content

Commit

Permalink
Merge pull request #48 from getsafle/feature-transaction-and-fee-updates
Browse files Browse the repository at this point in the history
Feature transaction and fee updates
  • Loading branch information
sshubhamagg committed Jan 23, 2024
2 parents 3f41775 + 7d4472e commit fa277c7
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 38 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,13 @@

##### GetFees() update

- Added await for the async call to get transactionSize and updated tests
- Added await for the async call to get transactionSize and updated tests

### 2.0.4 (2024-01-09)

- Updated Sochain api key

### 2.0.5 (2024-01-23)

- Replaced blockcyper api with sochain api to fetch fees in satoshi
- Updated sign transaction to use bitcoinjs-lib
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@getsafle/vault-bitcoin-controller",
"version": "2.0.3",
"version": "2.0.5",
"description": "",
"engines": {
"node": ">= 10"
Expand Down
3 changes: 1 addition & 2 deletions src/constants/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
module.exports = {
SOCHAIN_API_KEY: 'F7RKphrzItSQV-MUoPY_S0XIuwTzxFpt',
SOCHAIN_API_KEY: 'jsGr7ioLvkz1Hfo6uwH_CGYdOnIpWtrJ',
SOCHAIN_BASE_URL: "https://sochain.com/api/v3/",
BLOCKCYPHER_BASE_URL: "https://api.blockcypher.com/v1/btc/"
}
11 changes: 5 additions & 6 deletions src/helper/calculateFeeAndInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ async function getTransactionSize(URL, headers){
let inputs = [];
utxos.data.data.outputs.forEach(async (element) => {
let utxo = {};
utxo.satoshis = sb.toSatoshi(parseFloat(element.value));
utxo.script = element.script;
utxo.address = element.address;
utxo.txId = element.hash;
utxo.outputIndex = element.index;
totalAmountAvailable += utxo.satoshis;
utxo.value = sb.toSatoshi(parseFloat(element.value));
utxo.scriptPubKey = element.script;
utxo.txid = element.hash;
utxo.vout = element.index;
totalAmountAvailable += utxo.value;
inputCount += 1;
inputs.push(utxo);
});
Expand Down
51 changes: 32 additions & 19 deletions src/helper/signTransaction.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
const bitcore = require("bitcore-lib")
const bitcoin = require("bitcoinjs-lib")

const {getFeeAndInput} = require('./calculateFeeAndInput')

async function signTransaction(from, to, amountToSend, URL, privateKey, satPerByte, headers) {

const transaction = new bitcore.Transaction();
async function signTransaction(from, to, amountToSend, URL, privateKey, satPerByte, headers, network) {
const psbt = new bitcoin.Psbt({ network: network })

const { totalAmountAvailable, inputs, fee } = await getFeeAndInput(URL, satPerByte, headers)

if (totalAmountAvailable - amountToSend - fee < 0) {
throw new Error("Balance is too low for this transaction");
}

//Set transaction input
transaction.from(inputs);

// set the recieving address and the amount to send
transaction.to(to, Math.floor(amountToSend));

// Set change address - Address to receive the left over funds after transfer
transaction.change(from);
for (const unspentOutput of inputs) {
psbt.addInput({
hash: unspentOutput.txid,
index: unspentOutput.vout,
witnessUtxo: {
script: Buffer.from(unspentOutput.scriptPubKey, 'hex'),
value: unspentOutput.value // value in satoshi
},
})
}

//manually set transaction fees: 20 satoshis per byte
transaction.fee(fee);
psbt.addOutput({address: to, value: amountToSend});

// Sign transaction with your private key
transaction.sign(privateKey);
const change = totalAmountAvailable - amountToSend - fee
psbt.addOutput({address: from, value: change});

for (let i = 0; i < inputs.length; i++) {
psbt.signInput(i, bitcoin.ECPair.fromWIF(privateKey, bitcoin.networks.testnet))
}

// serialize Transactions
const serializedTransaction = transaction.serialize();
const isValid = psbt.validateSignaturesOfAllInputs()

return serializedTransaction;
if (isValid) {
psbt.finalizeAllInputs()
// signed transaction hex
const transaction = psbt.extractTransaction()
const signedTransaction = transaction.toHex()
const transactionId = transaction.getId()

return signedTransaction
}

}


module.exports = signTransaction
19 changes: 12 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const axios = require("axios");
const helpers = require('./helper/index')

const { bitcoin: { HD_PATH_MAINNET, HD_PATH_TESTNET }, bitcoin_transaction: { NATIVE_TRANSFER }, bitcoin_network: { MAINNET, TESTNET }} = require('./config/index')
const { SOCHAIN_API_KEY, SOCHAIN_BASE_URL, BLOCKCYPHER_BASE_URL } = require('./constants/index')
const { SOCHAIN_API_KEY, SOCHAIN_BASE_URL } = require('./constants/index')

class KeyringController {

Expand Down Expand Up @@ -92,7 +92,7 @@ class KeyringController {
const headers = { "API-KEY": SOCHAIN_API_KEY}

try {
const signedTransaction = await helpers.signTransaction(from, to, amount, URL, privateKey, satPerByte, headers)
const signedTransaction = await helpers.signTransaction(from, to, amount, URL, privateKey, satPerByte, headers, network)
return { signedTransaction };
} catch (err) {
throw err
Expand Down Expand Up @@ -148,28 +148,33 @@ class KeyringController {
async getFees(rawTransaction) {
const { networkType } = this.store.getState()
const { from } = rawTransaction

try {
const URL = BLOCKCYPHER_BASE_URL + `${networkType === TESTNET.NETWORK ? 'test3' : "main"}/`
const headers = { "API-KEY": SOCHAIN_API_KEY}

const URL = SOCHAIN_BASE_URL + "network_info/" + `${networkType === TESTNET.NETWORK ? 'BTCTEST' : "BTC"}`
const response = await axios({
url : `${URL}`,
method: 'GET',
headers: headers,
});

let blocks = response.data.data['mempool'].blocks.slice(0,3)

let fees = {
slow: {
satPerByte: parseInt(response.data.low_fee_per_kb/1000),
satPerByte: parseInt(blocks[2].median_fee_rate),
},
standard: {
satPerByte: parseInt(response.data.medium_fee_per_kb/1000),
satPerByte: parseInt(blocks[1].median_fee_rate),
},
fast: {
satPerByte: parseInt(response.data.high_fee_per_kb/1000)
satPerByte: parseInt(blocks[0].median_fee_rate)
}
}

// get transaction size
const sochainURL = SOCHAIN_BASE_URL + `unspent_outputs/${networkType === TESTNET.NETWORK ? 'BTCTEST' : "BTC"}/${from}`
const headers = { "API-KEY": SOCHAIN_API_KEY}

let { transactionSize } = await helpers.getTransactionSize(sochainURL, headers)

Expand Down

0 comments on commit fa277c7

Please sign in to comment.