@ordinalsbot/bitcoin-fee-estimator
Version:
A library for calculating Bitcoin transaction fees
76 lines (64 loc) • 2.06 kB
text/typescript
import { ScriptType } from "../types";
import { encodingLength } from "varuint-bitcoin";
import { estimateInputSize, getOutputSize } from "../common";
export function getTxOverhead(
inputScripts: ScriptType[],
outputCount: number,
): number {
const inputCount = inputScripts.length;
const hasWitnessInputs = inputScripts.some((type) =>
[
ScriptType.P2WPKH,
ScriptType.P2WSH,
ScriptType.P2TR,
ScriptType.P2SH_P2WPKH,
ScriptType.P2SH_P2WSH,
].includes(type),
);
const baseSize =
4 + // nVersion
encodingLength(inputCount) + // input count (varint)
encodingLength(outputCount) + // output count (varint)
4; // nLockTime
const segwitMarkerAndFlag = hasWitnessInputs ? 0.5 : 0;
return baseSize + segwitMarkerAndFlag;
}
export function estimateTxVBytesSimple(
inputScript: ScriptType[] = [ScriptType.P2TR],
outputScript: ScriptType[] = [ScriptType.P2TR],
opReturnData: Buffer | string | null = null,
): number {
const overhead = getTxOverhead(inputScript, outputScript.length);
let totalInput = 0;
for (const script of inputScript) {
totalInput += estimateInputSize(script);
}
const outputSize = outputScript.reduce(
(total, scriptType) => total + getOutputSize(scriptType),
0,
);
let opReturnSize = 0;
if (opReturnData !== null) {
const dataBuffer =
typeof opReturnData === "string"
? Buffer.from(opReturnData, "utf8")
: opReturnData;
opReturnSize =
8 + 1 + encodingLength(dataBuffer.length) + dataBuffer.length; // (8)value + 1(OP_RETURN) + (N)length Bytes + (M)Data
}
const vBytes = Math.ceil(overhead + totalInput + outputSize + opReturnSize);
return vBytes;
}
export function estimateTxFee(
inputScript: ScriptType[] = [ScriptType.P2TR],
outputScript: ScriptType[] = [ScriptType.P2TR],
feeRate: number,
opReturnData: Buffer | string | null = null,
): number {
const vBytes = estimateTxVBytesSimple(
inputScript,
outputScript,
opReturnData,
);
return Math.ceil(vBytes * feeRate);
}