@tatumio/tatum-v1
Version:
Tatum API client allows browsers and Node.js clients to interact with Tatum API.
169 lines • 15.6 kB
JavaScript
;
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.signAdaOffchainKMSTransaction = exports.sendAdaOffchainTransaction = void 0;
const cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const tatum_1 = require("../connector/tatum");
const model_1 = require("../model");
const transaction_1 = require("../transaction");
const wallet_1 = require("../wallet");
const common_1 = require("./common");
const kms_1 = require("./kms");
/**
* Send Ada 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 sendAdaOffchainTransaction = async (testnet, body) => {
if (body.signatureId) {
return kms_1.offchainTransferAdaKMS(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 = '1';
}
const { id, data } = await common_1.offchainStoreWithdrawal(withdrawal);
const { amount, address, } = withdrawal;
let txData;
try {
txData = await prepareAdaSignedOffchainTransaction(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.ADA })), { id });
}
catch (e) {
console.error(e);
try {
await common_1.offchainCancelWithdrawal(id);
}
catch (e1) {
console.log(e);
return { id };
}
throw e;
}
};
exports.sendAdaOffchainTransaction = sendAdaOffchainTransaction;
const prepareAdaSignedOffchainTransaction = async (testnet, data, amount, address, mnemonic, keyPair, changeAddress, xpub, multipleAmounts, signatureId) => {
var _a;
const txBuilder = await transaction_1.initTransactionBuilder();
const fromAddress = data.filter(input => input.address).map(input => ({ address: input.address.address }));
await transaction_1.addAddressInputsWithoutPrivateKey(txBuilder, fromAddress);
addOffchainInputs(txBuilder, data);
if (multipleAmounts === null || multipleAmounts === void 0 ? void 0 : multipleAmounts.length) {
for (const [i, multipleAmount] of multipleAmounts.entries()) {
transaction_1.addOutputAda(txBuilder, address.split(',')[i], multipleAmount);
}
}
else {
transaction_1.addOutputAda(txBuilder, address, amount);
}
const lastVin = data.find(d => d.vIn === '-1');
if (new bignumber_js_1.default(lastVin.amount).isGreaterThan(0)) {
if (xpub) {
const zeroAddress = await wallet_1.generateAddressFromXPub(model_1.Currency.ADA, testnet, xpub, 0);
transaction_1.addOutputAda(txBuilder, zeroAddress, lastVin.amount);
}
else if (changeAddress) {
transaction_1.addOutputAda(txBuilder, changeAddress, lastVin.amount);
}
else {
throw new Error('Impossible to prepare transaction. Either xpub or keyPair and attr must be present.');
}
}
const lovelaceFee = transaction_1.adaToLovelace(1);
txBuilder.set_fee(cardano_serialization_lib_nodejs_1.BigNum.from_str(lovelaceFee));
const txBody = txBuilder.build();
if (signatureId) {
return JSON.stringify({ txData: txBody.to_bytes().toString() });
}
const vKeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new();
const txHash = cardano_serialization_lib_nodejs_1.hash_transaction(txBody);
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;
const privateKey = await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.ADA, testnet, mnemonic, derivationKey);
transaction_1.makeWitness(privateKey, txHash, vKeyWitnesses);
}
else if (keyPair) {
const { privateKey } = keyPair.find(k => k.address === input.address.address);
transaction_1.makeWitness(privateKey, txHash, vKeyWitnesses);
}
else {
throw new Error('Impossible to prepare transaction. Either mnemonic or keyPair and attr must be present.');
}
}
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');
};
const addOffchainInputs = (transactionBuilder, inputs) => {
var _a;
let amount = new bignumber_js_1.default(0);
for (const input of inputs) {
if (input.vIn !== '-1' && input.amount && input.vInIndex !== undefined && ((_a = input.address) === null || _a === void 0 ? void 0 : _a.address)) {
transaction_1.addInput(transactionBuilder, {
value: transaction_1.adaToLovelace(input.amount),
index: input.vInIndex,
txHash: input.vIn,
}, input.address.address);
amount = amount.plus(input.amount);
}
}
return amount;
};
/**
* Sign Ada 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 signAdaOffchainKMSTransaction = async (tx, mnemonic, testnet) => {
var _a;
if (tx.chain !== model_1.Currency.ADA || !tx.withdrawalResponses) {
throw Error('Unsupported chain.');
}
const txData = JSON.parse(tx.serializedTransaction).txData;
const transactionBody = cardano_serialization_lib_nodejs_1.TransactionBody.from_bytes(Uint8Array.from(txData.split(',')));
const txHash = cardano_serialization_lib_nodejs_1.hash_transaction(transactionBody);
const vKeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new();
for (const response of tx.withdrawalResponses) {
if (response.vIn === '-1') {
continue;
}
const privateKey = await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.ADA, testnet, mnemonic, ((_a = response.address) === null || _a === void 0 ? void 0 : _a.derivationKey) || 0);
transaction_1.makeWitness(privateKey, 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(transactionBody, witnesses).to_bytes()).toString('hex');
};
exports.signAdaOffchainKMSTransaction = signAdaOffchainKMSTransaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL29mZmNoYWluL2FkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtGQVFrRDtBQUNsRCxnRUFBcUM7QUFDckMsOENBQWtEO0FBQ2xELG9DQUErRztBQUMvRyxnREFPd0I7QUFDeEIsc0NBQW9GO0FBQ3BGLHFDQUFnRztBQUNoRywrQkFBOEM7QUFFOUM7Ozs7OztHQU1HO0FBQ0ksTUFBTSwwQkFBMEIsR0FBRyxLQUFLLEVBQUUsT0FBZ0IsRUFBRSxJQUE4QixFQUFFLEVBQUU7SUFDakcsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1FBQ2xCLE9BQU8sNEJBQXNCLENBQUMsSUFBSSxDQUFDLENBQUE7S0FDdEM7SUFDRCxNQUFNLG9CQUFZLENBQUMsSUFBSSxFQUFFLGdDQUF3QixDQUFDLENBQUM7SUFDbkQsTUFBTSxFQUNGLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxhQUFhLEtBQzVDLElBQUksRUFENkMsVUFBVSxVQUMzRCxJQUFJLEVBRkYsdUNBRUwsQ0FBTyxDQUFBO0lBQ1IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDakIsVUFBVSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUE7S0FDdkI7SUFDRCxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sZ0NBQXVCLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDOUQsTUFBTSxFQUNGLE1BQU0sRUFBRSxPQUFPLEdBQ2xCLEdBQUcsVUFBVSxDQUFBO0lBQ2QsSUFBSSxNQUFNLENBQUE7SUFDVixJQUFJO1FBQ0EsTUFBTSxHQUFHLE1BQU0sbUNBQW1DLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsZUFB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