diff --git a/src/core/input.ts b/src/core/input.ts index 2e17ff6..69492ac 100644 --- a/src/core/input.ts +++ b/src/core/input.ts @@ -14,7 +14,8 @@ export function classifyInput(input: string, chain?: ChainKey): InputType { chain === "litecoin" || chain === "ecash" || chain === "tron" || - chain === "cardano") && + chain === "cardano" || + chain === "pepecoin") && /^[0-9a-fA-F]{64}$/.test(trimmed)) || (chain === "solana" && /^[1-9A-HJ-NP-Za-km-z]{64,88}$/.test(trimmed)) || (chain === "sui" && /^[1-9A-HJ-NP-Za-km-z]{43,44}$/.test(trimmed)) diff --git a/src/core/types.ts b/src/core/types.ts index 7046a0f..91f4952 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -143,7 +143,13 @@ export interface ContractInfo { } /** Unit used by a provider's fee suggestions. */ -export type GasUnit = "gwei" | "sat/vB" | "litoshi/vB" | "micro-lamports/CU" | "MIST"; +export type GasUnit = + | "gwei" + | "sat/vB" + | "litoshi/vB" + | "pepetoshi/vB" + | "micro-lamports/CU" + | "MIST"; /** Gas or fee-market data in provider-native units. */ export interface GasData { diff --git a/src/providers/index.ts b/src/providers/index.ts index a530ad3..2a72cb3 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -51,7 +51,7 @@ export const builtins: readonly ProviderEntry[] = [ }, { key: "mempool", - chains: ["bitcoin", "litecoin"], + chains: ["bitcoin", "litecoin", "pepecoin"], defaultURL: "https://mempool.space", load: () => import("./mempool.js").then((m) => m.Mempool), }, diff --git a/src/providers/mempool.ts b/src/providers/mempool.ts index f6b7881..744d1c0 100644 --- a/src/providers/mempool.ts +++ b/src/providers/mempool.ts @@ -33,12 +33,14 @@ const DEFAULT_BASE = "https://mempool.space"; const CHAIN_BASES: Partial> = { bitcoin: DEFAULT_BASE, litecoin: "https://litecoinspace.org", + pepecoin: "https://peppool.space", }; /** Fee rates come back in the chain's smallest unit per virtual byte. */ const FEE_UNITS: Partial> = { bitcoin: "sat/vB", litecoin: "litoshi/vB", + pepecoin: "pepetoshi/vB", }; interface MempoolAddressSummary { diff --git a/test/unit/mempool.test.ts b/test/unit/mempool.test.ts index b3b1bd4..5b913fc 100644 --- a/test/unit/mempool.test.ts +++ b/test/unit/mempool.test.ts @@ -12,6 +12,9 @@ const KNOWN_BTC = "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"; // A Litecoin mining pool address with tens of thousands of transactions const KNOWN_LTC = "LfdYLbP9F9CpmCX6atZnHZb8KkS8T6x4DK"; +// A Pepecoin address +const KNOWN_PEP = "Pu5spyDwNEQxmWLkUHv779AWNkpMdQ29SZ"; + afterEach(() => { vi.unstubAllGlobals(); }); @@ -102,6 +105,40 @@ describe("mempool provider", () => { expect(gas.unit).toBe("litoshi/vB"); }); + it("getBalance returns PEP balance from peppool", async () => { + const balance = await provider.getBalance(KNOWN_PEP, "pepecoin"); + + expect(balance.address).toBe(KNOWN_PEP); + expect(balance.chain).toBe("pepecoin"); + expect(balance.symbol).toBe("PEP"); + expect(balance.balance).toMatch(/^-?\d+$/); + expect(Number(balance.balanceFormatted)).toBeGreaterThanOrEqual(0); + }); + + it("routes pepecoin calls to peppool.space", async () => { + const fetch = stubJSON({ + chain_stats: { + funded_txo_count: 1, + funded_txo_sum: 10, + spent_txo_count: 0, + spent_txo_sum: 0, + }, + }); + + await provider.getBalance(KNOWN_PEP, "pepecoin"); + + expect(String(fetch.mock.calls[0]?.[0])).toBe(`https://peppool.space/api/address/${KNOWN_PEP}`); + }); + + it("labels pepecoin fee estimates in pepetoshi/vB", async () => { + stubJSON({ fastestFee: 2, halfHourFee: 1, hourFee: 1, economyFee: 1, minimumFee: 1 }); + + const gas = await provider.getGasData!("pepecoin"); + + expect(gas.chain).toBe("pepecoin"); + expect(gas.unit).toBe("pepetoshi/vB"); + }); + it("joins custom base URLs with exactly one separator", async () => { const fetch = vi.fn(async () => { return new Response( diff --git a/test/unit/resolve.test.ts b/test/unit/resolve.test.ts index 0123020..a943040 100644 --- a/test/unit/resolve.test.ts +++ b/test/unit/resolve.test.ts @@ -47,6 +47,7 @@ describe("resolveProvider", () => { expect(resolveProvider(undefined, "bitcoin")).toBe("mempool"); expect(resolveProvider(undefined, "litecoin")).toBe("mempool"); + expect(resolveProvider(undefined, "pepecoin")).toBe("mempool"); }); it("keeps a configured provider that serves the requested chain", () => {