@happyvertical/payments 0.74.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @happyvertical/payments - Multi-backend payment provider abstraction.
3
+ *
4
+ * The default entrypoint exports only provider contracts, shared errors, and
5
+ * the dynamic factory. Adapter implementations live behind subpath exports:
6
+ * `@happyvertical/payments/base-usdc`, `@happyvertical/payments/btc`, and
7
+ * `@happyvertical/payments/stripe`.
8
+ */
9
+ export * from './errors.js';
10
+ export * from './factory.js';
11
+ export * from './types.js';
12
+ /** @internal */
13
+ export declare const PACKAGE_VERSION_INITIALIZED = true;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAE3B,gBAAgB;AAChB,eAAO,MAAM,2BAA2B,OAAO,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ import { P as PaymentConfigurationError } from "./chunks/errors-BgFC46qQ.js";
2
+ import { a, b, c, d } from "./chunks/errors-BgFC46qQ.js";
3
+ async function createPaymentBackend(options) {
4
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
5
+ throw new PaymentConfigurationError(
6
+ "Payment backend options must be an object."
7
+ );
8
+ }
9
+ const type = options.type;
10
+ if (typeof type !== "string" || !type.trim()) {
11
+ throw new PaymentConfigurationError(
12
+ "Payment backend type must be a string."
13
+ );
14
+ }
15
+ const normalizedType = type.trim();
16
+ const backendOptions = {
17
+ ...options,
18
+ type: normalizedType
19
+ };
20
+ switch (backendOptions.type) {
21
+ case "base-usdc": {
22
+ const { BaseUsdcAdapter } = await import("./adapters/base-usdc.js");
23
+ return new BaseUsdcAdapter(backendOptions);
24
+ }
25
+ case "btc": {
26
+ const { BtcAdapter } = await import("./adapters/btc.js");
27
+ return new BtcAdapter(backendOptions);
28
+ }
29
+ case "stripe": {
30
+ const { StripeAdapter } = await import("./adapters/stripe.js");
31
+ return new StripeAdapter(backendOptions);
32
+ }
33
+ default:
34
+ throw new PaymentConfigurationError(
35
+ `Unknown payment backend type: ${normalizedType}`
36
+ );
37
+ }
38
+ }
39
+ const PACKAGE_VERSION_INITIALIZED = true;
40
+ export {
41
+ PACKAGE_VERSION_INITIALIZED,
42
+ PaymentConfigurationError,
43
+ a as PaymentError,
44
+ b as PaymentProviderError,
45
+ c as PaymentUnsupportedError,
46
+ d as PaymentVerificationError,
47
+ createPaymentBackend
48
+ };
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/factory.ts","../src/index.ts"],"sourcesContent":["import type { BaseUsdcAdapterOptions } from './adapters/base-usdc.js';\nimport type { BtcAdapterOptions } from './adapters/btc.js';\nimport type { StripeAdapterOptions } from './adapters/stripe.js';\nimport { PaymentConfigurationError } from './errors.js';\nimport type { PaymentBackend } from './types.js';\n\nexport type PaymentBackendOptions =\n | ({ type: 'base-usdc' } & BaseUsdcAdapterOptions)\n | ({ type: 'btc' } & BtcAdapterOptions)\n | ({ type: 'stripe' } & StripeAdapterOptions);\n\nexport async function createPaymentBackend(\n options: PaymentBackendOptions,\n): Promise<PaymentBackend> {\n if (!options || typeof options !== 'object' || Array.isArray(options)) {\n throw new PaymentConfigurationError(\n 'Payment backend options must be an object.',\n );\n }\n\n const type = (options as { type?: unknown }).type;\n\n if (typeof type !== 'string' || !type.trim()) {\n throw new PaymentConfigurationError(\n 'Payment backend type must be a string.',\n );\n }\n\n const normalizedType = type.trim();\n const backendOptions = {\n ...options,\n type: normalizedType,\n } as PaymentBackendOptions;\n\n switch (backendOptions.type) {\n case 'base-usdc': {\n const { BaseUsdcAdapter } = await import('./adapters/base-usdc.js');\n return new BaseUsdcAdapter(backendOptions);\n }\n case 'btc': {\n const { BtcAdapter } = await import('./adapters/btc.js');\n return new BtcAdapter(backendOptions);\n }\n case 'stripe': {\n const { StripeAdapter } = await import('./adapters/stripe.js');\n return new StripeAdapter(backendOptions);\n }\n default:\n throw new PaymentConfigurationError(\n `Unknown payment backend type: ${normalizedType}`,\n );\n }\n}\n","/**\n * @happyvertical/payments - Multi-backend payment provider abstraction.\n *\n * The default entrypoint exports only provider contracts, shared errors, and\n * the dynamic factory. Adapter implementations live behind subpath exports:\n * `@happyvertical/payments/base-usdc`, `@happyvertical/payments/btc`, and\n * `@happyvertical/payments/stripe`.\n */\n\nexport * from './errors.js';\nexport * from './factory.js';\nexport * from './types.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"names":[],"mappings":";;AAWA,eAAsB,qBACpB,SACyB;AACzB,MAAI,CAAC,WAAW,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACrE,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,OAAQ,QAA+B;AAE7C,MAAI,OAAO,SAAS,YAAY,CAAC,KAAK,QAAQ;AAC5C,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,iBAAiB,KAAK,KAAA;AAC5B,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA,IACH,MAAM;AAAA,EAAA;AAGR,UAAQ,eAAe,MAAA;AAAA,IACrB,KAAK,aAAa;AAChB,YAAM,EAAE,gBAAA,IAAoB,MAAM,OAAO,yBAAyB;AAClE,aAAO,IAAI,gBAAgB,cAAc;AAAA,IAC3C;AAAA,IACA,KAAK,OAAO;AACV,YAAM,EAAE,WAAA,IAAe,MAAM,OAAO,mBAAmB;AACvD,aAAO,IAAI,WAAW,cAAc;AAAA,IACtC;AAAA,IACA,KAAK,UAAU;AACb,YAAM,EAAE,cAAA,IAAkB,MAAM,OAAO,sBAAsB;AAC7D,aAAO,IAAI,cAAc,cAAc;AAAA,IACzC;AAAA,IACA;AACE,YAAM,IAAI;AAAA,QACR,iCAAiC,cAAc;AAAA,MAAA;AAAA,EACjD;AAEN;ACtCO,MAAM,8BAA8B;"}
@@ -0,0 +1,32 @@
1
+ import { PaymentEvent, PaymentStatus, PaymentStatusResult, WatchPaymentInput } from './types.js';
2
+ export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
3
+ export declare const TERMINAL_PAYMENT_STATUSES: Set<PaymentStatus>;
4
+ export declare const DEFAULT_MAX_STORED_PAYMENT_OPTIONS = 1000;
5
+ export declare function getFetch(fetchLike?: FetchLike): FetchLike;
6
+ export declare function normalizeDate(value: Date | string): Date;
7
+ export declare function normalizeFutureDate(value: Date | string, context: string): Date;
8
+ export declare function normalizeAmount(value: string): string;
9
+ export declare function normalizePositiveAmount(value: string, context: string): string;
10
+ export declare function normalizeCurrency(value: string, context: string): string;
11
+ export declare function normalizeMinorUnitAmount(value: number, context: string): number;
12
+ export declare function normalizePositiveMinorUnitAmount(value: number, context: string): number;
13
+ export declare function normalizePositivePaymentAmount(value: number, currency: string, context: string): number;
14
+ export declare function normalizeMaxStoredPaymentOptions(value: number | undefined, context: string): number;
15
+ export declare function rememberPaymentOption<TOption>(optionsByQuote: Map<string, TOption>, quoteId: string, option: TOption, maxStoredPaymentOptions: number): void;
16
+ export declare function normalizeNonEmptyString(value: string, context: string): string;
17
+ export declare function normalizeUrlString(value: string, context: string): string;
18
+ export declare function decimalToAtomicUnits(value: string, decimals: number): string;
19
+ export declare function atomicUnitsToDecimal(value: string | bigint, decimals: number): string;
20
+ export declare function amountToMinorUnits(value: string, decimals?: number): string;
21
+ export declare function minorUnitsToDecimal(value: number, decimals: number): string;
22
+ export declare function decimalToMinorUnitAmount(value: string | bigint, decimals: number, context: string): number;
23
+ export declare function currencyMinorUnitDecimals(currency: string): number;
24
+ export declare function applyExpiryToPendingStatus(status: PaymentStatus, expiresAt?: Date): PaymentStatus;
25
+ export declare function compareDecimalAmounts(left: string, right: string): -1 | 0 | 1;
26
+ export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
27
+ export declare function pollPaymentStatus(input: WatchPaymentInput, getStatus: () => Promise<PaymentStatusResult>): AsyncIterable<PaymentEvent>;
28
+ export declare function toPaymentEvent(status: PaymentStatusResult): PaymentEvent;
29
+ export declare function readJsonResponse<T>(response: Response, context: string): Promise<T>;
30
+ export declare function formEncode(params: Record<string, unknown>): string;
31
+ export declare function throwUnsupported(message: string): never;
32
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { CreatePaymentOptionInput, PaymentBackend, PaymentBackendCapabilities, PaymentOption, PaymentStatusResult, PayoutResult } from '../types.js';
2
+ type ConformanceExpectation = {
3
+ toBe(expected: unknown): void;
4
+ toEqual(expected: unknown): void;
5
+ toBeGreaterThanOrEqual(expected: number): void;
6
+ toBeInstanceOf(expected: unknown): void;
7
+ toContain(expected: unknown): void;
8
+ toMatchObject(expected: unknown): void;
9
+ resolves: {
10
+ toMatchObject(expected: unknown): Promise<void>;
11
+ };
12
+ };
13
+ type ConformanceExpect = ((actual: unknown) => ConformanceExpectation) & {
14
+ any(expected: unknown): unknown;
15
+ objectContaining(expected: Record<string, unknown>): unknown;
16
+ };
17
+ export interface PaymentBackendConformanceTestApi {
18
+ describe(name: string, callback: () => void): void;
19
+ it(name: string, callback: () => void | Promise<void>): void;
20
+ expect: ConformanceExpect;
21
+ }
22
+ export interface PaymentBackendConformanceHarness {
23
+ createBackend(): PaymentBackend | Promise<PaymentBackend>;
24
+ createPaymentOptionInput?: CreatePaymentOptionInput;
25
+ expectedCapabilities?: Partial<PaymentBackendCapabilities>;
26
+ expectedOption?: Partial<PaymentOption>;
27
+ expectedStatus?: Partial<PaymentStatusResult>;
28
+ payoutInput?: Parameters<PaymentBackend['sendPayout']>[0];
29
+ expectedPayout?: Partial<PayoutResult>;
30
+ }
31
+ export declare function definePaymentBackendConformanceTests(backendName: string, harness: PaymentBackendConformanceHarness, testApi?: PaymentBackendConformanceTestApi): void;
32
+ export {};
33
+ //# sourceMappingURL=conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/testing/conformance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,cAAc,EACd,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,YAAY,EACb,MAAM,aAAa,CAAC;AAErB,KAAK,sBAAsB,GAAG;IAC5B,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,cAAc,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,QAAQ,EAAE;QACR,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;CACH,CAAC;AAEF,KAAK,iBAAiB,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,sBAAsB,CAAC,GAAG;IACvE,GAAG,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;IAChC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CAC9D,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACnD,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7D,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,gCAAgC;IAC/C,aAAa,IAAI,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1D,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,oBAAoB,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,WAAW,CAAC,EAAE,UAAU,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC;AAWD,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,gCAAgC,EACzC,OAAO,mCAAiC,GACvC,IAAI,CAsGN"}
@@ -0,0 +1,114 @@
1
+ const futureExpiryOffsetMs = 365 * 24 * 60 * 60 * 1e3;
2
+ const defaultPaymentOptionInput = {
3
+ quoteId: "quote-conformance",
4
+ amount: 1234,
5
+ currency: "USD",
6
+ expiresAt: new Date(Date.now() + futureExpiryOffsetMs)
7
+ };
8
+ function definePaymentBackendConformanceTests(backendName, harness, testApi = readGlobalConformanceTestApi()) {
9
+ const { describe, expect, it } = testApi;
10
+ describe(`${backendName} PaymentBackend conformance`, () => {
11
+ it("declares required capabilities", async () => {
12
+ const backend = await harness.createBackend();
13
+ expect(backend.capabilities.id).toEqual(expect.any(String));
14
+ expect(backend.capabilities.displayName).toEqual(expect.any(String));
15
+ expect(backend.capabilities.settlementCurrency).toEqual(
16
+ expect.any(String)
17
+ );
18
+ expect(backend.capabilities.chain).toEqual(expect.any(String));
19
+ expect(["address", "url", "psbt"]).toContain(
20
+ backend.capabilities.settlementShape
21
+ );
22
+ expect(typeof backend.capabilities.x402Capable).toBe("boolean");
23
+ expect(typeof backend.capabilities.supportsRefunds).toBe("boolean");
24
+ expect(typeof backend.capabilities.supportsPayouts).toBe("boolean");
25
+ expect(typeof backend.capabilities.supportsWebhooks).toBe("boolean");
26
+ expect(
27
+ backend.capabilities.confirmationLatency.expectedSeconds
28
+ ).toBeGreaterThanOrEqual(0);
29
+ expect(backend.capabilities).toMatchObject(
30
+ harness.expectedCapabilities ?? {}
31
+ );
32
+ });
33
+ it("creates a payment option with stable quote metadata", async () => {
34
+ const backend = await harness.createBackend();
35
+ const input = harness.createPaymentOptionInput ?? defaultPaymentOptionInput;
36
+ const option = await backend.createPaymentOption(input);
37
+ expect(option.backendId).toBe(backend.capabilities.id);
38
+ expect(option.quoteId).toBe(input.quoteId);
39
+ expect(option.payTo).toEqual(expect.any(String));
40
+ expect(option.settlementCurrency).toBe(
41
+ backend.capabilities.settlementCurrency
42
+ );
43
+ expect(option.settlementShape).toBe(backend.capabilities.settlementShape);
44
+ expect(option.settlementAmount).toEqual(expect.any(Number));
45
+ expect(option.amount).toBe(input.amount);
46
+ expect(option.currency).toBe(input.currency);
47
+ expect(option.expiresAt).toBeInstanceOf(Date);
48
+ expect(option).toMatchObject(harness.expectedOption ?? {});
49
+ });
50
+ it("reports idempotent status for an option", async () => {
51
+ const backend = await harness.createBackend();
52
+ const input = harness.createPaymentOptionInput ?? defaultPaymentOptionInput;
53
+ const option = await backend.createPaymentOption(input);
54
+ const status = await backend.getStatus(input.quoteId, option.payTo);
55
+ expect(status.backendId).toBe(backend.capabilities.id);
56
+ expect(status.quoteId).toBe(input.quoteId);
57
+ expect(status.payTo).toBe(option.payTo);
58
+ expect(status.updatedAt).toBeInstanceOf(Date);
59
+ expect(status).toMatchObject(harness.expectedStatus ?? {});
60
+ });
61
+ it("returns an async iterable from watchPayment", async () => {
62
+ const backend = await harness.createBackend();
63
+ const input = harness.createPaymentOptionInput ?? defaultPaymentOptionInput;
64
+ const option = await backend.createPaymentOption(input);
65
+ const stream = backend.watchPayment({
66
+ quoteId: input.quoteId,
67
+ payTo: option.payTo,
68
+ pollIntervalMs: 1,
69
+ timeoutMs: 1
70
+ });
71
+ expect(typeof stream[Symbol.asyncIterator]).toBe("function");
72
+ await expect(
73
+ stream[Symbol.asyncIterator]().next()
74
+ ).resolves.toMatchObject({
75
+ value: expect.objectContaining({
76
+ backendId: backend.capabilities.id,
77
+ quoteId: input.quoteId
78
+ })
79
+ });
80
+ });
81
+ it("sends payouts through the backend payout surface", async () => {
82
+ const backend = await harness.createBackend();
83
+ const payout = await backend.sendPayout(
84
+ harness.payoutInput ?? {
85
+ destination: "destination-conformance",
86
+ amount: 100,
87
+ currency: "USD"
88
+ }
89
+ );
90
+ expect(payout.backendId).toBe(backend.capabilities.id);
91
+ expect(payout.destination).toEqual(expect.any(String));
92
+ expect(payout.amount).toEqual(expect.any(Number));
93
+ expect(payout.currency).toEqual(expect.any(String));
94
+ expect(payout).toMatchObject(harness.expectedPayout ?? {});
95
+ });
96
+ });
97
+ }
98
+ function readGlobalConformanceTestApi() {
99
+ const candidate = globalThis;
100
+ if (typeof candidate.describe === "function" && typeof candidate.it === "function" && typeof candidate.expect === "function" && typeof candidate.expect.any === "function" && typeof candidate.expect.objectContaining === "function") {
101
+ return {
102
+ describe: candidate.describe,
103
+ expect: candidate.expect,
104
+ it: candidate.it
105
+ };
106
+ }
107
+ throw new Error(
108
+ "definePaymentBackendConformanceTests requires a test API. Pass { describe, expect, it } from Vitest or enable compatible test globals."
109
+ );
110
+ }
111
+ export {
112
+ definePaymentBackendConformanceTests
113
+ };
114
+ //# sourceMappingURL=conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.js","sources":["../../src/testing/conformance.ts"],"sourcesContent":["import type {\n CreatePaymentOptionInput,\n PaymentBackend,\n PaymentBackendCapabilities,\n PaymentOption,\n PaymentStatusResult,\n PayoutResult,\n} from '../types.js';\n\ntype ConformanceExpectation = {\n toBe(expected: unknown): void;\n toEqual(expected: unknown): void;\n toBeGreaterThanOrEqual(expected: number): void;\n toBeInstanceOf(expected: unknown): void;\n toContain(expected: unknown): void;\n toMatchObject(expected: unknown): void;\n resolves: {\n toMatchObject(expected: unknown): Promise<void>;\n };\n};\n\ntype ConformanceExpect = ((actual: unknown) => ConformanceExpectation) & {\n any(expected: unknown): unknown;\n objectContaining(expected: Record<string, unknown>): unknown;\n};\n\nexport interface PaymentBackendConformanceTestApi {\n describe(name: string, callback: () => void): void;\n it(name: string, callback: () => void | Promise<void>): void;\n expect: ConformanceExpect;\n}\n\nexport interface PaymentBackendConformanceHarness {\n createBackend(): PaymentBackend | Promise<PaymentBackend>;\n createPaymentOptionInput?: CreatePaymentOptionInput;\n expectedCapabilities?: Partial<PaymentBackendCapabilities>;\n expectedOption?: Partial<PaymentOption>;\n expectedStatus?: Partial<PaymentStatusResult>;\n payoutInput?: Parameters<PaymentBackend['sendPayout']>[0];\n expectedPayout?: Partial<PayoutResult>;\n}\n\nconst futureExpiryOffsetMs = 365 * 24 * 60 * 60 * 1_000;\n\nconst defaultPaymentOptionInput: CreatePaymentOptionInput = {\n quoteId: 'quote-conformance',\n amount: 1234,\n currency: 'USD',\n expiresAt: new Date(Date.now() + futureExpiryOffsetMs),\n};\n\nexport function definePaymentBackendConformanceTests(\n backendName: string,\n harness: PaymentBackendConformanceHarness,\n testApi = readGlobalConformanceTestApi(),\n): void {\n const { describe, expect, it } = testApi;\n\n describe(`${backendName} PaymentBackend conformance`, () => {\n it('declares required capabilities', async () => {\n const backend = await harness.createBackend();\n\n expect(backend.capabilities.id).toEqual(expect.any(String));\n expect(backend.capabilities.displayName).toEqual(expect.any(String));\n expect(backend.capabilities.settlementCurrency).toEqual(\n expect.any(String),\n );\n expect(backend.capabilities.chain).toEqual(expect.any(String));\n expect(['address', 'url', 'psbt']).toContain(\n backend.capabilities.settlementShape,\n );\n expect(typeof backend.capabilities.x402Capable).toBe('boolean');\n expect(typeof backend.capabilities.supportsRefunds).toBe('boolean');\n expect(typeof backend.capabilities.supportsPayouts).toBe('boolean');\n expect(typeof backend.capabilities.supportsWebhooks).toBe('boolean');\n expect(\n backend.capabilities.confirmationLatency.expectedSeconds,\n ).toBeGreaterThanOrEqual(0);\n expect(backend.capabilities).toMatchObject(\n harness.expectedCapabilities ?? {},\n );\n });\n\n it('creates a payment option with stable quote metadata', async () => {\n const backend = await harness.createBackend();\n const input =\n harness.createPaymentOptionInput ?? defaultPaymentOptionInput;\n const option = await backend.createPaymentOption(input);\n\n expect(option.backendId).toBe(backend.capabilities.id);\n expect(option.quoteId).toBe(input.quoteId);\n expect(option.payTo).toEqual(expect.any(String));\n expect(option.settlementCurrency).toBe(\n backend.capabilities.settlementCurrency,\n );\n expect(option.settlementShape).toBe(backend.capabilities.settlementShape);\n expect(option.settlementAmount).toEqual(expect.any(Number));\n expect(option.amount).toBe(input.amount);\n expect(option.currency).toBe(input.currency);\n expect(option.expiresAt).toBeInstanceOf(Date);\n expect(option).toMatchObject(harness.expectedOption ?? {});\n });\n\n it('reports idempotent status for an option', async () => {\n const backend = await harness.createBackend();\n const input =\n harness.createPaymentOptionInput ?? defaultPaymentOptionInput;\n const option = await backend.createPaymentOption(input);\n const status = await backend.getStatus(input.quoteId, option.payTo);\n\n expect(status.backendId).toBe(backend.capabilities.id);\n expect(status.quoteId).toBe(input.quoteId);\n expect(status.payTo).toBe(option.payTo);\n expect(status.updatedAt).toBeInstanceOf(Date);\n expect(status).toMatchObject(harness.expectedStatus ?? {});\n });\n\n it('returns an async iterable from watchPayment', async () => {\n const backend = await harness.createBackend();\n const input =\n harness.createPaymentOptionInput ?? defaultPaymentOptionInput;\n const option = await backend.createPaymentOption(input);\n const stream = backend.watchPayment({\n quoteId: input.quoteId,\n payTo: option.payTo,\n pollIntervalMs: 1,\n timeoutMs: 1,\n });\n\n expect(typeof stream[Symbol.asyncIterator]).toBe('function');\n await expect(\n stream[Symbol.asyncIterator]().next(),\n ).resolves.toMatchObject({\n value: expect.objectContaining({\n backendId: backend.capabilities.id,\n quoteId: input.quoteId,\n }),\n });\n });\n\n it('sends payouts through the backend payout surface', async () => {\n const backend = await harness.createBackend();\n const payout = await backend.sendPayout(\n harness.payoutInput ?? {\n destination: 'destination-conformance',\n amount: 100,\n currency: 'USD',\n },\n );\n\n expect(payout.backendId).toBe(backend.capabilities.id);\n expect(payout.destination).toEqual(expect.any(String));\n expect(payout.amount).toEqual(expect.any(Number));\n expect(payout.currency).toEqual(expect.any(String));\n expect(payout).toMatchObject(harness.expectedPayout ?? {});\n });\n });\n}\n\nfunction readGlobalConformanceTestApi(): PaymentBackendConformanceTestApi {\n const candidate = globalThis as {\n describe?: unknown;\n expect?: unknown;\n it?: unknown;\n };\n\n if (\n typeof candidate.describe === 'function' &&\n typeof candidate.it === 'function' &&\n typeof candidate.expect === 'function' &&\n typeof (candidate.expect as { any?: unknown }).any === 'function' &&\n typeof (candidate.expect as { objectContaining?: unknown })\n .objectContaining === 'function'\n ) {\n return {\n describe:\n candidate.describe as PaymentBackendConformanceTestApi['describe'],\n expect: candidate.expect as ConformanceExpect,\n it: candidate.it as PaymentBackendConformanceTestApi['it'],\n };\n }\n\n throw new Error(\n 'definePaymentBackendConformanceTests requires a test API. Pass { describe, expect, it } from Vitest or enable compatible test globals.',\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ export type PaymentSettlementShape = 'address' | 'url' | 'psbt';
2
+ export type PaymentStatus = 'pending' | 'processing' | 'confirmed' | 'failed' | 'expired' | 'refunded' | 'requires_action';
3
+ export interface PaymentConfirmationLatency {
4
+ expectedSeconds: number;
5
+ minConfirmations?: number;
6
+ maxExpectedSeconds?: number;
7
+ description?: string;
8
+ }
9
+ export interface PaymentBackendCapabilities {
10
+ id: string;
11
+ displayName: string;
12
+ settlementCurrency: string;
13
+ supportedSettlementCurrencies?: string[];
14
+ chain: string;
15
+ settlementShape: PaymentSettlementShape;
16
+ x402Capable: boolean;
17
+ confirmationLatency: PaymentConfirmationLatency;
18
+ supportsRefunds: boolean;
19
+ supportsPayouts: boolean;
20
+ supportsWebhooks: boolean;
21
+ metadata?: Record<string, unknown>;
22
+ }
23
+ export interface CreatePaymentOptionInput {
24
+ quoteId: string;
25
+ amount: number;
26
+ currency: string;
27
+ expiresAt: Date | string;
28
+ idempotencyKey?: string;
29
+ buyerEmail?: string;
30
+ description?: string;
31
+ successUrl?: string;
32
+ cancelUrl?: string;
33
+ metadata?: Record<string, string | number | boolean | null | undefined>;
34
+ }
35
+ export interface PaymentOption {
36
+ backendId: string;
37
+ quoteId: string;
38
+ payTo: string;
39
+ settlementShape: PaymentSettlementShape;
40
+ settlementCurrency: string;
41
+ settlementAmount: number;
42
+ amount: number;
43
+ currency: string;
44
+ expiresAt: Date;
45
+ memo?: string;
46
+ providerPaymentId?: string;
47
+ paymentUri?: string;
48
+ metadata?: Record<string, unknown>;
49
+ }
50
+ export interface PaymentStatusResult {
51
+ backendId: string;
52
+ quoteId: string;
53
+ payTo: string;
54
+ status: PaymentStatus;
55
+ settlementCurrency: string;
56
+ settlementAmount?: number;
57
+ receivedAmount?: number;
58
+ amount?: number;
59
+ currency?: string;
60
+ requiredConfirmations?: number;
61
+ confirmations?: number;
62
+ transactionId?: string;
63
+ providerPaymentId?: string;
64
+ updatedAt: Date;
65
+ raw?: unknown;
66
+ }
67
+ export interface PaymentStatusContext {
68
+ settlementAmount?: number;
69
+ amount?: number;
70
+ currency?: string;
71
+ expiresAt?: Date | string;
72
+ providerPaymentId?: string;
73
+ requiredConfirmations?: number;
74
+ searchStartBlock?: string | number | bigint;
75
+ metadata?: Record<string, unknown>;
76
+ }
77
+ export interface WatchPaymentInput {
78
+ quoteId: string;
79
+ payTo: string;
80
+ signal?: AbortSignal;
81
+ pollIntervalMs?: number;
82
+ timeoutMs?: number;
83
+ statusContext?: PaymentStatusContext;
84
+ }
85
+ export interface PaymentEvent extends PaymentStatusResult {
86
+ event: 'status' | 'confirmed' | 'failed' | 'expired' | 'refunded' | 'timeout';
87
+ }
88
+ export interface PaymentWebhookEvent {
89
+ id?: string;
90
+ deliveryId?: string;
91
+ invoiceId?: string;
92
+ quoteId?: string;
93
+ type?: string;
94
+ status: PaymentStatus;
95
+ providerPaymentId?: string;
96
+ duplicate?: boolean;
97
+ raw: unknown;
98
+ }
99
+ export interface VerifyX402ProofInput {
100
+ paymentHeader: string;
101
+ quoteId: string;
102
+ payTo: string;
103
+ amount: number;
104
+ currency: string;
105
+ resource?: string;
106
+ method?: string;
107
+ network?: string;
108
+ scheme?: string;
109
+ expiresAt?: Date | string;
110
+ }
111
+ export interface X402VerificationResult {
112
+ valid: boolean;
113
+ backendId: string;
114
+ quoteId: string;
115
+ payTo: string;
116
+ transactionId?: string;
117
+ payer?: string;
118
+ amount?: number;
119
+ currency?: string;
120
+ network?: string;
121
+ reason?: string;
122
+ raw?: unknown;
123
+ }
124
+ export interface SendPayoutInput {
125
+ destination: string;
126
+ amount: number;
127
+ currency?: string;
128
+ quoteId?: string;
129
+ idempotencyKey?: string;
130
+ memo?: string;
131
+ metadata?: Record<string, string | number | boolean | null | undefined>;
132
+ }
133
+ export interface PayoutResult {
134
+ backendId: string;
135
+ status: 'submitted' | 'pending_signature' | 'requires_action' | 'failed';
136
+ payoutId?: string;
137
+ transactionId?: string;
138
+ psbt?: string;
139
+ destination: string;
140
+ amount: number;
141
+ currency: string;
142
+ raw?: unknown;
143
+ }
144
+ export interface RefundPaymentInput {
145
+ paymentId?: string;
146
+ transactionId?: string;
147
+ destination?: string;
148
+ amount?: number;
149
+ currency?: string;
150
+ idempotencyKey?: string;
151
+ reason?: string;
152
+ metadata?: Record<string, string | number | boolean | null | undefined>;
153
+ }
154
+ export interface RefundResult {
155
+ backendId: string;
156
+ status: 'submitted' | 'succeeded' | 'failed' | 'requires_action';
157
+ refundId?: string;
158
+ transactionId?: string;
159
+ amount?: number;
160
+ currency?: string;
161
+ raw?: unknown;
162
+ }
163
+ export interface PaymentBackend {
164
+ readonly capabilities: PaymentBackendCapabilities;
165
+ createPaymentOption(input: CreatePaymentOptionInput): Promise<PaymentOption>;
166
+ watchPayment(input: WatchPaymentInput): AsyncIterable<PaymentEvent>;
167
+ getStatus(quoteId: string, payTo: string, context?: PaymentStatusContext): Promise<PaymentStatusResult>;
168
+ verifyX402Proof?(input: VerifyX402ProofInput): Promise<X402VerificationResult>;
169
+ sendPayout(input: SendPayoutInput): Promise<PayoutResult>;
170
+ refundPayment?(input: RefundPaymentInput): Promise<RefundResult>;
171
+ parseWebhookEvent?(payload: string, signature?: string): PaymentWebhookEvent;
172
+ }
173
+ export type PaymentBackendFactory<TOptions> = (options: TOptions) => PaymentBackend | Promise<PaymentBackend>;
174
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/metadata.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@happyvertical/payments",
3
+ "path": "packages/payments",
4
+ "position": {
5
+ "index": 20,
6
+ "count": 30
7
+ },
8
+ "description": "Payment backend abstraction with adapters for Base USDC, BTCPay Server, and Stripe",
9
+ "provides": [
10
+ "Payment backend abstraction with adapters for Base USDC, BTCPay Server, and Stripe"
11
+ ],
12
+ "implements": [],
13
+ "requires": {
14
+ "workspace": [],
15
+ "externalHappyVertical": [],
16
+ "external": [
17
+ "@noble/curves",
18
+ "@noble/hashes",
19
+ "@scure/bip32"
20
+ ]
21
+ },
22
+ "dependents": [],
23
+ "stability": {
24
+ "level": "stable",
25
+ "reason": "Primary package surface is described as implemented and production-oriented."
26
+ },
27
+ "keywords": [
28
+ "payments"
29
+ ]
30
+ }
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "@happyvertical/payments",
3
+ "version": "0.74.8",
4
+ "description": "Payment backend abstraction with adapters for Base USDC, BTCPay Server, and Stripe",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./base-usdc": {
14
+ "types": "./dist/adapters/base-usdc.d.ts",
15
+ "import": "./dist/adapters/base-usdc.js"
16
+ },
17
+ "./btc": {
18
+ "types": "./dist/adapters/btc.d.ts",
19
+ "import": "./dist/adapters/btc.js"
20
+ },
21
+ "./stripe": {
22
+ "types": "./dist/adapters/stripe.d.ts",
23
+ "import": "./dist/adapters/stripe.js"
24
+ },
25
+ "./testing": {
26
+ "types": "./dist/testing/conformance.d.ts",
27
+ "import": "./dist/testing/conformance.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE",
34
+ "AGENT.md",
35
+ "metadata.json"
36
+ ],
37
+ "publishConfig": {
38
+ "registry": "https://registry.npmjs.org",
39
+ "access": "public"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/happyvertical/sdk.git",
44
+ "directory": "packages/payments"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/happyvertical/sdk/issues"
48
+ },
49
+ "homepage": "https://github.com/happyvertical/sdk/tree/main/packages/payments#readme",
50
+ "license": "MIT",
51
+ "peerDependencies": {
52
+ "@noble/curves": "~2.0.1",
53
+ "@noble/hashes": "~2.0.1",
54
+ "@scure/bip32": "~2.0.1"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "@noble/curves": {
58
+ "optional": true
59
+ },
60
+ "@noble/hashes": {
61
+ "optional": true
62
+ },
63
+ "@scure/bip32": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "devDependencies": {
68
+ "@noble/curves": "2.0.1",
69
+ "@noble/hashes": "2.0.1",
70
+ "@scure/bip32": "2.0.1",
71
+ "@types/node": "24.12.2",
72
+ "@vitest/coverage-v8": "4.1.5",
73
+ "typescript": "^5.9.3",
74
+ "vite": "7.3.2",
75
+ "vite-plugin-dts": "4.5.4",
76
+ "vitest": "^4.1.5"
77
+ },
78
+ "scripts": {
79
+ "test": "npx vitest run",
80
+ "test:watch": "npx vitest",
81
+ "build": "vite build",
82
+ "build:watch": "vite build --watch",
83
+ "docs": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules",
84
+ "docs:watch": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules --watch",
85
+ "clean": "rm -rf dist docs",
86
+ "dev": "npm run build:watch & npm run test:watch"
87
+ }
88
+ }