const LibCash = require('@developers.cash/libcash-js')
// LibCash instance
const libCash = new LibCash()
/**
* Utility functions
*/
class Utils {
static buildOutput (output) {
const built = {
amount: output.amountNative || 0
}
// If address is set, create P2PKH script
if (output.address) {
const address = libCash.Address.toHash160(output.address)
const type = libCash.Address.detectAddressType(output.address)
if (type === 'p2sh') {
built.script = libCash.Script.fromASM(`OP_HASH160 ${address} OP_EQUAL`)
} else if (type === 'p2pkh') {
built.script = libCash.Script.fromASM(`OP_DUP OP_HASH160 ${address} OP_EQUALVERIFY OP_CHECKSIG`)
} else {
throw new Error('Unsupported address type')
}
} else if (output.script) { // If a script is set, convert it to buffer
built.script = libCash.Script.fromASM(output.script)
} else { // Otherwise, throw an error
throw new Error('Output did not contain address or script')
}
return built
}
static buildOutputs (outputs) {
const built = []
for (const output of outputs) {
built.push(Utils.buildOutput(output))
}
return built
}
/**
* Verify that transaction contains outputs specified in invoice
* @param invoice The Invoice
* @param transaction Raw Transaction Hex
*/
static matchesInvoice (invoiceDB, transactions) {
// Build outputs so that they are in script format
const invoiceOutputs = Utils.buildOutputs(invoiceDB.outputs)
// Iterate through the transactions and their outputs
for (const transaction of transactions) {
let tx = ''
// Convert string to buffer (JSON Payment Proto will give us string)
if (typeof transaction === 'string') {
tx = Buffer.from(transaction, 'hex')
}
// HACK Bitcore's BIP70 wraps buffers in its own format
// We should try to move away from Bitcore in future.
if (typeof transaction === 'object') {
tx = transaction.toBuffer()
}
// Decode the transaction
tx = libCash.Transaction.fromBuffer(tx)
// Iterate through each output
for (const out of tx.outs) {
for (let i = invoiceOutputs.length - 1; i >= 0; i--) {
const invoiceOut = invoiceOutputs[i]
if (out.value === invoiceOut.amount && out.script.equals(invoiceOut.script)) {
invoiceOutputs.splice(i, 1)
}
}
}
}
console.log(invoiceOutputs)
// If all outputs have been given, return true
return !invoiceOutputs.length
}
}
module.exports = Utils