@primitivedotdev/sdk 1.6.0 → 1.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/README.md +137 -0
- package/dist/api/index.d.ts +4 -4
- package/dist/api/index.js +3 -3
- package/dist/{api-ClLMDF81.js → api-26ENR8Ph.js} +30 -1
- package/dist/contract/index.d.ts +2 -2
- package/dist/contract/index.js +1 -1
- package/dist/{errors-DyuAXctD.d.ts → errors-bXUNXAlf.d.ts} +1 -1
- package/dist/{index-iZWfb98V.d.ts → index-BDnY9HH-.d.ts} +30 -48
- package/dist/{index-BnbrY8kp.d.ts → index-C3ahy3ls.d.ts} +161 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/openapi/index.js +1 -1
- package/dist/{operations.generated-DQIrhCT5.js → operations.generated-Bu20uPOw.js} +304 -0
- package/dist/parser/index.d.ts +1 -1
- package/dist/{types-QT2ss9ho.d.ts → types-BjnIxPED.d.ts} +97 -2
- package/dist/webhook/index.d.ts +4 -4
- package/dist/webhook/index.js +2 -2
- package/dist/{webhook-CwjCyFv-.js → webhook-CiIPtegj.js} +155 -26
- package/dist/x402/index.d.ts +195 -1
- package/dist/x402/index.js +279 -27
- package/package.json +1 -1
|
@@ -8132,6 +8132,94 @@ function verifyDownloadToken(params) {
|
|
|
8132
8132
|
return { valid: true };
|
|
8133
8133
|
}
|
|
8134
8134
|
//#endregion
|
|
8135
|
+
//#region src/webhook/events.ts
|
|
8136
|
+
/**
|
|
8137
|
+
* The five first-party email events (subject = an email).
|
|
8138
|
+
*/
|
|
8139
|
+
const EMAIL_EVENT_TYPES = [
|
|
8140
|
+
"email.received",
|
|
8141
|
+
"email.bounced",
|
|
8142
|
+
"email.tls_report",
|
|
8143
|
+
"email.dmarc_report",
|
|
8144
|
+
"email.dmarc_failure"
|
|
8145
|
+
];
|
|
8146
|
+
/**
|
|
8147
|
+
* The two x402 settlement-notification events (subject = a payment). Emitted for
|
|
8148
|
+
* both the synthetic API pay flow and the email-native settle path.
|
|
8149
|
+
*/
|
|
8150
|
+
const PAYMENT_EVENT_TYPES = ["payment.settled", "payment.failed"];
|
|
8151
|
+
/**
|
|
8152
|
+
* The interaction step events (subject = an interaction). One event per accepted
|
|
8153
|
+
* protocol step, named `interaction.<protocolShort>.<suffix>`.
|
|
8154
|
+
*
|
|
8155
|
+
* The x402 slice covers the payment lifecycle a payee/payer cares about; the ack
|
|
8156
|
+
* slice covers the acknowledgement protocols.
|
|
8157
|
+
*/
|
|
8158
|
+
const INTERACTION_EVENT_TYPES = [
|
|
8159
|
+
"interaction.ack.acked",
|
|
8160
|
+
"interaction.ack.canceled",
|
|
8161
|
+
"interaction.ack.expired",
|
|
8162
|
+
"interaction.ack.received",
|
|
8163
|
+
"interaction.ack.requested",
|
|
8164
|
+
"interaction.x402.challenge",
|
|
8165
|
+
"interaction.x402.declined",
|
|
8166
|
+
"interaction.x402.expired",
|
|
8167
|
+
"interaction.x402.payment",
|
|
8168
|
+
"interaction.x402.rejected",
|
|
8169
|
+
"interaction.x402.settled",
|
|
8170
|
+
"interaction.x402.verify_timeout"
|
|
8171
|
+
];
|
|
8172
|
+
/**
|
|
8173
|
+
* The full enumerated catalog of every current webhook event type: the five
|
|
8174
|
+
* email.*, the two payment.*, and every interaction.<protocol>.<suffix>.
|
|
8175
|
+
*/
|
|
8176
|
+
const WEBHOOK_EVENT_TYPES = [
|
|
8177
|
+
...EMAIL_EVENT_TYPES,
|
|
8178
|
+
...PAYMENT_EVENT_TYPES,
|
|
8179
|
+
...INTERACTION_EVENT_TYPES
|
|
8180
|
+
];
|
|
8181
|
+
const WEBHOOK_EVENT_TYPE_SET = new Set(WEBHOOK_EVENT_TYPES);
|
|
8182
|
+
/** True if `eventType` is a known current catalog value. */
|
|
8183
|
+
function isKnownWebhookEventType(eventType) {
|
|
8184
|
+
return eventType != null && WEBHOOK_EVENT_TYPE_SET.has(eventType);
|
|
8185
|
+
}
|
|
8186
|
+
function eventName(event) {
|
|
8187
|
+
if (typeof event !== "object" || event === null) return void 0;
|
|
8188
|
+
const value = event.event;
|
|
8189
|
+
return typeof value === "string" ? value : void 0;
|
|
8190
|
+
}
|
|
8191
|
+
/**
|
|
8192
|
+
* Type guard for the `email.received` event. Confirms the discriminator AND
|
|
8193
|
+
* that the body validates against the canonical schema, so a payload that names
|
|
8194
|
+
* itself `email.received` but is malformed does not narrow.
|
|
8195
|
+
*/
|
|
8196
|
+
function isEmailReceivedEvent(event) {
|
|
8197
|
+
if (eventName(event) !== "email.received") return false;
|
|
8198
|
+
try {
|
|
8199
|
+
validateEmailReceivedEvent(event);
|
|
8200
|
+
return true;
|
|
8201
|
+
} catch {
|
|
8202
|
+
return false;
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8205
|
+
/** Type guard for any `payment.*` event. */
|
|
8206
|
+
function isPaymentEvent(event) {
|
|
8207
|
+
const name = eventName(event);
|
|
8208
|
+
return name === "payment.settled" || name === "payment.failed";
|
|
8209
|
+
}
|
|
8210
|
+
/** Type guard for the `payment.settled` event. */
|
|
8211
|
+
function isPaymentSettledEvent(event) {
|
|
8212
|
+
return eventName(event) === "payment.settled";
|
|
8213
|
+
}
|
|
8214
|
+
/** Type guard for the `payment.failed` event. */
|
|
8215
|
+
function isPaymentFailedEvent(event) {
|
|
8216
|
+
return eventName(event) === "payment.failed";
|
|
8217
|
+
}
|
|
8218
|
+
/** Type guard for any `interaction.x402.*` event. */
|
|
8219
|
+
function isInteractionX402Event(event) {
|
|
8220
|
+
return eventName(event)?.startsWith("interaction.x402.") ?? false;
|
|
8221
|
+
}
|
|
8222
|
+
//#endregion
|
|
8135
8223
|
//#region src/webhook/encoding.ts
|
|
8136
8224
|
/**
|
|
8137
8225
|
* Buffer encoding utilities
|
|
@@ -10014,40 +10102,52 @@ const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/
|
|
|
10014
10102
|
* }
|
|
10015
10103
|
* ```
|
|
10016
10104
|
*/
|
|
10017
|
-
function parseWebhookEvent(input) {
|
|
10105
|
+
function parseWebhookEvent(input, eventType) {
|
|
10018
10106
|
if (input === null) throw new WebhookPayloadError("PAYLOAD_NULL", "Received null instead of webhook payload", "Check that your request body variable is defined.");
|
|
10019
10107
|
if (input === void 0) throw new WebhookPayloadError("PAYLOAD_UNDEFINED", "Received undefined instead of webhook payload", "Make sure you're passing the request body to parseWebhookEvent()");
|
|
10020
10108
|
if (Array.isArray(input)) throw new WebhookPayloadError("PAYLOAD_IS_ARRAY", "Received array instead of webhook payload object", "Webhook payloads must be objects, not arrays.");
|
|
10021
10109
|
if (typeof input !== "object") throw new WebhookPayloadError("PAYLOAD_WRONG_TYPE", `Received ${typeof input} instead of webhook payload object`, "Webhook payloads must be objects.");
|
|
10022
10110
|
const obj = input;
|
|
10023
|
-
|
|
10024
|
-
|
|
10111
|
+
const resolvedEvent = typeof eventType === "string" && eventType || (typeof obj.event === "string" ? obj.event : void 0);
|
|
10112
|
+
if (!resolvedEvent) throw new WebhookPayloadError("PAYLOAD_MISSING_EVENT", "Missing event discriminator: no X-Webhook-Event header and no 'event' field in payload", "Pass the X-Webhook-Event header (the canonical discriminator) or call handleWebhookEvent, which reads it for you.");
|
|
10113
|
+
switch (resolvedEvent) {
|
|
10025
10114
|
case "email.received": return validateEmailReceivedEvent(input);
|
|
10026
|
-
|
|
10115
|
+
case "payment.settled":
|
|
10116
|
+
case "payment.failed": return {
|
|
10117
|
+
...obj,
|
|
10118
|
+
event: resolvedEvent
|
|
10119
|
+
};
|
|
10120
|
+
default:
|
|
10121
|
+
if (isKnownWebhookEventType(resolvedEvent)) return {
|
|
10122
|
+
...obj,
|
|
10123
|
+
event: resolvedEvent
|
|
10124
|
+
};
|
|
10125
|
+
return {
|
|
10126
|
+
...obj,
|
|
10127
|
+
event: resolvedEvent
|
|
10128
|
+
};
|
|
10027
10129
|
}
|
|
10028
10130
|
}
|
|
10029
10131
|
/**
|
|
10030
|
-
*
|
|
10031
|
-
*
|
|
10032
|
-
*
|
|
10033
|
-
* ```typescript
|
|
10034
|
-
* const event = parseWebhookEvent(payload);
|
|
10035
|
-
* if (isEmailReceivedEvent(event)) {
|
|
10036
|
-
* // TypeScript knows event is EmailReceivedEvent
|
|
10037
|
-
* console.log(event.email.headers.subject);
|
|
10038
|
-
* }
|
|
10039
|
-
* ```
|
|
10132
|
+
* The header that names the webhook event for ALL event families
|
|
10133
|
+
* (`email.*`, `payment.*`, `interaction.*`). It is the primary discriminator
|
|
10134
|
+
* the parser keys on, because the stored body is sent verbatim with no envelope.
|
|
10040
10135
|
*/
|
|
10041
|
-
|
|
10042
|
-
if (typeof event !== "object" || event === null || !("event" in event) || event.event !== "email.received") return false;
|
|
10043
|
-
try {
|
|
10044
|
-
validateEmailReceivedEvent(event);
|
|
10045
|
-
return true;
|
|
10046
|
-
} catch {
|
|
10047
|
-
return false;
|
|
10048
|
-
}
|
|
10049
|
-
}
|
|
10136
|
+
const WEBHOOK_EVENT_HEADER = "X-Webhook-Event";
|
|
10050
10137
|
const SIGNATURE_HEADER_NAMES = ["primitive-signature", "mymx-signature"];
|
|
10138
|
+
/**
|
|
10139
|
+
* Read the `X-Webhook-Event` header value (case-insensitive). Returns null when
|
|
10140
|
+
* the header is absent.
|
|
10141
|
+
*/
|
|
10142
|
+
function getEventHeader(headers) {
|
|
10143
|
+
if (headers instanceof Headers) return headers.get("x-webhook-event");
|
|
10144
|
+
const obj = headers;
|
|
10145
|
+
const key = Object.keys(obj).find((k) => k.toLowerCase() === "x-webhook-event");
|
|
10146
|
+
if (!key) return null;
|
|
10147
|
+
const value = obj[key];
|
|
10148
|
+
if (Array.isArray(value)) return value[0] ?? null;
|
|
10149
|
+
return value ?? null;
|
|
10150
|
+
}
|
|
10051
10151
|
const STANDARD_WEBHOOKS_HEADER_NAMES = [
|
|
10052
10152
|
"webhook-signature",
|
|
10053
10153
|
"webhook-id",
|
|
@@ -10160,7 +10260,7 @@ function getStandardWebhooksHeaders(headers) {
|
|
|
10160
10260
|
* });
|
|
10161
10261
|
* ```
|
|
10162
10262
|
*/
|
|
10163
|
-
function
|
|
10263
|
+
function verifyWebhookRequest(options) {
|
|
10164
10264
|
const { body, headers, secret, toleranceSeconds } = options;
|
|
10165
10265
|
const swHeaders = getStandardWebhooksHeaders(headers);
|
|
10166
10266
|
if (swHeaders) verifyStandardWebhooksSignature({
|
|
@@ -10177,7 +10277,36 @@ function handleWebhook(options) {
|
|
|
10177
10277
|
secret,
|
|
10178
10278
|
toleranceSeconds
|
|
10179
10279
|
});
|
|
10180
|
-
|
|
10280
|
+
}
|
|
10281
|
+
/**
|
|
10282
|
+
* Verify, then parse any webhook event into a typed value.
|
|
10283
|
+
*
|
|
10284
|
+
* Unlike {@link handleWebhook}, this returns the full {@link WebhookEvent}
|
|
10285
|
+
* union, so it handles `payment.*` and `interaction.x402.*` events in addition
|
|
10286
|
+
* to `email.*`. The flow is:
|
|
10287
|
+
*
|
|
10288
|
+
* 1. Verify the signature over the RAW body (works for every event family).
|
|
10289
|
+
* 2. Parse the JSON body.
|
|
10290
|
+
* 3. Classify on the `X-Webhook-Event` HEADER (the primary discriminator),
|
|
10291
|
+
* returning a typed event for known types and an UnknownEvent for the rest.
|
|
10292
|
+
*
|
|
10293
|
+
* @example
|
|
10294
|
+
* ```typescript
|
|
10295
|
+
* const event = handleWebhookEvent({ body, headers, secret });
|
|
10296
|
+
* if (isPaymentSettledEvent(event)) {
|
|
10297
|
+
* // typed PaymentSettledEvent
|
|
10298
|
+
* } else if (isInteractionX402Event(event)) {
|
|
10299
|
+
* // typed interaction.x402.* event
|
|
10300
|
+
* }
|
|
10301
|
+
* ```
|
|
10302
|
+
*/
|
|
10303
|
+
function handleWebhookEvent(options) {
|
|
10304
|
+
verifyWebhookRequest(options);
|
|
10305
|
+
return parseWebhookEvent(parseJsonBody(options.body), getEventHeader(options.headers));
|
|
10306
|
+
}
|
|
10307
|
+
function handleWebhook(options) {
|
|
10308
|
+
verifyWebhookRequest(options);
|
|
10309
|
+
return validateEmailReceivedEvent(parseJsonBody(options.body));
|
|
10181
10310
|
}
|
|
10182
10311
|
function receive(input, options) {
|
|
10183
10312
|
if (input instanceof Request) return receiveFromRequest(input, options);
|
|
@@ -10364,4 +10493,4 @@ function verifyRawEmailDownload(downloaded, event) {
|
|
|
10364
10493
|
return buffer;
|
|
10365
10494
|
}
|
|
10366
10495
|
//#endregion
|
|
10367
|
-
export {
|
|
10496
|
+
export { LEGACY_CONFIRMED_HEADER as A, isEmailReceivedEvent as B, SpfResult as C, STANDARD_WEBHOOK_TIMESTAMP_HEADER as D, STANDARD_WEBHOOK_SIGNATURE_HEADER as E, verifyWebhookSignature as F, isPaymentSettledEvent as G, isKnownWebhookEventType as H, EMAIL_EVENT_TYPES as I, safeValidateEmailReceivedEvent as J, generateDownloadToken as K, INTERACTION_EVENT_TYPES as L, PRIMITIVE_CONFIRMED_HEADER as M, PRIMITIVE_SIGNATURE_HEADER as N, signStandardWebhooksPayload as O, signWebhookPayload as P, PAYMENT_EVENT_TYPES as R, ParsedStatus as S, STANDARD_WEBHOOK_ID_HEADER as T, isPaymentEvent as U, isInteractionX402Event as V, isPaymentFailedEvent as W, validateEmailReceivedEvent as Y, DkimResult as _, getEventHeader as a, EventType as b, isDownloadExpired as c, receive as d, verifyRawEmailDownload as f, AuthVerdict as g, AuthConfidence as h, getDownloadTimeRemaining as i, LEGACY_SIGNATURE_HEADER as j, verifyStandardWebhooksSignature as k, isRawIncluded as l, validateEmailAuth as m, confirmedHeaders as n, handleWebhook as o, WEBHOOK_VERSION as p, verifyDownloadToken as q, decodeRawEmail as r, handleWebhookEvent as s, WEBHOOK_EVENT_HEADER as t, parseWebhookEvent as u, DmarcPolicy as v, emailReceivedEventJsonSchema as w, ForwardVerdict as x, DmarcResult as y, WEBHOOK_EVENT_TYPES as z };
|
package/dist/x402/index.d.ts
CHANGED
|
@@ -130,8 +130,123 @@ interface X402PaymentPayload {
|
|
|
130
130
|
};
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* The protocol the email-native payment interaction runs (`x402.payment/1`).
|
|
135
|
+
* The payer's reply carries the `payment` step of this protocol.
|
|
136
|
+
*/
|
|
137
|
+
declare const X402_INTERACTION_PROTOCOL = "x402.payment";
|
|
138
|
+
declare const X402_INTERACTION_PROTOCOL_VERSION = 1;
|
|
139
|
+
/**
|
|
140
|
+
* The interaction.json envelope for one step of an email-carried interaction.
|
|
141
|
+
* The payer's `payment` step is sent as an `interaction.json` MIME attachment
|
|
142
|
+
* in the reply; the platform parses this envelope, validates the step against
|
|
143
|
+
* the `x402.payment` protocol, and re-verifies the embedded payment.
|
|
144
|
+
*/
|
|
145
|
+
interface InteractionEnvelope<P = unknown> {
|
|
146
|
+
interaction_version: 1;
|
|
147
|
+
/** The thread id (`uuid@domain`) the step belongs to. */
|
|
148
|
+
interaction_id: string;
|
|
149
|
+
protocol: string;
|
|
150
|
+
protocol_version: number;
|
|
151
|
+
/** The protocol step name (e.g. `"payment"`). */
|
|
152
|
+
step: string;
|
|
153
|
+
/** This step's id (a fresh UUID). */
|
|
154
|
+
step_id: string;
|
|
155
|
+
/** The id of the step this one answers (the challenge step), or null. */
|
|
156
|
+
prev_step_id: string | null;
|
|
157
|
+
expires_at: string | null;
|
|
158
|
+
payload: P;
|
|
159
|
+
}
|
|
160
|
+
/** The `payload` of an `x402.payment` `payment` step: the signed x402 payload. */
|
|
161
|
+
interface X402PaymentStepPayload {
|
|
162
|
+
payment: X402PaymentPayload;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* A built, signed payment-step envelope plus its canonical JSON bytes. The
|
|
166
|
+
* caller attaches `json` as the `interaction.json` part of the reply email; the
|
|
167
|
+
* platform reads `envelope` back from those exact bytes.
|
|
168
|
+
*/
|
|
169
|
+
interface BuiltPaymentStep {
|
|
170
|
+
envelope: InteractionEnvelope<X402PaymentStepPayload>;
|
|
171
|
+
/** The canonical interaction.json body (what to attach to the reply). */
|
|
172
|
+
json: string;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build the section-2.3 interaction.json envelope for a `payment` step. Pure: no
|
|
176
|
+
* I/O. `payment` is the signed exact-EVM payload (from
|
|
177
|
+
* `buildExactEvmPaymentPayload`); `prevStepId` is the challenge step id this
|
|
178
|
+
* payment answers, and `stepId` is a fresh UUID for the payment step. Returns
|
|
179
|
+
* the envelope and its canonical JSON, so the bytes the platform reads back are
|
|
180
|
+
* exactly the ones produced here.
|
|
181
|
+
*/
|
|
182
|
+
declare function buildPaymentStepEnvelope(params: {
|
|
183
|
+
/** The thread id (`uuid@domain`). */interactionId: string; /** A fresh UUID identifying this payment step. */
|
|
184
|
+
stepId: string; /** The challenge step id this payment answers. */
|
|
185
|
+
prevStepId: string;
|
|
186
|
+
payment: X402PaymentPayload; /** Optional ISO-8601 step expiry. */
|
|
187
|
+
expiresAt?: string | null;
|
|
188
|
+
}): BuiltPaymentStep;
|
|
133
189
|
/** Assemble the wire payload from a signed authorization. */
|
|
134
190
|
declare function toPaymentPayload(network: string, auth: TransferAuthorization, signature: Hex): X402PaymentPayload;
|
|
191
|
+
/**
|
|
192
|
+
* Absolute ceiling on the total signed window (validBefore - validAfter). A
|
|
193
|
+
* signed EIP-3009 authorization stays settleable on-chain until validBefore
|
|
194
|
+
* regardless of the interaction state, so an unbounded window is a standing
|
|
195
|
+
* "funds committed" risk. The real window is minutes; this 24h cap is the hard
|
|
196
|
+
* safety ceiling, enforced so a caller-supplied window cannot bypass it.
|
|
197
|
+
*/
|
|
198
|
+
declare const DEFAULT_MAX_WINDOW_SEC: number;
|
|
199
|
+
/**
|
|
200
|
+
* Compute the EIP-3009 validity window for a payment. `validBefore` is the
|
|
201
|
+
* value that governs on-chain validity, so it MUST cover the challenge's
|
|
202
|
+
* `expires_at` plus a settlement margin; `validAfter` is set generously in the
|
|
203
|
+
* past for clock skew. The total window is hard-capped at `maxWindowSec` so
|
|
204
|
+
* neither a far-future `challengeExpiresAtSec` nor a widened margin can produce
|
|
205
|
+
* a window the platform verifier would later reject.
|
|
206
|
+
*/
|
|
207
|
+
declare function computePaymentValidityWindow(params: {
|
|
208
|
+
/** The challenge's expires_at, unix seconds. */challengeExpiresAtSec: number; /** Current time, unix seconds. */
|
|
209
|
+
nowSec: number; /** Headroom past expiry for verify+settle to complete. Default 5 min. */
|
|
210
|
+
settlementMarginSec?: number; /** How far in the past to set validAfter for clock skew. Default 5 min. */
|
|
211
|
+
clockSkewSec?: number; /** Hard ceiling on validBefore - validAfter. Default 24h. */
|
|
212
|
+
maxWindowSec?: number;
|
|
213
|
+
}): {
|
|
214
|
+
validAfter: bigint;
|
|
215
|
+
validBefore: bigint;
|
|
216
|
+
};
|
|
217
|
+
/** The x402 named networks supported in v1 (testnet first). */
|
|
218
|
+
type X402Network = "base-sepolia" | "base";
|
|
219
|
+
/**
|
|
220
|
+
* The interaction-aware signer: derive the bound nonce, assemble the
|
|
221
|
+
* authorization, and sign it. This is the one piece a stock x402 signer cannot
|
|
222
|
+
* do (it generates the nonce internally with no injection point), so the payer
|
|
223
|
+
* side needs this Primitive-provided helper. The key never leaves the caller.
|
|
224
|
+
*/
|
|
225
|
+
declare function signInteractionPayment(params: {
|
|
226
|
+
/** Sign EIP-712 typed data with the caller's own key. */sign: (typedData: TransferWithAuthorizationTypedData) => Promise<Hex>; /** Payer (from) address. */
|
|
227
|
+
payer: Address;
|
|
228
|
+
domain: TokenDomain; /** Recipient (the challenger's payTo). */
|
|
229
|
+
payTo: Address; /** Amount in token base units. */
|
|
230
|
+
amount: bigint; /** Inputs that derive the interaction-bound EIP-3009 nonce. */
|
|
231
|
+
nonceBinding: NonceBinding;
|
|
232
|
+
validAfter: bigint;
|
|
233
|
+
validBefore: bigint;
|
|
234
|
+
}): Promise<{
|
|
235
|
+
authorization: TransferAuthorization;
|
|
236
|
+
signature: Hex;
|
|
237
|
+
}>;
|
|
238
|
+
/**
|
|
239
|
+
* Assemble (and validate) the exact-EVM x402 wire payload from an
|
|
240
|
+
* interaction-bound, locally-signed authorization. The numeric authorization
|
|
241
|
+
* fields are decimal strings in the wire schema, so the bigints are stringified
|
|
242
|
+
* here; the nonce passes through as hex. Validation rejects a malformed nonce or
|
|
243
|
+
* signature loudly rather than emitting a payload the platform will reject.
|
|
244
|
+
*/
|
|
245
|
+
declare function buildExactEvmPaymentPayload(params: {
|
|
246
|
+
network: X402Network;
|
|
247
|
+
authorization: TransferAuthorization;
|
|
248
|
+
signature: Hex;
|
|
249
|
+
}): X402PaymentPayload;
|
|
135
250
|
//#endregion
|
|
136
251
|
//#region src/x402/client.d.ts
|
|
137
252
|
interface X402PaymentRequirements {
|
|
@@ -159,6 +274,33 @@ interface X402Challenge {
|
|
|
159
274
|
payment_requirements: X402PaymentRequirements;
|
|
160
275
|
expires_at: string;
|
|
161
276
|
}
|
|
277
|
+
/** The nonce binding the payer hashes into the EIP-3009 nonce. */
|
|
278
|
+
interface X402NonceBinding {
|
|
279
|
+
interaction_id: string;
|
|
280
|
+
challenge_step_id: string;
|
|
281
|
+
challenge_nonce: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The challenge details carried inside an email-native challenge: what the
|
|
285
|
+
* payer needs to sign and pay. Distinct from the synthetic `X402Challenge` in
|
|
286
|
+
* that it has no top-level `id`/`amount`; everything is in the nested objects.
|
|
287
|
+
*/
|
|
288
|
+
interface X402EmailChallengeDetails {
|
|
289
|
+
payment_requirements: X402PaymentRequirements;
|
|
290
|
+
nonce_binding: X402NonceBinding;
|
|
291
|
+
expires_at: string;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* The result of issuing an email-native challenge (`createEmailChallenge`).
|
|
295
|
+
* `interaction_id` is the real email thread id (`uuid@domain`) the payment is
|
|
296
|
+
* bound to. Hand the whole object to the payer; the payer calls
|
|
297
|
+
* `payEmailChallenge` with it to build the signed payment step.
|
|
298
|
+
*/
|
|
299
|
+
interface X402EmailChallenge {
|
|
300
|
+
interaction_id: string;
|
|
301
|
+
challenge_id: string;
|
|
302
|
+
challenge: X402EmailChallengeDetails;
|
|
303
|
+
}
|
|
162
304
|
interface X402Receipt {
|
|
163
305
|
id: string;
|
|
164
306
|
status: string;
|
|
@@ -220,6 +362,34 @@ interface X402ChargeInput {
|
|
|
220
362
|
*/
|
|
221
363
|
idempotencyKey?: string;
|
|
222
364
|
}
|
|
365
|
+
interface X402EmailChargeInput {
|
|
366
|
+
/** Your sending address (the payee / funds receiver). */
|
|
367
|
+
from: string;
|
|
368
|
+
/** The payer's email address the challenge is sent to. */
|
|
369
|
+
to: string;
|
|
370
|
+
/**
|
|
371
|
+
* Amount in token base units (USDC has 6 decimals, so "10000" = 0.01).
|
|
372
|
+
* Provide exactly one of `amount` or `amountUsdc`.
|
|
373
|
+
*/
|
|
374
|
+
amount?: string;
|
|
375
|
+
/**
|
|
376
|
+
* Amount as human USDC (e.g. "0.01"), converted to base units for you.
|
|
377
|
+
* Provide exactly one of `amount` or `amountUsdc`.
|
|
378
|
+
*/
|
|
379
|
+
amountUsdc?: string;
|
|
380
|
+
/** Defaults to "base-sepolia". */
|
|
381
|
+
network?: string;
|
|
382
|
+
description?: string;
|
|
383
|
+
/** A URL identifying the thing being paid for. */
|
|
384
|
+
resource?: string;
|
|
385
|
+
/** Seconds until the challenge expires (default 1h). */
|
|
386
|
+
expiresIn?: number;
|
|
387
|
+
/**
|
|
388
|
+
* Optional idempotency key. Retrying `createEmailChallenge()` with the same
|
|
389
|
+
* key returns the original challenge without sending a second email.
|
|
390
|
+
*/
|
|
391
|
+
idempotencyKey?: string;
|
|
392
|
+
}
|
|
223
393
|
declare class X402Error extends Error {
|
|
224
394
|
/** HTTP status, or 0 for a client-side / transport error that never reached the server. */
|
|
225
395
|
readonly status: number;
|
|
@@ -246,6 +416,30 @@ declare class X402Client {
|
|
|
246
416
|
constructor(options?: X402ClientOptions);
|
|
247
417
|
/** Request a payment (payee side). Returns the challenge to hand to the payer. */
|
|
248
418
|
charge(input: X402ChargeInput): Promise<X402Challenge>;
|
|
419
|
+
/**
|
|
420
|
+
* Issue a payment challenge over an email thread (payee side). Sends the
|
|
421
|
+
* challenge as an email from `from` to `to` and binds the payment to that
|
|
422
|
+
* thread. Returns the challenge (including the real `interaction_id`); deliver
|
|
423
|
+
* it to the payer, who calls `payEmailChallenge` to build the signed payment.
|
|
424
|
+
*
|
|
425
|
+
* Provide exactly one of `amount` (base units) or `amountUsdc` (human USDC).
|
|
426
|
+
*/
|
|
427
|
+
createEmailChallenge(input: X402EmailChargeInput): Promise<X402EmailChallenge>;
|
|
428
|
+
/**
|
|
429
|
+
* Build the signed payment step for an email-native challenge (payer side).
|
|
430
|
+
* Given a received `X402EmailChallenge` and the caller's signer, this derives
|
|
431
|
+
* the interaction-bound authorization, signs it locally, and returns the
|
|
432
|
+
* signed `interaction.json` payment-step envelope plus its canonical JSON
|
|
433
|
+
* bytes. It does NOT send anything.
|
|
434
|
+
*
|
|
435
|
+
* The caller sends `result.json` back as an `interaction.json` attachment on a
|
|
436
|
+
* reply to the challenge email (e.g. via the SDK's `send` / `reply`); the
|
|
437
|
+
* platform reads the envelope from those exact bytes, re-derives the bound
|
|
438
|
+
* nonce, and settles.
|
|
439
|
+
*/
|
|
440
|
+
payEmailChallenge(challenge: X402EmailChallenge, options: {
|
|
441
|
+
signer: X402Signer;
|
|
442
|
+
}): Promise<BuiltPaymentStep>;
|
|
249
443
|
/**
|
|
250
444
|
* Pay a challenge (payer side). Derives the interaction-bound authorization,
|
|
251
445
|
* signs it locally with the caller's key, and submits it for settlement.
|
|
@@ -292,4 +486,4 @@ declare class X402Client {
|
|
|
292
486
|
}
|
|
293
487
|
declare function createX402Client(options?: X402ClientOptions): X402Client;
|
|
294
488
|
//#endregion
|
|
295
|
-
export { NonceBinding, PayoutRegistrationMessageInput, TRANSFER_WITH_AUTHORIZATION_TYPES, TokenDomain, TransferAuthorization, TransferWithAuthorizationTypedData, X402Challenge, X402ChargeInput, X402Client, X402ClientOptions, X402DeclinedPayment, X402Error, X402PaymentPayload, X402PaymentRequirements, X402PayoutAddress, X402Receipt, X402Signer, X402SpendPolicy, buildPayoutRegistrationMessage, createX402Client, deriveEip3009Nonce, toPaymentPayload, transferWithAuthorizationTypedData };
|
|
489
|
+
export { BuiltPaymentStep, DEFAULT_MAX_WINDOW_SEC, InteractionEnvelope, NonceBinding, PayoutRegistrationMessageInput, TRANSFER_WITH_AUTHORIZATION_TYPES, TokenDomain, TransferAuthorization, TransferWithAuthorizationTypedData, X402Challenge, X402ChargeInput, X402Client, X402ClientOptions, X402DeclinedPayment, X402EmailChallenge, X402EmailChallengeDetails, X402EmailChargeInput, X402Error, X402Network, X402NonceBinding, X402PaymentPayload, X402PaymentRequirements, X402PaymentStepPayload, X402PayoutAddress, X402Receipt, X402Signer, X402SpendPolicy, X402_INTERACTION_PROTOCOL, X402_INTERACTION_PROTOCOL_VERSION, buildExactEvmPaymentPayload, buildPaymentStepEnvelope, buildPayoutRegistrationMessage, computePaymentValidityWindow, createX402Client, deriveEip3009Nonce, signInteractionPayment, toPaymentPayload, transferWithAuthorizationTypedData };
|