UNPKG

@tatumio/tatum-v1

Version:

Tatum API client allows browsers and Node.js clients to interact with Tatum API.

215 lines 23.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.adaToLovelace = exports.lovelaceToAda = exports.signTransaction = exports.processFeeAndRest = exports.makeWitness = exports.createWitnesses = exports.initTransactionBuilder = exports.addInput = exports.addOutputAda = exports.addOutputLovelace = exports.addUtxoInputs = exports.addInputsPrivateKeys = exports.addAddressInputsWithoutPrivateKey = exports.addAddressInputs = exports.addInputs = exports.addChangeIfNeeded = exports.addFee = exports.addOutputs = exports.signAdaKMSTransaction = exports.sendAdaTransaction = exports.prepareAdaTransaction = void 0; const cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const ada_1 = require("../blockchain/ada"); const tatum_1 = require("../connector/tatum"); const model_1 = require("../model"); /** * Prepare a signed Ada transaction with the private key locally. Nothing is broadcasted to the blockchain. * @param transferAdaBlockchain content of the transaction to prepare. * @returns raw transaction data in hex, to be broadcasted to blockchain. */ const prepareAdaTransaction = async (transferAdaBlockchain) => { await tatum_1.validateBody(transferAdaBlockchain, model_1.TransferAdaBlockchain); const txBuilder = await exports.initTransactionBuilder(); const { to } = transferAdaBlockchain; const { privateKeysToSign, amount: fromAmount } = await exports.addInputs(txBuilder, transferAdaBlockchain); const toAmount = exports.addOutputs(txBuilder, to); await exports.processFeeAndRest(txBuilder, fromAmount, toAmount, transferAdaBlockchain); return exports.signTransaction(txBuilder, transferAdaBlockchain, privateKeysToSign); }; exports.prepareAdaTransaction = prepareAdaTransaction; /** * Send Ada transaction to the blockchain. This method broadcasts signed transaction to the blockchain. * This operation is irreversible. * @param body content of the transaction to broadcast * @returns transaction id of the transaction in the blockchain */ const sendAdaTransaction = async (body) => { return ada_1.adaBroadcast(await exports.prepareAdaTransaction(body)); }; exports.sendAdaTransaction = sendAdaTransaction; /** * Sign Ada pending transaction from Tatum KMS * @param tx pending transaction from KMS * @param privateKeys private keys to sign transaction with. * @returns transaction data to be broadcast to blockchain. */ const signAdaKMSTransaction = async (tx, privateKeys) => { if (tx.chain !== model_1.Currency.ADA) { throw Error('Unsupported chain.'); } const transferAdaBlockchain = JSON.parse(tx.serializedTransaction).txData; const txBuilder = await exports.initTransactionBuilder(); const { to } = transferAdaBlockchain; const { amount: fromAmount } = await exports.addInputs(txBuilder, transferAdaBlockchain); const toAmount = exports.addOutputs(txBuilder, to); await exports.processFeeAndRest(txBuilder, fromAmount, toAmount, transferAdaBlockchain); const txBody = txBuilder.build(); const txHash = cardano_serialization_lib_nodejs_1.hash_transaction(txBody); const vKeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new(); for (const key of privateKeys) { exports.makeWitness(key, txHash, vKeyWitnesses); } const witnesses = cardano_serialization_lib_nodejs_1.TransactionWitnessSet.new(); witnesses.set_vkeys(vKeyWitnesses); return Buffer.from(cardano_serialization_lib_nodejs_1.Transaction.new(txBody, witnesses).to_bytes()).toString('hex'); }; exports.signAdaKMSTransaction = signAdaKMSTransaction; const addOutputs = (transactionBuilder, tos) => { let amount = new bignumber_js_1.default(0); for (const to of tos) { const valueAdded = exports.addOutputAda(transactionBuilder, to.address, to.value); amount = amount.plus(valueAdded); } return amount; }; exports.addOutputs = addOutputs; const addFee = (txBuilder, feeInLovelace) => { txBuilder.set_fee(cardano_serialization_lib_nodejs_1.BigNum.from_str(feeInLovelace.toString())); }; exports.addFee = addFee; const addChangeIfNeeded = (txBuilder, changeAddress) => { txBuilder.add_change_if_needed(cardano_serialization_lib_nodejs_1.Address.from_bech32(changeAddress)); }; exports.addChangeIfNeeded = addChangeIfNeeded; const addInputs = async (transactionBuilder, transferAdaBlockchain) => { const { fromUTXO, fromAddress } = transferAdaBlockchain; if (fromAddress) { return exports.addAddressInputs(transactionBuilder, fromAddress); } if (fromUTXO) { return exports.addUtxoInputs(transactionBuilder, fromUTXO); } throw new Error('Field fromAddress or fromUTXO is not filled.'); }; exports.addInputs = addInputs; const addAddressInputs = async (transactionBuilder, fromAddresses) => { const amount = await exports.addAddressInputsWithoutPrivateKey(transactionBuilder, fromAddresses); const privateKeysToSign = await exports.addInputsPrivateKeys(fromAddresses); return { amount, privateKeysToSign }; }; exports.addAddressInputs = addAddressInputs; const addAddressInputsWithoutPrivateKey = async (transactionBuilder, fromAddresses) => { let amount = new bignumber_js_1.default(0); for (const fromAddress of fromAddresses) { const { address } = fromAddress; const utxos = await ada_1.adaGetUtxos(address); for (const utxo of utxos) { amount = amount.plus(utxo.value); exports.addInput(transactionBuilder, utxo, address); } } return amount; }; exports.addAddressInputsWithoutPrivateKey = addAddressInputsWithoutPrivateKey; const addInputsPrivateKeys = async (froms) => { const privateKeysToSign = []; for (const from of froms) { privateKeysToSign.push(from.signatureId || from.privateKey); } return privateKeysToSign; }; exports.addInputsPrivateKeys = addInputsPrivateKeys; const addUtxoInputs = async (transactionBuilder, fromUTXOs) => { let amount = new bignumber_js_1.default(0); const privateKeysToSign = []; for (const utxo of fromUTXOs) { const transaction = await ada_1.adaGetTransaction(utxo.txHash); const output = transaction.outputs.find(output => output.index === utxo.index); if (output) { const value = output.value; amount = amount.plus(value); exports.addInput(transactionBuilder, Object.assign({ value }, utxo), output.address); privateKeysToSign.push(utxo.signatureId || utxo.privateKey); } } return { amount, privateKeysToSign }; }; exports.addUtxoInputs = addUtxoInputs; const addOutputLovelace = (transactionBuilder, address, amount) => { transactionBuilder.add_output(cardano_serialization_lib_nodejs_1.TransactionOutput.new(cardano_serialization_lib_nodejs_1.Address.from_bech32(address), cardano_serialization_lib_nodejs_1.Value.new(cardano_serialization_lib_nodejs_1.BigNum.from_str(amount)))); }; exports.addOutputLovelace = addOutputLovelace; const addOutputAda = (transactionBuilder, address, amount) => { const amountLovelace = exports.adaToLovelace(amount); exports.addOutputLovelace(transactionBuilder, address, amountLovelace); return amountLovelace; }; exports.addOutputAda = addOutputAda; const addInput = (transactionBuilder, utxo, address) => { transactionBuilder.add_input(cardano_serialization_lib_nodejs_1.Address.from_bech32(address), cardano_serialization_lib_nodejs_1.TransactionInput.new(cardano_serialization_lib_nodejs_1.TransactionHash.from_bytes(Buffer.from(utxo.txHash, 'hex')), utxo.index), cardano_serialization_lib_nodejs_1.Value.new(cardano_serialization_lib_nodejs_1.BigNum.from_str(utxo.value))); }; exports.addInput = addInput; const initTransactionBuilder = async () => { const txBuilder = cardano_serialization_lib_nodejs_1.TransactionBuilder.new(cardano_serialization_lib_nodejs_1.LinearFee.new(cardano_serialization_lib_nodejs_1.BigNum.from_str('44'), cardano_serialization_lib_nodejs_1.BigNum.from_str('155381')), cardano_serialization_lib_nodejs_1.BigNum.from_str('1000000'), cardano_serialization_lib_nodejs_1.BigNum.from_str('500000000'), cardano_serialization_lib_nodejs_1.BigNum.from_str('2000000')); const { tip: { slotNo } } = await ada_1.adaGetBlockChainInfo(); txBuilder.set_ttl(slotNo + 50000); return txBuilder; }; exports.initTransactionBuilder = initTransactionBuilder; const createWitnesses = (transactionBody, transferAdaBlockchain) => { const { fromAddress, fromUTXO } = transferAdaBlockchain; const txHash = cardano_serialization_lib_nodejs_1.hash_transaction(transactionBody); const vKeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new(); if (fromAddress) { for (const address of fromAddress) { if (address.privateKey) { exports.makeWitness(address.privateKey, txHash, vKeyWitnesses); } } } else if (fromUTXO) { for (const utxo of fromUTXO) { if (utxo.privateKey) { exports.makeWitness(utxo.privateKey, txHash, vKeyWitnesses); } } } else { throw new Error('No private key for witness found.'); } const witnesses = cardano_serialization_lib_nodejs_1.TransactionWitnessSet.new(); witnesses.set_vkeys(vKeyWitnesses); return witnesses; }; exports.createWitnesses = createWitnesses; const makeWitness = (privateKey, txHash, vKeyWitnesses) => { const privateKeyCardano = cardano_serialization_lib_nodejs_1.Bip32PrivateKey.from_128_xprv(Buffer.from(privateKey, 'hex')).to_raw_key(); vKeyWitnesses.add(cardano_serialization_lib_nodejs_1.make_vkey_witness(txHash, privateKeyCardano)); }; exports.makeWitness = makeWitness; const processFeeAndRest = async (transactionBuilder, fromAmountInLovelace, toAmountInLovelace, transferAdaBlockchain) => { const feeInLovelace = new bignumber_js_1.default(exports.adaToLovelace((transferAdaBlockchain === null || transferAdaBlockchain === void 0 ? void 0 : transferAdaBlockchain.fee) || 0)); const changeAddress = transferAdaBlockchain.changeAddress; if (feeInLovelace.isEqualTo(0)) { exports.addChangeIfNeeded(transactionBuilder, changeAddress); } else { const changeInLovelace = fromAmountInLovelace.minus(toAmountInLovelace).minus(feeInLovelace); if (changeInLovelace.gt(0)) exports.addOutputLovelace(transactionBuilder, changeAddress, changeInLovelace.toString()); exports.addFee(transactionBuilder, feeInLovelace); } }; exports.processFeeAndRest = processFeeAndRest; const signTransaction = (transactionBuilder, transferAdaBlockchain, privateKeysToSign) => { const txBody = transactionBuilder.build(); const { fromAddress, fromUTXO } = transferAdaBlockchain; if ((fromAddress && fromAddress[0].signatureId) || (fromUTXO && fromUTXO[0].signatureId)) { return JSON.stringify({ txData: transferAdaBlockchain, privateKeysToSign }); } const witnesses = exports.createWitnesses(txBody, transferAdaBlockchain); return Buffer.from(cardano_serialization_lib_nodejs_1.Transaction.new(txBody, witnesses).to_bytes()).toString('hex'); }; exports.signTransaction = signTransaction; const lovelaceToAda = (lovelace) => new bignumber_js_1.default(lovelace).dividedBy(1000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR).toString(); exports.lovelaceToAda = lovelaceToAda; const adaToLovelace = (ada) => new bignumber_js_1.default(ada).times(1000000).toString(); exports.adaToLovelace = adaToLovelace; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zYWN0aW9uL2FkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwrRkFNaUQ7QUFDakQsZ0VBQW9DO0FBQ3BDLDJDQUFzRztBQUN0Ryw4Q0FBaUQ7QUFDakQsb0NBQThHO0FBRTlHOzs7O0dBSUc7QUFDSSxNQUFNLHFCQUFxQixHQUFHLEtBQUssRUFBRSxxQkFBNEMsRUFBRSxFQUFFO0lBQzFGLE1BQU0sb0JBQVksQ0FBQyxxQkFBcUIsRUFBRSw2QkFBcUIsQ0FBQyxDQUFBO0lBQ2hFLE1BQU0sU0FBUyxHQUFHLE1BQU0sOEJBQXNCLEVBQUUsQ0FBQTtJQUNoRCxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcscUJBQXFCLENBQUE7SUFFcEMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxNQUFNLGlCQUFTLENBQUMsU0FBUyxFQUFFLHFCQUFxQixDQUFDLENBQUE7SUFDbkcsTUFBTSxRQUFRLEdBQUcsa0JBQVUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDMUMsTUFBTSx5QkFBaUIsQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxxQkFBcUIsQ0FBQyxDQUFBO0lBRS9FLE9BQU8sdUJBQWUsQ0FBQyxTQUFTLEVBQUUscUJBQXFCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQTtBQUM3RSxDQUFDLENBQUE7QUFWWSxRQUFBLHFCQUFxQix5QkFVakM7QUFFRDs7Ozs7R0FLRztBQUNJLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxFQUFFLElBQTJCLEVBQUUsRUFBRTtJQUN0RSxPQUFPLGtCQUFZLENBQUMsTUFBTSw2QkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO0FBQ3hELENBQUMsQ0FBQTtBQUZZLFFBQUEsa0JBQWtCLHNCQUU5QjtBQUVEOzs7OztHQUtHO0FBQ0ksTUFBTSxxQkFBcUIs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