UNPKG

@tatumio/tatum-v1

Version:

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

161 lines 14.1 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.prepareBitcoinSignedOffchainTransaction = exports.signBitcoinOffchainKMSTransaction = exports.sendBitcoinOffchainTransaction = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); // @ts-ignore const bitcore_lib_1 = require("bitcore-lib"); const tatum_1 = require("../connector/tatum"); const model_1 = require("../model"); const wallet_1 = require("../wallet"); const common_1 = require("./common"); const kms_1 = require("./kms"); /** * Send Bitcoin transaction from Tatum Ledger account to the blockchain. This method broadcasts signed transaction to the blockchain. * This operation is irreversible. * @param testnet mainnet or testnet version * @param body content of the transaction to broadcast * @returns transaction id of the transaction in the blockchain or id of the withdrawal, if it was not cancelled automatically */ const sendBitcoinOffchainTransaction = async (testnet, body) => { if (body.signatureId) { return kms_1.offchainTransferBtcKMS(body); } await tatum_1.validateBody(body, model_1.TransferBtcBasedOffchain); const { mnemonic, keyPair, xpub, attr: changeAddress } = body, withdrawal = __rest(body, ["mnemonic", "keyPair", "xpub", "attr"]); if (!withdrawal.fee) { withdrawal.fee = '0.0005'; } const { id, data } = await common_1.offchainStoreWithdrawal(withdrawal); const { amount, address, } = withdrawal; let txData; try { txData = await exports.prepareBitcoinSignedOffchainTransaction(testnet, data, amount, address, mnemonic, keyPair, changeAddress, xpub, withdrawal.multipleAmounts); } catch (e) { console.error(e); await common_1.offchainCancelWithdrawal(id); throw e; } try { return Object.assign(Object.assign({}, await common_1.offchainBroadcast({ txData, withdrawalId: id, currency: model_1.Currency.BTC })), { id }); } catch (e) { console.error(e); try { await common_1.offchainCancelWithdrawal(id); } catch (e1) { console.log(e); return { id }; } throw e; } }; exports.sendBitcoinOffchainTransaction = sendBitcoinOffchainTransaction; /** * Sign Bitcoin pending transaction from Tatum KMS * @param tx pending transaction from KMS * @param mnemonic mnemonic to generate private keys to sign transaction with. * @param testnet mainnet or testnet version * @returns transaction data to be broadcast to blockchain. */ const signBitcoinOffchainKMSTransaction = async (tx, mnemonic, testnet) => { var _a; if (tx.chain !== model_1.Currency.BTC || !tx.withdrawalResponses) { throw Error('Unsupported chain.'); } const builder = new bitcore_lib_1.Transaction(JSON.parse(tx.serializedTransaction)); for (const response of tx.withdrawalResponses) { if (response.vIn === '-1') { continue; } builder.sign(bitcore_lib_1.PrivateKey.fromWIF(await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.BTC, testnet, mnemonic, ((_a = response.address) === null || _a === void 0 ? void 0 : _a.derivationKey) || 0))); } return builder.serialize(true); }; exports.signBitcoinOffchainKMSTransaction = signBitcoinOffchainKMSTransaction; /** * Sign Bitcoin transaction with private keys locally. Nothing is broadcast to the blockchain. * @param testnet mainnet or testnet version * @param data data from Tatum system to prepare transaction from * @param amount amount to send * @param address recipient address, if multiple recipients are present, it should be string separated by ',' * @param mnemonic mnemonic to sign transaction from. mnemonic or keyPair must be present * @param keyPair keyPair to sign transaction from. keyPair or mnemonic must be present * @param changeAddress address to send the rest of the unused coins * @param xpub xpub of the wallet * @param multipleAmounts if multiple recipients are present in the address separated by ',', this should be list of amounts to send * @param signatureId if using KMS, this is signatureId of the wallet representing mnemonic * @returns transaction data to be broadcast to blockchain. */ const prepareBitcoinSignedOffchainTransaction = async (testnet, data, amount, address, mnemonic, keyPair, changeAddress, xpub, multipleAmounts, signatureId) => { var _a; const tx = new bitcore_lib_1.Transaction(); data.forEach((input) => { if (input.vIn !== '-1') { tx.from({ txId: input.vIn, outputIndex: input.vInIndex, script: bitcore_lib_1.Script.fromAddress(input.address.address).toString(), satoshis: Number(new bignumber_js_1.default(input.amount).multipliedBy(100000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR)) }); } }); const lastVin = data.find(d => d.vIn === '-1'); if (multipleAmounts === null || multipleAmounts === void 0 ? void 0 : multipleAmounts.length) { for (const [i, multipleAmount] of multipleAmounts.entries()) { tx.to(address.split(',')[i], Number(new bignumber_js_1.default(multipleAmount).multipliedBy(100000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR))); } } else { tx.to(address, Number(new bignumber_js_1.default(amount).multipliedBy(100000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR))); } if (new bignumber_js_1.default(lastVin.amount).isGreaterThan(0)) { if (xpub) { tx.to(wallet_1.generateAddressFromXPub(model_1.Currency.BTC, testnet, xpub, 0), Number(new bignumber_js_1.default(lastVin.amount).multipliedBy(100000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR))); } else if (changeAddress) { tx.to(changeAddress, Number(new bignumber_js_1.default(lastVin.amount).multipliedBy(100000000).toFixed(8, bignumber_js_1.default.ROUND_FLOOR))); } else { throw new Error('Impossible to prepare transaction. Either mnemonic or keyPair and attr must be present.'); } } if (signatureId) { return JSON.stringify(tx); } for (const input of data) { // when there is no address field present, input is pool transfer to 0 if (input.vIn === '-1') { continue; } if (mnemonic) { const derivationKey = ((_a = input.address) === null || _a === void 0 ? void 0 : _a.derivationKey) || 0; tx.sign(bitcore_lib_1.PrivateKey.fromWIF(await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.BTC, testnet, mnemonic, derivationKey))); } else if (keyPair) { const { privateKey } = keyPair.find(k => k.address === input.address.address); tx.sign(bitcore_lib_1.PrivateKey.fromWIF(privateKey)); } else { throw new Error('Impossible to prepare transaction. Either mnemonic or keyPair and attr must be present.'); } } return tx.serialize(true); }; exports.prepareBitcoinSignedOffchainTransaction = prepareBitcoinSignedOffchainTransaction; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Y29pbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9vZmZjaGFpbi9iaXRjb2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0VBQW9DO0FBQ3BDLGFBQWE7QUFDYiw2Q0FBMkQ7QUFDM0QsOENBQStDO0FBQy9DLG9DQUE0RztBQUM1RyxzQ0FBaUY7QUFDakYscUNBQTZGO0FBQzdGLCtCQUE4QztBQUU5Qzs7Ozs7O0dBTUc7QUFDSSxNQUFNLDhCQUE4QixHQUFHLEtBQUssRUFBRSxPQUFnQixFQUFFLElBQThCLEVBQUUsRUFBRTtJQUNyRyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDbEIsT0FBTyw0QkFBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQTtLQUN0QztJQUNELE1BQU0sb0JBQVksQ0FBQyxJQUFJLEVBQUUsZ0NBQXdCLENBQUMsQ0FBQTtJQUNsRCxNQUFNLEVBQ0YsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLGFBQWEsS0FDNUMsSUFBSSxFQUQ2QyxVQUFVLFVBQzNELElBQUksRUFGRix1Q0FFTCxDQUFPLENBQUE7SUFDUixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNqQixVQUFVLENBQUMsR0FBRyxHQUFHLFFBQVEsQ0FBQTtLQUM1QjtJQUNELE1BQU0sRUFBQyxFQUFFLEVBQUUsSUFBSSxFQUFDLEdBQUcsTUFBTSxnQ0FBdUIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUM1RCxNQUFNLEVBQ0YsTUFBTSxFQUFFLE9BQU8sR0FDbEIsR0FBRyxVQUFVLENBQUE7SUFDZCxJQUFJLE1BQU0sQ0FBQTtJQUNWLElBQUk7UUFDQSxNQUFNLEdBQUcsTUFBTSwrQ0FBdUMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQTtLQUM3SjtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNoQixNQUFNLGlDQUF3QixDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sQ0FBQyxDQUFBO0tBQ1Y7SUFDRCxJQUFJO1FBQ0EsdUNBQVcsTUFBTSwwQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxnQkFBUSxDQUFDLEdBQUcsRUFBQyxDQUFDLEtBQUUsRUFBRSxJQUFDO0tBQzlGO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDUixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ2hCLElBQUk7WUFDQSxNQUFNLGlDQUF3QixDQUFDLEVBQUUsQ0FBQyxDQUFBO1NBQ3JDO1FBQUMsT0FBTyxFQUFFLEVBQUU7WUFDVCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2QsT0FBTyxFQUFDLEVBQUUsRUFBQyxDQUFBO1NBQ2Q7UUFDRCxNQUFNLENBQUMsQ0FBQTtLQUNWO0FBQ0wsQ0FBQyxDQUFBO0FBbkNZLFFBQUEsOEJBQThCLGtDQW1DMUM7QUFFRDs7Ozs7O0dBTUc7QUFDSSxNQUFNLGlDQUFpQyxHQUFHLEtBQUssRUFBRSxFQUFrQixFQUFFLFFBQWdCLEVBQUUsT0FBZ0IsRUFBRSxFQUFFOztJQUM5RyxJQUFJLEVBQUUsQ0FBQyxLQUFLLEtBQUssZ0JBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEVBQUU7UUFDdEQsTUFBTSxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtLQUNwQztJQUNELE1BQU0sT0FBTyxHQUFHLElBQUkseUJBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUE7SUFDckUsS0FBSyxNQUFNLFFBQVEsSUFBSSxFQUFFLENBQUMsbUJBQW1CLEVBQUU7UUFDM0MsSUFBSSxRQUFRLENBQUMsR0FBRyxLQUFLLElBQUksRUFBRTtZQUN2QixTQUFRO1NBQ1g7UUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLHdCQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sdUNBQThCLENBQUMsZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFBLE1BQUEsUUFBUSxDQUFDLE9BQU8sMENBQUUsYUFBYSxLQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtLQUNoSjtJQUNELE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUNsQyxDQUFDLENBQUE7QUFaWSxRQUFBLGlDQUFpQyxxQ0FZN0M7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0ksTUFBTSx1Q0FBdUMsR0FDaEQsS0FBSyxFQUFFLE9BQWdCLEVBQUUsSUFBOEIsRUFBRSxNQUFjLEVBQUUsT0FBZSxFQUFFLFFBQWlCLEVBQUUsT0FBbUIsRUFDekgsYUFBc0IsRUFBRSxJQUFhLEVBQUUsZUFBMEIsRUFBRSxXQUFvQixFQUFFLEVBQUU7O0lBQzlGLE1BQU0sRUFBRSxHQUFHLElBQUkseUJBQVcsRUFBRSxDQUFBO0lBRTVCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNuQixJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssSUFBSSxFQUFFO1lBQ3BCLEVBQUUsQ0FBQyxJQUFJLENBQUM7Z0JBQ0osSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHO2dCQUNmLFdBQVcsRUFBRSxLQUFLLENBQUMsUUFBUTtnQkFDM0IsTUFBTSxFQUFFLG9CQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFO2dCQUM1RCxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksc0JBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsc0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQzthQUMxRyxDQUFDLENBQUE7U0FDTDtJQUNMLENBQUMsQ0FBQyxDQUFBO0lBRUYsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssSUFBSSxDQUEyQixDQUFBO0lBQ3hFLElBQUksZUFBZSxhQUFmLGVBQWUsdUJBQWYsZUFBZSxDQUFFLE1BQU0sRUFBRTtRQUN6QixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsY0FBYyxDQUFDLElBQUksZUFBZSxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3pELEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxzQkFBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLHNCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ2hJO0tBQ0o7U0FBTTtRQUNILEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJLHNCQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsc0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUE7S0FDMUc7SUFDRCxJQUFJLElBQUksc0JBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ2hELElBQUksSUFBSSxFQUFFO1lBQ04sRUFBRSxDQUFDLEVBQUUsQ0FBQyxnQ0FBdUIsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUN6RCxNQUFNLENBQUMsSUFBSSxzQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxzQkFBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtTQUN2RzthQUFNLElBQUksYUFBYSxFQUFFO1lBQ3RCLEVBQUUsQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxJQUFJLHNCQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLHNCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ3hIO2FBQU07WUFDSCxNQUFNLElBQUksS0FBSyxDQUFDLHlGQUF5RixDQUFDLENBQUE7U0FDN0c7S0FDSjtJQUVELElBQUksV0FBVyxFQUFFO1FBQ2IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0tBQzVCO0lBRUQsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLEVBQUU7UUFDdEIsc0VBQXNFO1FBQ3RFLElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDcEIsU0FBUTtTQUNYO1FBQ0QsSUFBSSxRQUFRLEVBQUU7WUFDVixNQUFNLGFBQWEsR0FBRyxDQUFBLE1BQUEsS0FBSyxDQUFDLE9BQU8sMENBQUUsYUFBYSxLQUFJLENBQUMsQ0FBQTtZQUN2RCxFQUFFLENBQUMsSUFBSSxDQUFDLHdCQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sdUNBQThCLENBQUMsZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUE7U0FDcEg7YUFBTSxJQUFJLE9BQU8sRUFBRTtZQUNoQixNQUFNLEVBQUMsVUFBVSxFQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQVksQ0FBQTtZQUN0RixFQUFFLENBQUMsSUFBSSxDQUFDLHdCQUFVLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUE7U0FDMUM7YUFBTTtZQUNILE1BQU0sSUFBSSxLQUFLLENBQUMseUZBQXlGLENBQUMsQ0FBQTtTQUM3RztLQUNKO0lBRUQsT0FBTyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFBO0FBQzdCLENBQUMsQ0FBQTtBQXhEUSxRQUFBLHVDQUF1QywyQ0F3RC9DIn0=