aboutsummaryrefslogtreecommitdiffstats
path: root/lib/p2a.ts
blob: 21a96713b46cfdb9fc1ea92e2effa03d949963ef (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import config from "$config";
import { bech32m } from "@scure/base";

export const P2A_VALUE = 240;
export const P2A_SCRIPT = "51024e73"; // OP_1 OP_PUSHBYTES_2 0x4e73
export const CHILD_VSIZE = 152;

const P2A_WITNESS_PROGRAM = new Uint8Array([0x4e, 0x73]);
const P2A_WITNESS_VERSION = 1;

const BECH32M_PREFIXES: Record<string, string> = {
  bitcoin: "bc",
  mainnet: "bc",
  testnet: "tb",
  signet: "tb",
  regtest: "bcrt",
};

function encodeP2AAddress(network: string): string {
  const prefix = BECH32M_PREFIXES[network];
  if (!prefix) throw new Error(`Unknown network: ${network}`);
  const words = [P2A_WITNESS_VERSION, ...bech32m.toWords(P2A_WITNESS_PROGRAM)];
  return bech32m.encode(prefix, words);
}

export function getP2AAddress(): string {
  const network = config.bitcoin.network || "mainnet";
  return encodeP2AAddress(network);
}

export function isP2AOutput(scriptPubKeyHex: string): boolean {
  return scriptPubKeyHex === P2A_SCRIPT;
}

export function calculateBumpReserve(
  userRate: number,
  fastestRate: number,
  parentVsize: number,
): number {
  const subsidy = Math.max(0, (fastestRate - userRate) * parentVsize);
  return Math.ceil(subsidy + fastestRate * CHILD_VSIZE);
}