@stricahq/typhonjs
Version:
Pure JS Cardano Wallet library
721 lines (720 loc) • 33.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
const buffer_1 = require("buffer");
const cbors = __importStar(require("@stricahq/cbors"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const lodash_1 = __importDefault(require("lodash"));
const helpers_1 = require("../utils/helpers");
const types_1 = require("../types");
const encoder_1 = require("../utils/encoder");
const crypto_1 = require("../utils/crypto");
const utils_1 = require("../utils/utils");
const transactionBuilder_1 = __importDefault(require("./helpers/transactionBuilder"));
const paymentTransaction_1 = require("./helpers/paymentTransaction");
const internal_types_1 = require("../internal-types");
class Transaction {
constructor({ protocolParams }) {
this.inputs = [];
this.referenceInputs = [];
this.outputs = [];
this.certificates = [];
this.withdrawals = [];
this.requiredWitnesses = new Map();
this.requiredNativeScriptWitnesses = new Map();
this.fee = new bignumber_js_1.default(5000000);
this.witnesses = [];
this.plutusScriptMap = new Map();
this.nativeScriptList = [];
this.collaterals = [];
this.requiredSigners = new Map();
this.plutusDataList = [];
this._isPlutusV1Transaction = false;
this._isPlutusV2Transaction = false;
this._isPlutusV3Transaction = false;
this.mints = [];
this.votingProcedures = [];
this.proposalProcedures = [];
this._protocolParams = protocolParams;
}
get protocolParams() {
return this._protocolParams;
}
getTTL() {
return this.ttl;
}
setTTL(ttl) {
this.ttl = ttl;
}
getValidityIntervalStart() {
return this.validityIntervalStart;
}
setValidityIntervalStart(validityIntervalStart) {
this.validityIntervalStart = validityIntervalStart;
}
addInput(input) {
if (input.address.paymentCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(input.address.paymentCredential.hash.toString("hex"), input.address.paymentCredential.bipPath);
}
else if (input.address.paymentCredential.type === types_1.HashType.SCRIPT) {
if (input.address.paymentCredential.plutusScript) {
this.plutusScriptMap.set(input.address.paymentCredential.plutusScript.cborHex, input.address.paymentCredential.plutusScript.type);
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV1) {
this._isPlutusV1Transaction = true;
}
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV2) {
this._isPlutusV2Transaction = true;
}
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV3) {
this._isPlutusV3Transaction = true;
}
}
else if (input.address.paymentCredential.nativeScript) {
const nativeScript = input.address.paymentCredential.nativeScript;
const pubKeyHashList = (0, helpers_1.getPubKeyHashListFromNativeScript)(nativeScript);
for (const pkh of pubKeyHashList) {
this.requiredNativeScriptWitnesses.set(pkh, undefined);
}
this.nativeScriptList.push(nativeScript);
}
}
if (input.plutusData) {
this.plutusDataList.push(input.plutusData);
}
this.inputs.push(input);
}
addReferenceInput(input) {
if (input.address &&
input.address.paymentCredential.type === types_1.HashType.SCRIPT &&
input.address.paymentCredential.plutusScript) {
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV1) {
this._isPlutusV1Transaction = true;
}
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV2) {
this._isPlutusV2Transaction = true;
}
if (input.address.paymentCredential.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV3) {
this._isPlutusV3Transaction = true;
}
}
this.referenceInputs.push(input);
}
addRequiredSigner(credential) {
this.requiredSigners.set(credential.hash.toString("hex"), credential.bipPath);
}
addCollateral(input) {
if (input.address.paymentCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(input.address.paymentCredential.hash.toString("hex"), input.address.paymentCredential.bipPath);
}
this.collaterals.push(input);
}
addMint(mint) {
this.mints.push(mint);
if (mint.plutusScript) {
this.plutusScriptMap.set(mint.plutusScript.cborHex, mint.plutusScript.type);
if (mint.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV1) {
this._isPlutusV1Transaction = true;
}
if (mint.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV2) {
this._isPlutusV2Transaction = true;
}
if (mint.plutusScript.type === types_1.PlutusScriptType.PlutusScriptV3) {
this._isPlutusV3Transaction = true;
}
}
else if (mint.nativeScript) {
// used to guesstimate fees by required pkh witnesses inside nativescript
// this flow can be improved in future version
const pubKeyHashList = (0, helpers_1.getPubKeyHashListFromNativeScript)(mint.nativeScript);
for (const pkh of pubKeyHashList) {
this.requiredNativeScriptWitnesses.set(pkh, undefined);
}
this.nativeScriptList.push(mint.nativeScript);
}
}
/**
* The method will add a certificate to the transaction to be included in cbor
* This method will automatically scan and include each unique required witnesses in the map
* to help sign the transaction
* @param certificate a certificate to include in the transaction
*/
addCertificate(certificate) {
switch (certificate.type) {
case types_1.CertificateType.STAKE_DELEGATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_REGISTRATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_DE_REGISTRATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_KEY_REGISTRATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_KEY_DE_REGISTRATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.VOTE_DELEGATION: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_VOTE_DELEG: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_REG_DELEG: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.VOTE_REG_DELEG: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.STAKE_VOTE_REG_DELEG: {
if (certificate.cert.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.stakeCredential.hash.toString("hex"), certificate.cert.stakeCredential.bipPath);
}
break;
}
case types_1.CertificateType.DREP_REG: {
if (certificate.cert.dRepCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.dRepCredential.hash.toString("hex"), certificate.cert.dRepCredential.bipPath);
}
break;
}
case types_1.CertificateType.DREP_DE_REG: {
if (certificate.cert.dRepCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.dRepCredential.hash.toString("hex"), certificate.cert.dRepCredential.bipPath);
}
break;
}
case types_1.CertificateType.DREP_UPDATE: {
if (certificate.cert.dRepCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(certificate.cert.dRepCredential.hash.toString("hex"), certificate.cert.dRepCredential.bipPath);
}
break;
}
default:
break;
}
this.certificates.push(certificate);
}
addOutput(output) {
const uOutput = output;
uOutput.tokens = (0, helpers_1.sortTokens)(uOutput.tokens);
this.outputs.push(uOutput);
if (uOutput.plutusData) {
this.plutusDataList.push(uOutput.plutusData);
}
}
addWithdrawal(withdrawal) {
if (withdrawal.rewardAccount.stakeCredential.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(withdrawal.rewardAccount.stakeCredential.hash.toString("hex"), withdrawal.rewardAccount.stakeCredential.bipPath);
}
this.withdrawals.push(withdrawal);
}
// add voting procedure to the transaction, used to vote on a governance proposal
addVotingProcedure(votingProcedure) {
if (votingProcedure.voter.key.type === types_1.HashType.ADDRESS) {
this.requiredWitnesses.set(votingProcedure.voter.key.hash.toString("hex"), votingProcedure.voter.key.bipPath);
}
this.votingProcedures.push(votingProcedure);
}
addProposalProcedure(proposalProcedure) {
// no additional signatures required to submit a governance action
this.proposalProcedures.push(proposalProcedure);
}
setCollateralOutput(output) {
const uOutput = output;
uOutput.tokens = (0, helpers_1.sortTokens)(uOutput.tokens);
this.collateralOutput = uOutput;
if (uOutput.plutusData) {
this.plutusDataList.push(uOutput.plutusData);
}
}
getCollateralOutput() {
return this.collateralOutput;
}
setTotalCollateral(amount) {
this.totalCollateral = amount;
}
getTotalCollateral() {
return this.totalCollateral;
}
setDonationAmount(amount) {
this.donationAmount = amount;
}
getDonationAmount() {
return this.donationAmount;
}
setTreasuryAmount(amount) {
this.treasuryAmount = amount;
}
getTreasuryAmount() {
return this.treasuryAmount;
}
/**
* This method will encode the transaction body to be included in the cbor
*/
encodeTransactionBody({ extraOutputs, scriptDataHash, }) {
const encodedBody = new Map();
encodedBody.set(internal_types_1.TransactionBodyItemType.INPUTS, (0, encoder_1.encodeInputs)(this.inputs));
let trxOutputs = this.outputs;
if (extraOutputs && extraOutputs.length > 0) {
trxOutputs = trxOutputs.concat(extraOutputs);
}
encodedBody.set(internal_types_1.TransactionBodyItemType.OUTPUTS, (0, encoder_1.encodeOutputs)(trxOutputs));
encodedBody.set(internal_types_1.TransactionBodyItemType.FEE, this.fee);
if (this.ttl !== undefined) {
encodedBody.set(internal_types_1.TransactionBodyItemType.TTL, this.ttl);
}
if (this.certificates.length > 0) {
encodedBody.set(internal_types_1.TransactionBodyItemType.CERTIFICATES, (0, encoder_1.encodeCertificates)(this.certificates));
}
if (this.withdrawals.length > 0) {
encodedBody.set(internal_types_1.TransactionBodyItemType.WITHDRAWALS, (0, encoder_1.encodeWithdrawals)(this.withdrawals));
}
if (this.auxiliaryData) {
const encodedAuxiliaryData = (0, encoder_1.encodeAuxiliaryData)(this.auxiliaryData);
const auxiliaryDataCbor = cbors.Encoder.encode(encodedAuxiliaryData);
const auxiliaryDataHash = (0, crypto_1.hash32)(auxiliaryDataCbor);
encodedBody.set(internal_types_1.TransactionBodyItemType.AUXILIARY_DATA_HASH, auxiliaryDataHash);
}
if (this.validityIntervalStart !== undefined) {
encodedBody.set(internal_types_1.TransactionBodyItemType.VALIDITY_INTERVAL_START, this.validityIntervalStart);
}
if (!lodash_1.default.isEmpty(this.mints)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.MINT, (0, encoder_1.encodeMint)(this.mints));
}
if (scriptDataHash) {
encodedBody.set(internal_types_1.TransactionBodyItemType.SCRIPT_DATA_HASH, scriptDataHash);
}
if (!lodash_1.default.isEmpty(this.collaterals)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.COLLATERAL_INPUTS, (0, encoder_1.encodeCollaterals)(this.collaterals));
}
const requiredSigners = Array.from(this.requiredSigners.keys());
if (!lodash_1.default.isEmpty(requiredSigners)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.REQUIRED_SIGNERS, requiredSigners.map((key) => buffer_1.Buffer.from(key, "hex")));
}
if (this.collateralOutput) {
encodedBody.set(internal_types_1.TransactionBodyItemType.COLLATERAL_OUTPUT, (0, encoder_1.encodeOutput)(this.collateralOutput));
}
if (this.totalCollateral) {
encodedBody.set(internal_types_1.TransactionBodyItemType.TOTAL_COLLATERAL, this.totalCollateral);
}
if (!lodash_1.default.isEmpty(this.referenceInputs)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.REFERENCE_INPUTS, (0, encoder_1.encodeInputs)(this.referenceInputs));
}
if (!lodash_1.default.isEmpty(this.votingProcedures)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.VOTING_PROCEDURES, (0, encoder_1.encodeVotingProcedures)(this.votingProcedures));
}
if (!lodash_1.default.isEmpty(this.proposalProcedures)) {
encodedBody.set(internal_types_1.TransactionBodyItemType.PROPOSAL_PROCEDURES, (0, encoder_1.encodeProposalProcedures)(this.proposalProcedures));
}
if (this.donationAmount) {
encodedBody.set(internal_types_1.TransactionBodyItemType.DONATION_AMOUNT, this.donationAmount);
}
if (this.treasuryAmount) {
encodedBody.set(internal_types_1.TransactionBodyItemType.TREASURY_AMOUNT, this.treasuryAmount);
}
return encodedBody;
}
transactionFee(size) {
return new bignumber_js_1.default(size)
.times(this._protocolParams.minFeeA)
.plus(this._protocolParams.minFeeB)
.integerValue(bignumber_js_1.default.ROUND_CEIL);
}
contractFee() {
let totalMem = 0;
let totalSteps = 0;
for (const input of this.inputs) {
if (input.redeemer) {
totalMem += input.redeemer.exUnits.mem;
totalSteps += input.redeemer.exUnits.steps;
}
}
for (const mint of this.mints) {
if (mint.redeemer) {
totalMem += mint.redeemer.exUnits.mem;
totalSteps += mint.redeemer.exUnits.steps;
}
}
const memPrice = new bignumber_js_1.default(totalMem).times(this._protocolParams.priceMem);
const stepsPrice = new bignumber_js_1.default(totalSteps).times(this._protocolParams.priceSteps);
return memPrice.plus(stepsPrice).integerValue(bignumber_js_1.default.ROUND_CEIL);
}
calculateRefScriptFee() {
// sizeIncrement and multiplier are fixed numbers in cardano node
const sizeIncrement = 25600;
const multiplier = 1.2;
const minFeeRefScriptCostPerByte = this._protocolParams.minFeeRefScriptCostPerByte;
const calculate = (acc, curTierPrice, size) => {
if (size < sizeIncrement) {
return curTierPrice.multipliedBy(size).plus(acc).integerValue(bignumber_js_1.default.ROUND_FLOOR);
}
const acc_ = curTierPrice.multipliedBy(sizeIncrement).plus(acc);
return calculate(acc_, curTierPrice.multipliedBy(multiplier), size - sizeIncrement);
};
const getNSSize = (nativeScript) => {
const encodedNativeScript = cbors.Encoder.encode((0, encoder_1.encodeNativeScript)(nativeScript));
return encodedNativeScript.length;
};
const getPSSize = (plutusScriptHex) => {
return buffer_1.Buffer.from(plutusScriptHex, "hex").length;
};
let totalRefScriptSize = 0;
for (const input of this.inputs) {
if (input.nativeScript) {
totalRefScriptSize += getNSSize(input.nativeScript);
}
if (input.plutusScript) {
totalRefScriptSize += getPSSize(input.plutusScript.cborHex);
}
}
for (const input of this.referenceInputs) {
if (input.nativeScript) {
totalRefScriptSize += getNSSize(input.nativeScript);
}
if (input.plutusScript) {
totalRefScriptSize += getPSSize(input.plutusScript.cborHex);
}
}
if (totalRefScriptSize > 0) {
return calculate(new bignumber_js_1.default(0), minFeeRefScriptCostPerByte, totalRefScriptSize);
}
return new bignumber_js_1.default(0);
}
calculateTxSize(extraOutputs) {
const combinedRequiredWitnesses = new Map();
for (const [key, value] of this.requiredNativeScriptWitnesses.entries()) {
combinedRequiredWitnesses.set(key, value);
}
for (const [key, value] of this.requiredSigners.entries()) {
combinedRequiredWitnesses.set(key, value);
}
for (const [key, value] of this.requiredWitnesses.entries()) {
combinedRequiredWitnesses.set(key, value);
}
const dummyWitnesses = [];
for (const [index] of Array.from(combinedRequiredWitnesses.keys()).entries()) {
dummyWitnesses.push({
publicKey: buffer_1.Buffer.alloc(32, index),
signature: buffer_1.Buffer.alloc(64),
});
}
const encodedWitnesses = (0, encoder_1.encodeWitnesses)(dummyWitnesses, this.inputs, this.plutusDataList, this.plutusScriptMap, this.nativeScriptList, this.mints);
const scriptDataHash = (0, helpers_1.generateScriptDataHash)(this._protocolParams.languageView, encodedWitnesses, this._isPlutusV1Transaction, this._isPlutusV2Transaction, this._isPlutusV3Transaction);
const encodedBody = this.encodeTransactionBody({ extraOutputs, scriptDataHash });
const transaction = [
encodedBody,
encodedWitnesses,
true,
this.auxiliaryData ? (0, encoder_1.encodeAuxiliaryData)(this.auxiliaryData) : null,
];
const cborTrx = cbors.Encoder.encode(transaction);
return cborTrx.length;
}
calculateFee(extraOutputs) {
const txSize = this.calculateTxSize(extraOutputs);
const txFee = this.transactionFee(txSize);
const contractFee = this.contractFee();
// introduced in Conway era
const refScriptFee = this.calculateRefScriptFee();
return txFee.plus(contractFee).plus(refScriptFee);
}
setFee(fee) {
this.fee = fee;
}
getFee() {
return this.fee;
}
calculateMinUtxoAmountBabbage(output) {
return (0, utils_1.calculateMinUtxoAmountBabbage)(output, this._protocolParams.utxoCostPerByte);
}
addWitness(witness) {
this.witnesses.push(witness);
}
getTransactionHash() {
const encodedWitnesses = (0, encoder_1.encodeWitnesses)(this.witnesses, this.inputs, this.plutusDataList, this.plutusScriptMap, this.nativeScriptList, this.mints);
const scriptDataHash = (0, helpers_1.generateScriptDataHash)(this._protocolParams.languageView, encodedWitnesses, this._isPlutusV1Transaction, this._isPlutusV2Transaction, this._isPlutusV3Transaction);
const encodedBody = this.encodeTransactionBody({ scriptDataHash });
const cborBody = cbors.Encoder.encode(encodedBody);
return (0, crypto_1.hash32)(cborBody);
}
getAuxiliaryData() {
return this.auxiliaryData;
}
getAuxiliaryDataHashHex() {
if (this.auxiliaryData) {
const encodedAuxiliaryData = (0, encoder_1.encodeAuxiliaryData)(this.auxiliaryData);
const auxiliaryDataCbor = cbors.Encoder.encode(encodedAuxiliaryData);
return (0, crypto_1.hash32)(auxiliaryDataCbor).toString("hex");
}
return undefined;
}
buildTransaction() {
const encodedWitnesses = (0, encoder_1.encodeWitnesses)(this.witnesses, this.inputs, this.plutusDataList, this.plutusScriptMap, this.nativeScriptList, this.mints);
const scriptDataHash = (0, helpers_1.generateScriptDataHash)(this._protocolParams.languageView, encodedWitnesses, this._isPlutusV1Transaction, this._isPlutusV2Transaction, this._isPlutusV3Transaction);
const encodedBody = this.encodeTransactionBody({ scriptDataHash });
const transaction = [
encodedBody,
encodedWitnesses,
true,
this.auxiliaryData ? (0, encoder_1.encodeAuxiliaryData)(this.auxiliaryData) : null,
];
const cborTrx = cbors.Encoder.encode(transaction);
const trxBodyCbor = cbors.Encoder.encode(encodedBody);
const hash = (0, crypto_1.hash32)(trxBodyCbor).toString("hex");
return {
hash,
payload: cborTrx.toString("hex"),
};
}
getInputs() {
return this.inputs;
}
getCertificates() {
return this.certificates;
}
getMints() {
const tokens = [];
for (const mint of this.mints) {
for (const asset of mint.assets) {
tokens.push({
policyId: mint.policyId,
assetName: asset.assetName,
amount: asset.amount,
});
}
}
const sortedTokens = (0, helpers_1.sortTokens)(tokens);
return (0, lodash_1.default)(sortedTokens)
.groupBy((token) => token.policyId)
.map((tokens, policyId) => ({
policyId,
assets: tokens.map((t) => ({ assetName: t.assetName, amount: t.amount })),
}))
.value();
}
getMintTokens() {
const tokens = [];
for (const mint of this.mints) {
for (const asset of mint.assets) {
if (asset.amount.isPositive()) {
tokens.push({
policyId: mint.policyId,
assetName: asset.assetName,
amount: asset.amount,
});
}
}
}
return tokens;
}
getBurnTokens() {
const tokens = [];
for (const mint of this.mints) {
for (const asset of mint.assets) {
if (asset.amount.isNegative()) {
tokens.push({
policyId: mint.policyId,
assetName: asset.assetName,
amount: asset.amount.abs(),
});
}
}
}
return tokens;
}
getInputAmount() {
let inputTokens = [];
let ada = new bignumber_js_1.default(0);
lodash_1.default.forEach(this.inputs, (input) => {
inputTokens = inputTokens.concat(input.tokens);
ada = ada.plus(input.amount);
});
inputTokens = lodash_1.default.concat(inputTokens, this.getMintTokens());
return {
ada,
tokens: (0, helpers_1.getUniqueTokens)(inputTokens),
};
}
getCollaterals() {
return this.collaterals;
}
getScriptIntegrityHash() {
const encodedWitnesses = (0, encoder_1.encodeWitnesses)(this.witnesses, this.inputs, this.plutusDataList, this.plutusScriptMap, this.nativeScriptList, this.mints);
const scriptDataHash = (0, helpers_1.generateScriptDataHash)(this._protocolParams.languageView, encodedWitnesses, this._isPlutusV1Transaction, this._isPlutusV2Transaction, this._isPlutusV3Transaction);
return scriptDataHash;
}
getCollateralAmount() {
const ada = this.collaterals.reduce((sum, collateral) => sum.plus(collateral.amount), new bignumber_js_1.default(0));
return ada;
}
getOutputs() {
return this.outputs;
}
getOutputAmount() {
let outputTokens = [];
let ada = new bignumber_js_1.default(0);
lodash_1.default.forEach(this.outputs, (output) => {
outputTokens = outputTokens.concat(output.tokens);
ada = ada.plus(output.amount);
});
outputTokens = lodash_1.default.concat(outputTokens, this.getBurnTokens());
return {
ada,
tokens: (0, helpers_1.getUniqueTokens)(outputTokens),
};
}
/**
* This method scans the certificates and proposal procedures added in the transaction
* to calculate additional ADA required for transaction validity.
* 1. stake key registration deposit ADA
* 2. proposal procedure deposit ADA
* 3. donation amount
* @returns additional ADA required for a valid transaction
*/
getAdditionalOutputAda() {
const depositInCerts = lodash_1.default.reduce(this.certificates, (result, cert) => {
if (cert.type === types_1.CertificateType.STAKE_REGISTRATION) {
// legacy stake registration cert, use deposit value from protocol param
return result.plus(this._protocolParams.stakeKeyDeposit);
}
if (cert.type === types_1.CertificateType.STAKE_KEY_REGISTRATION) {
return result.plus(cert.cert.deposit);
}
return result;
}, new bignumber_js_1.default(0));
const depositInProposalProcedure = lodash_1.default.reduce(this.proposalProcedures, (result, pp) => {
return result.plus(pp.deposit);
}, new bignumber_js_1.default(0));
const donationAmount = this.donationAmount || new bignumber_js_1.default(0);
return depositInCerts.plus(depositInProposalProcedure).plus(donationAmount);
}
/**
* This method scans the certificates added in the transaction to calculate
* additional ADA available in inputs as part of the deposit refund.
* Essentially ADA to be considered as additional input due to deposit refunds.
* @returns additional ADA available as input
*/
getAdditionalInputAda() {
const certDeposit = lodash_1.default.reduce(this.certificates, (result, cert) => {
if (cert.type === types_1.CertificateType.STAKE_DE_REGISTRATION) {
// legacy stake de registration certificate, use deposit value from protocol params
return result.plus(this._protocolParams.stakeKeyDeposit);
}
if (cert.type === types_1.CertificateType.STAKE_KEY_DE_REGISTRATION) {
return result.plus(cert.cert.deposit);
}
return result;
}, new bignumber_js_1.default(0));
const withdrawalAda = lodash_1.default.reduce(this.withdrawals, (result, withdrawal) => {
return result.plus(withdrawal.amount);
}, new bignumber_js_1.default(0));
return certDeposit.plus(withdrawalAda);
}
getWithdrawals() {
return this.withdrawals;
}
getRequiredWitnesses() {
return this.requiredWitnesses;
}
getRequiredNativeScriptWitnesses() {
return this.requiredNativeScriptWitnesses;
}
getRequiredSigners() {
return this.requiredSigners;
}
getVotingProcedures() {
return this.votingProcedures;
}
getProposalProcedures() {
return this.proposalProcedures;
}
setAuxiliaryData(auxData) {
this.auxiliaryData = auxData;
}
isPlutusTransaction() {
return (this._isPlutusV1Transaction || this._isPlutusV2Transaction || this._isPlutusV3Transaction);
}
/**
* Function to prepare transaction automatically
* There are other helper methods for preparing transactions that use this method
* This method should be used when you know what you are doing
* sets required inputs,
* fees,
* change etc
* resulting transaction is the final tx that can be built for signing
*/
prepareTransaction({ inputs, changeAddress, collateralInputs = [], }) {
return (0, transactionBuilder_1.default)({ transaction: this, inputs, changeAddress, collateralInputs });
}
/**
* Function for a simple send ADA transaction
* Provide necessary outputs, and available inputs, returns a final tx
*/
paymentTransaction({ inputs, outputs, changeAddress, auxiliaryData, ttl, }) {
return (0, paymentTransaction_1.paymentTransaction)({
inputs,
outputs,
changeAddress,
auxiliaryData,
ttl,
protocolParams: this.protocolParams,
});
}
}
exports.Transaction = Transaction;
exports.default = Transaction;