@ledgerhq/coin-tezos
Version:
121 lines • 5.43 kB
JavaScript
import { DerivationType } from "@taquito/ledger-signer";
import { compressPublicKey } from "@taquito/ledger-signer/dist/lib/utils";
import { COST_PER_BYTE, getRevealFee, ORIGINATION_SIZE } from "@taquito/taquito";
import { b58Encode, PrefixV2 } from "@taquito/utils";
import { log } from "@ledgerhq/logs";
import { getTezosToolkit } from "./tezosToolkit";
import { UnsupportedTransactionMode } from "../types/errors";
/**
* Fetch the transaction fees for a transaction
*
* @param {Account} account
* @param {Transaction} transaction
*/
export async function estimateFees({ account, transaction, }) {
const encodedPubKey = b58Encode(compressPublicKey(Buffer.from(account.xpub || "", "hex"), DerivationType.ED25519), PrefixV2.Ed25519PublicKey);
const tezosToolkit = getTezosToolkit();
tezosToolkit.setProvider({
signer: {
publicKeyHash: async () => account.address,
publicKey: async () => encodedPubKey,
sign: () => Promise.reject(new Error("unsupported")),
secretKey: () => Promise.reject(new Error("unsupported")),
},
});
const estimation = {
fees: BigInt(0),
gasLimit: BigInt(0),
storageLimit: BigInt(0),
estimatedFees: BigInt(0),
};
// For legacy compatibility
if (account.balance === BigInt(0)) {
return transaction.useAllAmount ? { ...estimation, amount: BigInt(0) } : estimation;
}
let amount = transaction.amount;
if (transaction.useAllAmount) {
amount = BigInt(1); // send max do a pre-estimation with minimum amount (taquito refuses 0)
}
try {
let estimate;
switch (transaction.mode) {
case "send":
estimate = await tezosToolkit.estimate.transfer({
mutez: true,
to: transaction.recipient,
amount: Number(amount),
storageLimit: ORIGINATION_SIZE, // https://github.com/TezTech/eztz/blob/master/PROTO_003_FEES.md for originating an account
});
break;
case "delegate":
estimate = await tezosToolkit.estimate.setDelegate({
source: account.address,
delegate: transaction.recipient,
});
break;
case "undelegate":
estimate = await tezosToolkit.estimate.setDelegate({
source: account.address,
});
break;
default:
throw new UnsupportedTransactionMode("unsupported mode", { mode: transaction.mode });
}
// NOTE: if useAllAmount is true, is it for sure in the send mode (ie. transfer)?
if (transaction.useAllAmount) {
let totalFees;
if (estimate.burnFeeMutez > 0) {
// NOTE: from https://github.com/ecadlabs/taquito/blob/master/integration-tests/__tests__/contract/empty-implicit-account-into-new-implicit-account.spec.ts#L37
totalFees = estimate.suggestedFeeMutez + estimate.burnFeeMutez - 20 * COST_PER_BYTE; // 20 is storage buffer
}
else {
totalFees = estimate.suggestedFeeMutez;
}
const maxAmount = parseInt(account.balance.toString()) -
(totalFees + (account.revealed ? 0 : getRevealFee(account.address)));
// NOTE: from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
// Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
// we need to increase the gasLimit and fee returned by the estimation
const gasBuffer = 500;
const MINIMAL_FEE_PER_GAS_MUTEZ = 0.1;
const increasedFee = (gasBuffer, opSize) => {
return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
};
const incr = increasedFee(gasBuffer, Number(estimate.opSize));
const maxMinusBuff = maxAmount - (gasBuffer - incr);
estimation.amount = maxMinusBuff > 0 ? BigInt(maxMinusBuff) : BigInt(0);
estimation.fees = BigInt(estimate.suggestedFeeMutez);
estimation.gasLimit = BigInt(estimate.gasLimit);
}
else {
estimation.fees = BigInt(estimate.suggestedFeeMutez);
estimation.gasLimit = BigInt(estimate.gasLimit);
estimation.amount = transaction.amount;
}
estimation.storageLimit = BigInt(estimate.storageLimit);
estimation.estimatedFees = estimation.fees;
if (!account.revealed) {
estimation.estimatedFees = estimation.estimatedFees + BigInt(getRevealFee(account.address));
}
}
catch (e) {
if (typeof e !== "object" || !e)
throw e;
if ("id" in e) {
estimation.taquitoError = e.id;
log("taquito-error", "taquito got error " + e.id);
}
else if ("status" in e) {
// in case of http 400, log & ignore (more case to handle)
log("taquito-network-error", String(e.message || ""), {
transaction: transaction,
});
throw e;
}
else {
throw e;
}
}
return estimation;
}
//# sourceMappingURL=estimateFees.js.map