@genesis-tech/genesispay-seller 0.8.0
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.
- package/CHANGELOG.md +330 -0
- package/LICENSE +21 -0
- package/README.md +429 -0
- package/dist/client.d.ts +275 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +541 -0
- package/dist/client.js.map +1 -0
- package/dist/customers.d.ts +41 -0
- package/dist/customers.d.ts.map +1 -0
- package/dist/customers.js +76 -0
- package/dist/customers.js.map +1 -0
- package/dist/errors.d.ts +63 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +162 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/invoices.d.ts +80 -0
- package/dist/invoices.d.ts.map +1 -0
- package/dist/invoices.js +133 -0
- package/dist/invoices.js.map +1 -0
- package/dist/mandate-gate.d.ts +49 -0
- package/dist/mandate-gate.d.ts.map +1 -0
- package/dist/mandate-gate.js +109 -0
- package/dist/mandate-gate.js.map +1 -0
- package/dist/mandates.d.ts +172 -0
- package/dist/mandates.d.ts.map +1 -0
- package/dist/mandates.js +213 -0
- package/dist/mandates.js.map +1 -0
- package/dist/networks.d.ts +10 -0
- package/dist/networks.d.ts.map +1 -0
- package/dist/networks.js +22 -0
- package/dist/networks.js.map +1 -0
- package/dist/payment-gate.d.ts +67 -0
- package/dist/payment-gate.d.ts.map +1 -0
- package/dist/payment-gate.js +106 -0
- package/dist/payment-gate.js.map +1 -0
- package/dist/peerpay-settlement.d.ts +27 -0
- package/dist/peerpay-settlement.d.ts.map +1 -0
- package/dist/peerpay-settlement.js +100 -0
- package/dist/peerpay-settlement.js.map +1 -0
- package/dist/plans.d.ts +68 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +127 -0
- package/dist/plans.js.map +1 -0
- package/dist/resource.d.ts +47 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +71 -0
- package/dist/resource.js.map +1 -0
- package/dist/usdc-amount.d.ts +7 -0
- package/dist/usdc-amount.d.ts.map +1 -0
- package/dist/usdc-amount.js +21 -0
- package/dist/usdc-amount.js.map +1 -0
- package/dist/webhooks.d.ts +277 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +223 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// `peerpay.customers.*` — reusable billing contacts over `/api/v1/customers`.
|
|
2
|
+
import { PeerPayConfigError } from "./errors.js";
|
|
3
|
+
import { asRecord, optionalMetadata, optionalString, requiredString, } from "./resource.js";
|
|
4
|
+
export function createCustomersResource(request) {
|
|
5
|
+
return {
|
|
6
|
+
create: async (input) => customerRequest(request, "POST", "/api/v1/customers", input, "create a customer"),
|
|
7
|
+
list: async () => {
|
|
8
|
+
const body = await request({
|
|
9
|
+
path: "/api/v1/customers",
|
|
10
|
+
operation: "GET /api/v1/customers",
|
|
11
|
+
action: "list customers",
|
|
12
|
+
});
|
|
13
|
+
const rows = asRecord(body)?.customers;
|
|
14
|
+
if (!Array.isArray(rows)) {
|
|
15
|
+
throw new PeerPayConfigError(`GenesisPay GET /api/v1/customers returned no customers array: ${JSON.stringify(body)}`);
|
|
16
|
+
}
|
|
17
|
+
return rows
|
|
18
|
+
.map(asRecord)
|
|
19
|
+
.filter((row) => Boolean(row?.publicId))
|
|
20
|
+
.map(toCustomer);
|
|
21
|
+
},
|
|
22
|
+
retrieve: async (publicId) => {
|
|
23
|
+
const id = requirePublicId(publicId, "customers.retrieve");
|
|
24
|
+
return customerRequest(request, "GET", `/api/v1/customers/${encodeURIComponent(id)}`, undefined, `retrieve customer "${id}"`);
|
|
25
|
+
},
|
|
26
|
+
update: async (publicId, input) => {
|
|
27
|
+
const id = requirePublicId(publicId, "customers.update");
|
|
28
|
+
return customerRequest(request, "PATCH", `/api/v1/customers/${encodeURIComponent(id)}`, input, `update customer "${id}"`);
|
|
29
|
+
},
|
|
30
|
+
archive: async (publicId) => {
|
|
31
|
+
const id = requirePublicId(publicId, "customers.archive");
|
|
32
|
+
return customerRequest(request, "POST", `/api/v1/customers/${encodeURIComponent(id)}/archive`, undefined, `archive customer "${id}"`);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function customerRequest(request, method, path, body, action) {
|
|
37
|
+
const response = await request({
|
|
38
|
+
method,
|
|
39
|
+
path,
|
|
40
|
+
operation: `${method} ${path}`,
|
|
41
|
+
action,
|
|
42
|
+
...(body === undefined ? {} : { body }),
|
|
43
|
+
});
|
|
44
|
+
const raw = asRecord(asRecord(response)?.customer);
|
|
45
|
+
if (!raw?.publicId) {
|
|
46
|
+
throw new PeerPayConfigError(`GenesisPay ${method} ${path} returned no customer: ${JSON.stringify(response)}`);
|
|
47
|
+
}
|
|
48
|
+
return toCustomer(raw);
|
|
49
|
+
}
|
|
50
|
+
function requirePublicId(publicId, method) {
|
|
51
|
+
const id = publicId?.trim();
|
|
52
|
+
if (!id) {
|
|
53
|
+
throw new PeerPayConfigError(`${method}(publicId) requires the publicId returned by customers.create().`);
|
|
54
|
+
}
|
|
55
|
+
return id;
|
|
56
|
+
}
|
|
57
|
+
export function toCustomer(raw) {
|
|
58
|
+
return {
|
|
59
|
+
id: requiredString(raw.id),
|
|
60
|
+
publicId: requiredString(raw.publicId),
|
|
61
|
+
name: requiredString(raw.name),
|
|
62
|
+
email: requiredString(raw.email),
|
|
63
|
+
companyName: optionalString(raw.companyName),
|
|
64
|
+
addressLine1: optionalString(raw.addressLine1),
|
|
65
|
+
addressLine2: optionalString(raw.addressLine2),
|
|
66
|
+
city: optionalString(raw.city),
|
|
67
|
+
postalCode: optionalString(raw.postalCode),
|
|
68
|
+
countryCode: optionalString(raw.countryCode),
|
|
69
|
+
taxId: optionalString(raw.taxId),
|
|
70
|
+
metadata: optionalMetadata(raw.metadata),
|
|
71
|
+
createdAt: requiredString(raw.createdAt),
|
|
72
|
+
updatedAt: requiredString(raw.updatedAt),
|
|
73
|
+
archivedAt: optionalString(raw.archivedAt),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=customers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customers.js","sourceRoot":"","sources":["../src/customers.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Missing/invalid key, unresolvable prod URL, or unreachable backend. */
|
|
2
|
+
export declare class PeerPayConfigError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The requested resource does not exist (HTTP 404). Kept separate from
|
|
7
|
+
* `PeerPayConfigError` on purpose: polling `checkout.retrieve()` for an unknown
|
|
8
|
+
* publicId is an ordinary application case and must stay distinguishable from
|
|
9
|
+
* "the key is broken / the backend is unreachable".
|
|
10
|
+
*/
|
|
11
|
+
export declare class PeerPayNotFoundError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/** Asset-integrity, mode↔network, or expectedPayTo-pin mismatch — a money-safety stop. */
|
|
15
|
+
export declare class PeerPayNetworkSafetyError extends Error {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
/** One rejected field, as the API reports it. `path` is dot-joined ("metadata.orderId"). */
|
|
19
|
+
export type PeerPayValidationIssue = {
|
|
20
|
+
path: string;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The request was well-formed but the input was rejected — HTTP 422 for a body,
|
|
25
|
+
* or HTTP 400 with field `issues` for a query string.
|
|
26
|
+
*
|
|
27
|
+
* `issues` is the server's structured list — the whole point of the class: 21
|
|
28
|
+
* metadata keys and a malformed wallet must not look the same to a caller that
|
|
29
|
+
* wants to surface the offending field back to its own user.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PeerPayValidationError extends Error {
|
|
32
|
+
readonly issues: PeerPayValidationIssue[];
|
|
33
|
+
constructor(message: string, issues?: PeerPayValidationIssue[]);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The API key exceeded its rate limit (HTTP 429).
|
|
37
|
+
*
|
|
38
|
+
* `retryAfterSeconds` mirrors the server's `Retry-After` header. It is `null`
|
|
39
|
+
* when the header is missing or unparseable — never a guessed default, because
|
|
40
|
+
* a caller sleeping on a made-up number is worse than one that backs off with
|
|
41
|
+
* its own policy.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PeerPayRateLimitError extends Error {
|
|
44
|
+
readonly retryAfterSeconds: number | null;
|
|
45
|
+
constructor(message: string, retryAfterSeconds: number | null);
|
|
46
|
+
}
|
|
47
|
+
export type ThrowForErrorResponseOptions = {
|
|
48
|
+
/** Operation label used in messages, e.g. `POST /api/v1/links`. */
|
|
49
|
+
operation: string;
|
|
50
|
+
/** Replaces the generic 404 message with a case-specific hint. */
|
|
51
|
+
notFoundMessage?: string;
|
|
52
|
+
/** Appended to the message — a next step for the caller, not error detail. */
|
|
53
|
+
hint?: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Maps a non-OK response onto the right error class and throws it.
|
|
57
|
+
*
|
|
58
|
+
* Consumes the response body exactly once (as text, then optimistically as
|
|
59
|
+
* JSON) so a non-JSON error page still ends up in the message instead of
|
|
60
|
+
* blowing up the mapper.
|
|
61
|
+
*/
|
|
62
|
+
export declare function throwForErrorResponse(response: Response, options: ThrowForErrorResponseOptions): Promise<never>;
|
|
63
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AASA,0EAA0E;AAC1E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,0FAA0F;AAC1F,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,4FAA4F;AAC5F,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,MAAM,EAAE,sBAAsB,EAAE,CAAC;gBAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,sBAAsB,EAAO;CAKnE;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;gBAE9B,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;CAK9D;AAED,MAAM,MAAM,4BAA4B,GAAG;IACzC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAUF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,KAAK,CAAC,CA4ChB"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Typed errors for every GenesisPay HTTP call.
|
|
2
|
+
//
|
|
3
|
+
// One rule, one place: `throwForErrorResponse` is the single mapper from a
|
|
4
|
+
// non-OK `Response` to an error class, so every method (checkout today, plans
|
|
5
|
+
// and mandates tomorrow) fails the same way. A method that hand-rolls its own
|
|
6
|
+
// `throw new PeerPayConfigError(...)` for a non-OK status is a bug — 422 and
|
|
7
|
+
// 429 carry information (which field is wrong, how long to wait) that a generic
|
|
8
|
+
// config error throws away.
|
|
9
|
+
/** Missing/invalid key, unresolvable prod URL, or unreachable backend. */
|
|
10
|
+
export class PeerPayConfigError extends Error {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "PeerPayConfigError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The requested resource does not exist (HTTP 404). Kept separate from
|
|
18
|
+
* `PeerPayConfigError` on purpose: polling `checkout.retrieve()` for an unknown
|
|
19
|
+
* publicId is an ordinary application case and must stay distinguishable from
|
|
20
|
+
* "the key is broken / the backend is unreachable".
|
|
21
|
+
*/
|
|
22
|
+
export class PeerPayNotFoundError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "PeerPayNotFoundError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Asset-integrity, mode↔network, or expectedPayTo-pin mismatch — a money-safety stop. */
|
|
29
|
+
export class PeerPayNetworkSafetyError extends Error {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "PeerPayNetworkSafetyError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The request was well-formed but the input was rejected — HTTP 422 for a body,
|
|
37
|
+
* or HTTP 400 with field `issues` for a query string.
|
|
38
|
+
*
|
|
39
|
+
* `issues` is the server's structured list — the whole point of the class: 21
|
|
40
|
+
* metadata keys and a malformed wallet must not look the same to a caller that
|
|
41
|
+
* wants to surface the offending field back to its own user.
|
|
42
|
+
*/
|
|
43
|
+
export class PeerPayValidationError extends Error {
|
|
44
|
+
issues;
|
|
45
|
+
constructor(message, issues = []) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = "PeerPayValidationError";
|
|
48
|
+
this.issues = issues;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The API key exceeded its rate limit (HTTP 429).
|
|
53
|
+
*
|
|
54
|
+
* `retryAfterSeconds` mirrors the server's `Retry-After` header. It is `null`
|
|
55
|
+
* when the header is missing or unparseable — never a guessed default, because
|
|
56
|
+
* a caller sleeping on a made-up number is worse than one that backs off with
|
|
57
|
+
* its own policy.
|
|
58
|
+
*/
|
|
59
|
+
export class PeerPayRateLimitError extends Error {
|
|
60
|
+
retryAfterSeconds;
|
|
61
|
+
constructor(message, retryAfterSeconds) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = "PeerPayRateLimitError";
|
|
64
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Maps a non-OK response onto the right error class and throws it.
|
|
69
|
+
*
|
|
70
|
+
* Consumes the response body exactly once (as text, then optimistically as
|
|
71
|
+
* JSON) so a non-JSON error page still ends up in the message instead of
|
|
72
|
+
* blowing up the mapper.
|
|
73
|
+
*/
|
|
74
|
+
export async function throwForErrorResponse(response, options) {
|
|
75
|
+
const body = await readErrorBody(response);
|
|
76
|
+
const detail = body.message ?? body.text;
|
|
77
|
+
const suffix = detail ? `: ${detail}` : "";
|
|
78
|
+
const hint = options.hint ? ` ${options.hint}` : "";
|
|
79
|
+
if (response.status === 404) {
|
|
80
|
+
throw new PeerPayNotFoundError(options.notFoundMessage ??
|
|
81
|
+
`GenesisPay ${options.operation} returned 404 (not found)${suffix}${hint}`);
|
|
82
|
+
}
|
|
83
|
+
// 422 is a rejected *body*; 400 with `issues[]` is a rejected *query string*
|
|
84
|
+
// (`GET /api/v1/mandates` answers that way). Both mean "your input was wrong,
|
|
85
|
+
// here are the fields", so both become PeerPayValidationError — a caller that
|
|
86
|
+
// wants to show the offending parameter must not have to branch on status.
|
|
87
|
+
//
|
|
88
|
+
// The `issues.length` gate is what keeps this narrow: a 400 without structured
|
|
89
|
+
// detail ("Request body must be JSON.", "startingAfter is not a mandate of this
|
|
90
|
+
// account.") stays a PeerPayConfigError exactly as before, so nothing that was
|
|
91
|
+
// a config error yesterday changes class today.
|
|
92
|
+
if (response.status === 422 || (response.status === 400 && body.issues.length > 0)) {
|
|
93
|
+
throw new PeerPayValidationError(`GenesisPay ${options.operation} rejected the input (${response.status})${suffix}`, body.issues);
|
|
94
|
+
}
|
|
95
|
+
if (response.status === 429) {
|
|
96
|
+
const retryAfterSeconds = parseRetryAfterSeconds(response.headers?.get("retry-after") ?? null);
|
|
97
|
+
const wait = retryAfterSeconds === null ? "" : ` Retry after ${retryAfterSeconds}s.`;
|
|
98
|
+
throw new PeerPayRateLimitError(`GenesisPay ${options.operation} was rate limited (429)${suffix}${wait}`, retryAfterSeconds);
|
|
99
|
+
}
|
|
100
|
+
throw new PeerPayConfigError(`GenesisPay ${options.operation} failed: ${response.status}${suffix}${hint}`.trim());
|
|
101
|
+
}
|
|
102
|
+
async function readErrorBody(response) {
|
|
103
|
+
const text = (await response.text().catch(() => "")).trim();
|
|
104
|
+
if (!text)
|
|
105
|
+
return { text: "", message: null, issues: [] };
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(text);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return { text, message: null, issues: [] };
|
|
112
|
+
}
|
|
113
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
114
|
+
return { text, message: null, issues: [] };
|
|
115
|
+
}
|
|
116
|
+
const record = parsed;
|
|
117
|
+
const message = typeof record.error === "string" && record.error
|
|
118
|
+
? record.error
|
|
119
|
+
: typeof record.message === "string" && record.message
|
|
120
|
+
? record.message
|
|
121
|
+
: null;
|
|
122
|
+
return { text, message, issues: toValidationIssues(record.issues) };
|
|
123
|
+
}
|
|
124
|
+
/** Tolerant: anything that is not a `{path, message}` object is dropped, never thrown on. */
|
|
125
|
+
function toValidationIssues(value) {
|
|
126
|
+
if (!Array.isArray(value))
|
|
127
|
+
return [];
|
|
128
|
+
const issues = [];
|
|
129
|
+
for (const entry of value) {
|
|
130
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
131
|
+
continue;
|
|
132
|
+
const issue = entry;
|
|
133
|
+
if (typeof issue.message !== "string")
|
|
134
|
+
continue;
|
|
135
|
+
issues.push({
|
|
136
|
+
path: typeof issue.path === "string" ? issue.path : "",
|
|
137
|
+
message: issue.message,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return issues;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* `Retry-After` is either delta-seconds or an HTTP date (RFC 9110). GenesisPay
|
|
144
|
+
* sends seconds; the date form is parsed anyway so a proxy that rewrites the
|
|
145
|
+
* header does not degrade the value to `null`.
|
|
146
|
+
*/
|
|
147
|
+
function parseRetryAfterSeconds(header) {
|
|
148
|
+
if (!header)
|
|
149
|
+
return null;
|
|
150
|
+
const raw = header.trim();
|
|
151
|
+
if (!raw)
|
|
152
|
+
return null;
|
|
153
|
+
if (/^\d+$/.test(raw)) {
|
|
154
|
+
const seconds = Number(raw);
|
|
155
|
+
return Number.isSafeInteger(seconds) ? seconds : null;
|
|
156
|
+
}
|
|
157
|
+
const dateMs = Date.parse(raw);
|
|
158
|
+
if (Number.isNaN(dateMs))
|
|
159
|
+
return null;
|
|
160
|
+
return Math.max(0, Math.ceil((dateMs - Date.now()) / 1_000));
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { PeerPay, type PeerPayKeyMode, type PeerPayClientOptions, type SellerConfig, type CheckoutAmountInput, type CheckoutCreateInput, type CheckoutLink, type CheckoutSession, type CheckoutAttempt, type CheckoutAttemptStatus, type SimulatePaymentOptions, type GateConfig, type ResolvingGate, } from "./client.js";
|
|
2
|
+
export { type SubscriptionPlan, type SubscriptionPlanStatus, type PlanCreateInput, type PlansResource, } from "./plans.js";
|
|
3
|
+
export { type Customer, type CustomerCreateInput, type CustomerUpdateInput, type CustomersResource, } from "./customers.js";
|
|
4
|
+
export { type Invoice, type InvoiceStatus, type InvoiceLineInput, type InvoiceDraftInput, type InvoiceEmailDelivery, type InvoicesResource, } from "./invoices.js";
|
|
5
|
+
export { type Mandate, type MandateKind, type MandateStatus, type MandateCreateInput, type MandateCreateResult, type MandateCharge, type MandateChargeInput, type MandateChargeStatus, type MandateListOptions, type MandateListPage, type PermitTypedData, type MandatesResource, } from "./mandates.js";
|
|
6
|
+
export { PeerPayConfigError, PeerPayNetworkSafetyError, PeerPayNotFoundError, PeerPayValidationError, PeerPayRateLimitError, type PeerPayValidationIssue, } from "./errors.js";
|
|
7
|
+
export { constructEvent, isKnownPeerPayEventType, PEERPAY_EVENT_TYPES, PeerPaySignatureVerificationError, type PeerPayEvent, type PeerPayAnyEvent, type PeerPayUnknownEvent, type PeerPayEventType, type PeerPayPaymentEvent, type PeerPayMandateEvent, type PeerPayAgentPaymentEvent, type PeerPayPaymentEventData, type PeerPayMandateEventData, type ConstructEventOptions, } from "./webhooks.js";
|
|
8
|
+
export { createPaymentGate, type PaymentGate, type PaymentGateConfig, type SettlementContext, type SettlementVerification, type VerifySettlement, type WrapOptions, } from "./payment-gate.js";
|
|
9
|
+
export { peerPaySettlement, DEFAULT_FACILITATOR_BASE_URL, type PeerPaySettlementOptions, } from "./peerpay-settlement.js";
|
|
10
|
+
export { resolvePaymentGateNetwork, type PaymentGateNetwork, type PaymentGateNetworkConfig, } from "./networks.js";
|
|
11
|
+
export { parseUsdcAmountToMinorUnits } from "./usdc-amount.js";
|
|
12
|
+
export { createMandateGate, MANDATE_HEADER, type MandateChargeOutcome, type MandateGate, type MandateGateOptions, } from "./mandate-gate.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAMrB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAKvB,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,iCAAiC,EACjC,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @genesis-tech/genesispay-seller — framework-agnostic x402 payment gate.
|
|
2
|
+
export { PeerPay, } from "./client.js";
|
|
3
|
+
// Every SDK method throws from this set: 404 → NotFound, 422 (and 400 when the
|
|
4
|
+
// body carries structured `issues`) → Validation, 429 → RateLimit (with
|
|
5
|
+
// `retryAfterSeconds`), anything else → Config.
|
|
6
|
+
export { PeerPayConfigError, PeerPayNetworkSafetyError, PeerPayNotFoundError, PeerPayValidationError, PeerPayRateLimitError, } from "./errors.js";
|
|
7
|
+
export { constructEvent, isKnownPeerPayEventType, PEERPAY_EVENT_TYPES, PeerPaySignatureVerificationError, } from "./webhooks.js";
|
|
8
|
+
export { createPaymentGate, } from "./payment-gate.js";
|
|
9
|
+
export { peerPaySettlement, DEFAULT_FACILITATOR_BASE_URL, } from "./peerpay-settlement.js";
|
|
10
|
+
export { resolvePaymentGateNetwork, } from "./networks.js";
|
|
11
|
+
export { parseUsdcAmountToMinorUnits } from "./usdc-amount.js";
|
|
12
|
+
export { createMandateGate, MANDATE_HEADER, } from "./mandate-gate.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,EACL,OAAO,GAaR,MAAM,aAAa,CAAC;AA4CrB,+EAA+E;AAC/E,wEAAwE;AACxE,gDAAgD;AAChD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GAEtB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,iCAAiC,GAWlC,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,GAOlB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,4BAA4B,GAE7B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,yBAAyB,GAG1B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EACL,iBAAiB,EACjB,cAAc,GAIf,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type Customer } from "./customers.js";
|
|
2
|
+
import { type PeerPayRequest } from "./resource.js";
|
|
3
|
+
export type InvoiceStatus = "draft" | "open" | "past_due" | "paid" | "void" | "uncollectible";
|
|
4
|
+
export type InvoiceLineInput = {
|
|
5
|
+
description: string;
|
|
6
|
+
quantity: number;
|
|
7
|
+
/** Decimal amount in the invoice asset, as a string with up to 6 decimals. */
|
|
8
|
+
unitAmount: string;
|
|
9
|
+
};
|
|
10
|
+
export type InvoiceDraftInput = {
|
|
11
|
+
customerId: string;
|
|
12
|
+
asset?: "USDC" | "EURC";
|
|
13
|
+
/** ISO-8601 timestamp with an offset. */
|
|
14
|
+
dueAt: string;
|
|
15
|
+
discountBps?: number;
|
|
16
|
+
taxBps?: number;
|
|
17
|
+
memo?: string;
|
|
18
|
+
footer?: string;
|
|
19
|
+
lineItems: InvoiceLineInput[];
|
|
20
|
+
};
|
|
21
|
+
export type Invoice = {
|
|
22
|
+
id: string;
|
|
23
|
+
publicId: string;
|
|
24
|
+
invoiceNumber: string | null;
|
|
25
|
+
status: InvoiceStatus;
|
|
26
|
+
asset: "USDC" | "EURC";
|
|
27
|
+
chainId: number;
|
|
28
|
+
customer: Customer;
|
|
29
|
+
lineItems: Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
position: number;
|
|
32
|
+
description: string;
|
|
33
|
+
quantity: number;
|
|
34
|
+
unitAmountMinor: string;
|
|
35
|
+
amountMinor: string;
|
|
36
|
+
}>;
|
|
37
|
+
subtotalMinor: string;
|
|
38
|
+
discountBps: number;
|
|
39
|
+
discountMinor: string;
|
|
40
|
+
taxBps: number;
|
|
41
|
+
taxMinor: string;
|
|
42
|
+
totalMinor: string;
|
|
43
|
+
memo: string | null;
|
|
44
|
+
footer: string | null;
|
|
45
|
+
dueAt: string;
|
|
46
|
+
createdAt: string;
|
|
47
|
+
updatedAt: string;
|
|
48
|
+
finalizedAt: string | null;
|
|
49
|
+
paidAt: string | null;
|
|
50
|
+
voidedAt: string | null;
|
|
51
|
+
uncollectibleAt: string | null;
|
|
52
|
+
hostedInvoiceUrl: string | null;
|
|
53
|
+
pdfUrl: string | null;
|
|
54
|
+
payment: {
|
|
55
|
+
payUrl: string | null;
|
|
56
|
+
txHash: string | null;
|
|
57
|
+
payerWallet: string | null;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export type InvoiceEmailDelivery = {
|
|
61
|
+
id: string;
|
|
62
|
+
status: "sent";
|
|
63
|
+
providerMessageId: string | null;
|
|
64
|
+
sentAt: string | null;
|
|
65
|
+
};
|
|
66
|
+
export interface InvoicesResource {
|
|
67
|
+
create(input: InvoiceDraftInput): Promise<Invoice>;
|
|
68
|
+
list(): Promise<Invoice[]>;
|
|
69
|
+
retrieve(publicId: string): Promise<Invoice>;
|
|
70
|
+
update(publicId: string, input: InvoiceDraftInput): Promise<Invoice>;
|
|
71
|
+
finalize(publicId: string): Promise<Invoice>;
|
|
72
|
+
send(publicId: string, options: {
|
|
73
|
+
idempotencyKey: string;
|
|
74
|
+
}): Promise<InvoiceEmailDelivery>;
|
|
75
|
+
void(publicId: string): Promise<Invoice>;
|
|
76
|
+
markUncollectible(publicId: string): Promise<Invoice>;
|
|
77
|
+
}
|
|
78
|
+
export declare function createInvoicesResource(request: PeerPayRequest): InvoicesResource;
|
|
79
|
+
export declare function toInvoice(raw: Record<string, unknown>): Invoice;
|
|
80
|
+
//# sourceMappingURL=invoices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../src/invoices.ts"],"names":[],"mappings":"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"}
|
package/dist/invoices.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// `peerpay.invoices.*` — one-off invoice lifecycle over `/api/v1/invoices`.
|
|
2
|
+
import { PeerPayConfigError } from "./errors.js";
|
|
3
|
+
import { toCustomer } from "./customers.js";
|
|
4
|
+
import { asRecord, oneOf, optionalString, requiredString, toAmountString, toCount, } from "./resource.js";
|
|
5
|
+
export function createInvoicesResource(request) {
|
|
6
|
+
return {
|
|
7
|
+
create: async (input) => invoiceRequest(request, "POST", "/api/v1/invoices", input, "create an invoice"),
|
|
8
|
+
list: async () => {
|
|
9
|
+
const body = await request({
|
|
10
|
+
path: "/api/v1/invoices",
|
|
11
|
+
operation: "GET /api/v1/invoices",
|
|
12
|
+
action: "list invoices",
|
|
13
|
+
});
|
|
14
|
+
const rows = asRecord(body)?.invoices;
|
|
15
|
+
if (!Array.isArray(rows)) {
|
|
16
|
+
throw new PeerPayConfigError(`GenesisPay GET /api/v1/invoices returned no invoices array: ${JSON.stringify(body)}`);
|
|
17
|
+
}
|
|
18
|
+
return rows
|
|
19
|
+
.map(asRecord)
|
|
20
|
+
.filter((row) => Boolean(row?.publicId))
|
|
21
|
+
.map(toInvoice);
|
|
22
|
+
},
|
|
23
|
+
retrieve: async (publicId) => {
|
|
24
|
+
const id = requirePublicId(publicId, "invoices.retrieve");
|
|
25
|
+
return invoiceRequest(request, "GET", `/api/v1/invoices/${encodeURIComponent(id)}`, undefined, `retrieve invoice "${id}"`);
|
|
26
|
+
},
|
|
27
|
+
update: async (publicId, input) => {
|
|
28
|
+
const id = requirePublicId(publicId, "invoices.update");
|
|
29
|
+
return invoiceRequest(request, "PATCH", `/api/v1/invoices/${encodeURIComponent(id)}`, input, `update invoice "${id}"`);
|
|
30
|
+
},
|
|
31
|
+
finalize: async (publicId) => transition(request, publicId, "finalize", "finalize an invoice"),
|
|
32
|
+
void: async (publicId) => transition(request, publicId, "void", "void an invoice"),
|
|
33
|
+
markUncollectible: async (publicId) => transition(request, publicId, "mark-uncollectible", "mark an invoice uncollectible"),
|
|
34
|
+
send: async (publicId, options) => {
|
|
35
|
+
const id = requirePublicId(publicId, "invoices.send");
|
|
36
|
+
const idempotencyKey = options?.idempotencyKey?.trim();
|
|
37
|
+
if (!idempotencyKey) {
|
|
38
|
+
throw new PeerPayConfigError("invoices.send requires a non-empty idempotencyKey.");
|
|
39
|
+
}
|
|
40
|
+
const path = `/api/v1/invoices/${encodeURIComponent(id)}/send`;
|
|
41
|
+
const response = await request({
|
|
42
|
+
method: "POST",
|
|
43
|
+
path,
|
|
44
|
+
operation: `POST ${path}`,
|
|
45
|
+
action: `send invoice "${id}"`,
|
|
46
|
+
headers: { "idempotency-key": idempotencyKey },
|
|
47
|
+
});
|
|
48
|
+
const delivery = asRecord(asRecord(response)?.delivery);
|
|
49
|
+
if (!delivery?.id) {
|
|
50
|
+
throw new PeerPayConfigError(`GenesisPay POST ${path} returned no delivery: ${JSON.stringify(response)}`);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
id: requiredString(delivery.id),
|
|
54
|
+
status: "sent",
|
|
55
|
+
providerMessageId: optionalString(delivery.providerMessageId),
|
|
56
|
+
sentAt: optionalString(delivery.sentAt),
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function transition(request, publicId, transitionName, action) {
|
|
62
|
+
const id = requirePublicId(publicId, `invoices.${transitionName}`);
|
|
63
|
+
return invoiceRequest(request, "POST", `/api/v1/invoices/${encodeURIComponent(id)}/${transitionName}`, undefined, action);
|
|
64
|
+
}
|
|
65
|
+
async function invoiceRequest(request, method, path, body, action) {
|
|
66
|
+
const response = await request({
|
|
67
|
+
method,
|
|
68
|
+
path,
|
|
69
|
+
operation: `${method} ${path}`,
|
|
70
|
+
action,
|
|
71
|
+
...(body === undefined ? {} : { body }),
|
|
72
|
+
});
|
|
73
|
+
const raw = asRecord(asRecord(response)?.invoice);
|
|
74
|
+
if (!raw?.publicId) {
|
|
75
|
+
throw new PeerPayConfigError(`GenesisPay ${method} ${path} returned no invoice: ${JSON.stringify(response)}`);
|
|
76
|
+
}
|
|
77
|
+
return toInvoice(raw);
|
|
78
|
+
}
|
|
79
|
+
function requirePublicId(publicId, method) {
|
|
80
|
+
const id = publicId?.trim();
|
|
81
|
+
if (!id) {
|
|
82
|
+
throw new PeerPayConfigError(`${method}(publicId) requires the publicId returned by invoices.create().`);
|
|
83
|
+
}
|
|
84
|
+
return id;
|
|
85
|
+
}
|
|
86
|
+
export function toInvoice(raw) {
|
|
87
|
+
const customer = asRecord(raw.customer) ?? {};
|
|
88
|
+
const payment = asRecord(raw.payment) ?? {};
|
|
89
|
+
const lines = Array.isArray(raw.lineItems) ? raw.lineItems : [];
|
|
90
|
+
return {
|
|
91
|
+
id: requiredString(raw.id),
|
|
92
|
+
publicId: requiredString(raw.publicId),
|
|
93
|
+
invoiceNumber: optionalString(raw.invoiceNumber),
|
|
94
|
+
status: oneOf(raw.status, ["draft", "open", "past_due", "paid", "void", "uncollectible"], "draft"),
|
|
95
|
+
asset: oneOf(raw.asset, ["USDC", "EURC"], "USDC"),
|
|
96
|
+
chainId: toCount(raw.chainId),
|
|
97
|
+
customer: toCustomer(customer),
|
|
98
|
+
lineItems: lines
|
|
99
|
+
.map(asRecord)
|
|
100
|
+
.filter((line) => Boolean(line?.id))
|
|
101
|
+
.map((line) => ({
|
|
102
|
+
id: requiredString(line.id),
|
|
103
|
+
position: toCount(line.position),
|
|
104
|
+
description: requiredString(line.description),
|
|
105
|
+
quantity: toCount(line.quantity),
|
|
106
|
+
unitAmountMinor: toAmountString(line.unitAmountMinor),
|
|
107
|
+
amountMinor: toAmountString(line.amountMinor),
|
|
108
|
+
})),
|
|
109
|
+
subtotalMinor: toAmountString(raw.subtotalMinor),
|
|
110
|
+
discountBps: toCount(raw.discountBps),
|
|
111
|
+
discountMinor: toAmountString(raw.discountMinor),
|
|
112
|
+
taxBps: toCount(raw.taxBps),
|
|
113
|
+
taxMinor: toAmountString(raw.taxMinor),
|
|
114
|
+
totalMinor: toAmountString(raw.totalMinor),
|
|
115
|
+
memo: optionalString(raw.memo),
|
|
116
|
+
footer: optionalString(raw.footer),
|
|
117
|
+
dueAt: requiredString(raw.dueAt),
|
|
118
|
+
createdAt: requiredString(raw.createdAt),
|
|
119
|
+
updatedAt: requiredString(raw.updatedAt),
|
|
120
|
+
finalizedAt: optionalString(raw.finalizedAt),
|
|
121
|
+
paidAt: optionalString(raw.paidAt),
|
|
122
|
+
voidedAt: optionalString(raw.voidedAt),
|
|
123
|
+
uncollectibleAt: optionalString(raw.uncollectibleAt),
|
|
124
|
+
hostedInvoiceUrl: optionalString(raw.hostedInvoiceUrl),
|
|
125
|
+
pdfUrl: optionalString(raw.pdfUrl),
|
|
126
|
+
payment: {
|
|
127
|
+
payUrl: optionalString(payment.payUrl),
|
|
128
|
+
txHash: optionalString(payment.txHash),
|
|
129
|
+
payerWallet: optionalString(payment.payerWallet),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=invoices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoices.js","sourceRoot":"","sources":["../src/invoices.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mandate gate — the signature-free metered path for humans and subscriptions.
|
|
3
|
+
*
|
|
4
|
+
* Instead of demanding a fresh signed payment per request (the x402 gate), the
|
|
5
|
+
* caller presents a standing payment mandate id via the `PEERPAY-MANDATE`
|
|
6
|
+
* header. The gate debits the mandate through GenesisPay
|
|
7
|
+
* (`POST /api/v1/mandates/:id/charge`) — a non-custodial on-chain pull from
|
|
8
|
+
* the payer's wallet directly to yours — and only runs your handler once the
|
|
9
|
+
* charge settled. Combine with `createPaymentGate` to accept both per-call
|
|
10
|
+
* x402 payments and mandate-metered calls on one endpoint.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MANDATE_HEADER = "PEERPAY-MANDATE";
|
|
13
|
+
export type MandateGateOptions = {
|
|
14
|
+
/** Decimal charge per request, e.g. "0.08". */
|
|
15
|
+
amount: string;
|
|
16
|
+
/** Base URL of the GenesisPay app (your PEERPAY_BASE_URL). */
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
/** GenesisPay seller API key ("pp_sk_..."). */
|
|
19
|
+
apiKey: string;
|
|
20
|
+
/** Description attached to each charge (shows up in activity/usage). */
|
|
21
|
+
description?: string;
|
|
22
|
+
/** Override for testing; defaults to global fetch. */
|
|
23
|
+
fetchFn?: typeof fetch;
|
|
24
|
+
};
|
|
25
|
+
export type MandateChargeOutcome = {
|
|
26
|
+
ok: true;
|
|
27
|
+
charge: {
|
|
28
|
+
id: string;
|
|
29
|
+
amountMinor: string;
|
|
30
|
+
txHash: string;
|
|
31
|
+
};
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
status: number;
|
|
35
|
+
code?: string;
|
|
36
|
+
error: string;
|
|
37
|
+
};
|
|
38
|
+
export type MandateGate = {
|
|
39
|
+
/** Charges the mandate once. Exposed for custom flows. */
|
|
40
|
+
charge: (mandateId: string, resourceUrl?: string) => Promise<MandateChargeOutcome>;
|
|
41
|
+
/**
|
|
42
|
+
* Wraps a fetch-style handler: requests carrying a valid `PEERPAY-MANDATE`
|
|
43
|
+
* header are charged and passed through; requests without one get a 402
|
|
44
|
+
* JSON body explaining how to attach a mandate.
|
|
45
|
+
*/
|
|
46
|
+
wrap: (handler: (request: Request) => Response | Promise<Response>) => (request: Request) => Promise<Response>;
|
|
47
|
+
};
|
|
48
|
+
export declare function createMandateGate(options: MandateGateOptions): MandateGate;
|
|
49
|
+
//# sourceMappingURL=mandate-gate.d.ts.map
|