@primitivedotdev/sdk 1.2.1 → 1.3.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/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +3 -3
- package/dist/{api-JvyzQsXn.js → api-DacG4JSU.js} +191 -1
- package/dist/{index-DdSffRr0.d.ts → index-X7RsDaVi.d.ts} +311 -2
- package/dist/index.d.ts +183 -3
- package/dist/index.js +196 -3
- package/dist/openapi/index.js +1 -1
- package/dist/{operations.generated-CvXrZUzc.js → operations.generated-DSMTMcWh.js} +549 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,10 +1,203 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as createPrimitiveClient, l as PrimitiveApiError, n as PrimitiveClient, r as client } from "./api-DacG4JSU.js";
|
|
2
2
|
import { a as VERIFICATION_ERRORS, c as WebhookVerificationError, d as formatAddress, f as normalizeReceivedEmail, i as RawEmailDecodeError, l as buildForwardSubject, n as PrimitiveWebhookError, o as WebhookPayloadError, p as parseHeaderAddress, r as RAW_EMAIL_ERRORS, s as WebhookValidationError, t as PAYLOAD_ERRORS, u as buildReplySubject } from "./errors-BPJGp9I6.js";
|
|
3
3
|
import { A as PRIMITIVE_CONFIRMED_HEADER, C as STANDARD_WEBHOOK_ID_HEADER, D as verifyStandardWebhooksSignature, E as signStandardWebhooksPayload, F as verifyDownloadToken, I as safeValidateEmailReceivedEvent, L as validateEmailReceivedEvent, M as signWebhookPayload, N as verifyWebhookSignature, O as LEGACY_CONFIRMED_HEADER, P as generateDownloadToken, S as emailReceivedEventJsonSchema, T as STANDARD_WEBHOOK_TIMESTAMP_HEADER, _ as DmarcResult, a as isDownloadExpired, b as ParsedStatus, c as parseWebhookEvent, d as WEBHOOK_VERSION, f as validateEmailAuth, g as DmarcPolicy, h as DkimResult, i as handleWebhook, j as PRIMITIVE_SIGNATURE_HEADER, k as LEGACY_SIGNATURE_HEADER, l as receive, m as AuthVerdict, n as decodeRawEmail, o as isEmailReceivedEvent, p as AuthConfidence, r as getDownloadTimeRemaining, s as isRawIncluded, t as confirmedHeaders, u as verifyRawEmailDownload, v as EventType, w as STANDARD_WEBHOOK_SIGNATURE_HEADER, x as SpfResult, y as ForwardVerdict } from "./webhook-BAwK8EOG.js";
|
|
4
|
+
import { concat, hexToBytes, keccak256, stringToBytes } from "viem";
|
|
5
|
+
//#region src/x402/sign.ts
|
|
6
|
+
/**
|
|
7
|
+
* x402 client-side signing.
|
|
8
|
+
*
|
|
9
|
+
* The payer signs an EIP-3009 `transferWithAuthorization` over the customer's
|
|
10
|
+
* own key; the key never leaves them. This module derives the interaction-bound
|
|
11
|
+
* nonce and assembles the EIP-712 typed data and the wire payload. The byte
|
|
12
|
+
* layout here MUST match the platform verifier exactly; a normative test vector
|
|
13
|
+
* (see sign.test.ts) locks the nonce derivation to the same value the server
|
|
14
|
+
* recomputes.
|
|
15
|
+
*/
|
|
16
|
+
/** A challenge nonce is 32 bytes rendered as 64 lowercase hex chars, no 0x. */
|
|
17
|
+
const CHALLENGE_NONCE_RE = /^[0-9a-f]{64}$/;
|
|
18
|
+
/** Single-byte domain separator between the variable-length string fields. */
|
|
19
|
+
const FIELD_SEPARATOR = new Uint8Array([0]);
|
|
20
|
+
/**
|
|
21
|
+
* Derive the EIP-3009 nonce bound to a specific interaction step:
|
|
22
|
+
*
|
|
23
|
+
* keccak256( utf8(lower(interaction_id)) || 0x00
|
|
24
|
+
* || utf8(lower(challenge_step_id)) || 0x00
|
|
25
|
+
* || hexdecode(challenge_nonce) )
|
|
26
|
+
*
|
|
27
|
+
* The `0x00` separators pin the field boundaries (undelimited concatenation of
|
|
28
|
+
* variable-length strings is collision-ambiguous), and the challenge nonce is
|
|
29
|
+
* decoded to its 32 raw bytes before hashing. The platform recomputes this and
|
|
30
|
+
* rejects a mismatch.
|
|
31
|
+
*/
|
|
32
|
+
function deriveEip3009Nonce(input) {
|
|
33
|
+
if (!CHALLENGE_NONCE_RE.test(input.challengeNonce)) throw new Error("challengeNonce must be exactly 64 lowercase hex chars (32 bytes), no 0x prefix");
|
|
34
|
+
return keccak256(concat([
|
|
35
|
+
stringToBytes(input.interactionId.toLowerCase()),
|
|
36
|
+
FIELD_SEPARATOR,
|
|
37
|
+
stringToBytes(input.challengeStepId.toLowerCase()),
|
|
38
|
+
FIELD_SEPARATOR,
|
|
39
|
+
hexToBytes(`0x${input.challengeNonce}`)
|
|
40
|
+
]));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The EIP-3009 `TransferWithAuthorization` EIP-712 type. The field order and
|
|
44
|
+
* types are part of the on-chain contract and MUST NOT change.
|
|
45
|
+
*/
|
|
46
|
+
const TRANSFER_WITH_AUTHORIZATION_TYPES = { TransferWithAuthorization: [
|
|
47
|
+
{
|
|
48
|
+
name: "from",
|
|
49
|
+
type: "address"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "to",
|
|
53
|
+
type: "address"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "value",
|
|
57
|
+
type: "uint256"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "validAfter",
|
|
61
|
+
type: "uint256"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "validBefore",
|
|
65
|
+
type: "uint256"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "nonce",
|
|
69
|
+
type: "bytes32"
|
|
70
|
+
}
|
|
71
|
+
] };
|
|
72
|
+
function transferWithAuthorizationTypedData(domain, auth) {
|
|
73
|
+
return {
|
|
74
|
+
domain: {
|
|
75
|
+
name: domain.name,
|
|
76
|
+
version: domain.version,
|
|
77
|
+
chainId: domain.chainId,
|
|
78
|
+
verifyingContract: domain.verifyingContract
|
|
79
|
+
},
|
|
80
|
+
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
81
|
+
primaryType: "TransferWithAuthorization",
|
|
82
|
+
message: auth
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Assemble the wire payload from a signed authorization. */
|
|
86
|
+
function toPaymentPayload(network, auth, signature) {
|
|
87
|
+
return {
|
|
88
|
+
x402Version: 1,
|
|
89
|
+
scheme: "exact",
|
|
90
|
+
network,
|
|
91
|
+
payload: {
|
|
92
|
+
signature,
|
|
93
|
+
authorization: {
|
|
94
|
+
from: auth.from,
|
|
95
|
+
to: auth.to,
|
|
96
|
+
value: auth.value.toString(),
|
|
97
|
+
validAfter: auth.validAfter.toString(),
|
|
98
|
+
validBefore: auth.validBefore.toString(),
|
|
99
|
+
nonce: auth.nonce
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/x402/client.ts
|
|
106
|
+
const CHAIN_IDS = {
|
|
107
|
+
"base-sepolia": 84532,
|
|
108
|
+
base: 8453
|
|
109
|
+
};
|
|
110
|
+
const CLOCK_SKEW_SEC = 300;
|
|
111
|
+
const SETTLEMENT_MARGIN_SEC = 300;
|
|
112
|
+
const DEFAULT_BASE_URL = "https://api.primitive.dev";
|
|
113
|
+
var X402Error = class extends Error {
|
|
114
|
+
status;
|
|
115
|
+
body;
|
|
116
|
+
constructor(message, status, body) {
|
|
117
|
+
super(message);
|
|
118
|
+
this.name = "X402Error";
|
|
119
|
+
this.status = status;
|
|
120
|
+
this.body = body;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var X402Client = class {
|
|
124
|
+
#apiKey;
|
|
125
|
+
#baseUrl;
|
|
126
|
+
#fetch;
|
|
127
|
+
constructor(options = {}) {
|
|
128
|
+
this.#apiKey = options.apiKey ?? process.env.PRIMITIVE_API_KEY ?? "";
|
|
129
|
+
this.#baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
130
|
+
this.#fetch = options.fetch ?? fetch;
|
|
131
|
+
}
|
|
132
|
+
async #request(method, path, body) {
|
|
133
|
+
const res = await this.#fetch(`${this.#baseUrl}${path}`, {
|
|
134
|
+
method,
|
|
135
|
+
headers: {
|
|
136
|
+
authorization: `Bearer ${this.#apiKey}`,
|
|
137
|
+
"content-type": "application/json"
|
|
138
|
+
},
|
|
139
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
140
|
+
});
|
|
141
|
+
const json = await res.json().catch(() => ({}));
|
|
142
|
+
if (!res.ok || json.success === false) throw new X402Error(json.error?.message ?? `request failed with ${res.status}`, res.status, json);
|
|
143
|
+
return json.data ?? json;
|
|
144
|
+
}
|
|
145
|
+
/** Request a payment (payee side). Returns the challenge to hand to the payer. */
|
|
146
|
+
charge(input) {
|
|
147
|
+
const body = {
|
|
148
|
+
amount: input.amount,
|
|
149
|
+
network: input.network ?? "base-sepolia"
|
|
150
|
+
};
|
|
151
|
+
if (input.payerOrg) body.payer_org = input.payerOrg;
|
|
152
|
+
if (input.description) body.description = input.description;
|
|
153
|
+
if (input.resource) body.resource = input.resource;
|
|
154
|
+
if (input.expiresIn !== void 0) body.expires_in = input.expiresIn;
|
|
155
|
+
return this.#request("POST", "/v1/x402/challenges", body);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Pay a challenge (payer side). Derives the interaction-bound authorization,
|
|
159
|
+
* signs it locally with the caller's key, and submits it for settlement.
|
|
160
|
+
*/
|
|
161
|
+
async pay(challenge, options) {
|
|
162
|
+
const chainId = CHAIN_IDS[challenge.network];
|
|
163
|
+
if (chainId === void 0) throw new X402Error(`unsupported network: ${challenge.network}`, 0);
|
|
164
|
+
const pr = challenge.payment_requirements;
|
|
165
|
+
const nonce = deriveEip3009Nonce({
|
|
166
|
+
interactionId: challenge.nonce_binding.interaction_id,
|
|
167
|
+
challengeStepId: challenge.nonce_binding.challenge_step_id,
|
|
168
|
+
challengeNonce: challenge.nonce_binding.challenge_nonce
|
|
169
|
+
});
|
|
170
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
171
|
+
const expiresAtMs = Date.parse(challenge.expires_at);
|
|
172
|
+
if (Number.isNaN(expiresAtMs)) throw new X402Error(`challenge has an invalid expires_at: ${challenge.expires_at}`, 0);
|
|
173
|
+
const expiresAtSec = Math.floor(expiresAtMs / 1e3);
|
|
174
|
+
const auth = {
|
|
175
|
+
from: options.signer.address,
|
|
176
|
+
to: pr.payTo,
|
|
177
|
+
value: BigInt(pr.maxAmountRequired),
|
|
178
|
+
validAfter: BigInt(nowSec - CLOCK_SKEW_SEC),
|
|
179
|
+
validBefore: BigInt(expiresAtSec + SETTLEMENT_MARGIN_SEC),
|
|
180
|
+
nonce
|
|
181
|
+
};
|
|
182
|
+
const signature = await options.signer.signTypedData(transferWithAuthorizationTypedData({
|
|
183
|
+
name: pr.extra.name,
|
|
184
|
+
version: pr.extra.version,
|
|
185
|
+
chainId,
|
|
186
|
+
verifyingContract: pr.asset
|
|
187
|
+
}, auth));
|
|
188
|
+
return this.#request("POST", `/v1/x402/challenges/${challenge.id}/pay`, { payment: toPaymentPayload(challenge.network, auth, signature) });
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
function createX402Client(options = {}) {
|
|
192
|
+
return new X402Client(options);
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
4
195
|
//#region src/index.ts
|
|
5
196
|
const primitive = {
|
|
6
197
|
client,
|
|
7
|
-
receive
|
|
198
|
+
receive,
|
|
199
|
+
/** Construct an x402 payments client. See `X402Client`. */
|
|
200
|
+
x402: createX402Client
|
|
8
201
|
};
|
|
9
202
|
//#endregion
|
|
10
|
-
export { AuthConfidence, AuthVerdict, DkimResult, DmarcPolicy, DmarcResult, EventType, ForwardVerdict, LEGACY_CONFIRMED_HEADER, LEGACY_SIGNATURE_HEADER, PAYLOAD_ERRORS, PRIMITIVE_CONFIRMED_HEADER, PRIMITIVE_SIGNATURE_HEADER, ParsedStatus, PrimitiveApiError, PrimitiveClient, PrimitiveWebhookError, RAW_EMAIL_ERRORS, RawEmailDecodeError, STANDARD_WEBHOOK_ID_HEADER, STANDARD_WEBHOOK_SIGNATURE_HEADER, STANDARD_WEBHOOK_TIMESTAMP_HEADER, SpfResult, VERIFICATION_ERRORS, WEBHOOK_VERSION, WebhookPayloadError, WebhookValidationError, WebhookVerificationError, buildForwardSubject, buildReplySubject, client, confirmedHeaders, createPrimitiveClient, decodeRawEmail, primitive as default, emailReceivedEventJsonSchema, formatAddress, generateDownloadToken, getDownloadTimeRemaining, handleWebhook, isDownloadExpired, isEmailReceivedEvent, isRawIncluded, normalizeReceivedEmail, parseHeaderAddress, parseWebhookEvent, receive, safeValidateEmailReceivedEvent, signStandardWebhooksPayload, signWebhookPayload, validateEmailAuth, validateEmailReceivedEvent, verifyDownloadToken, verifyRawEmailDownload, verifyStandardWebhooksSignature, verifyWebhookSignature };
|
|
203
|
+
export { AuthConfidence, AuthVerdict, DkimResult, DmarcPolicy, DmarcResult, EventType, ForwardVerdict, LEGACY_CONFIRMED_HEADER, LEGACY_SIGNATURE_HEADER, PAYLOAD_ERRORS, PRIMITIVE_CONFIRMED_HEADER, PRIMITIVE_SIGNATURE_HEADER, ParsedStatus, PrimitiveApiError, PrimitiveClient, PrimitiveWebhookError, RAW_EMAIL_ERRORS, RawEmailDecodeError, STANDARD_WEBHOOK_ID_HEADER, STANDARD_WEBHOOK_SIGNATURE_HEADER, STANDARD_WEBHOOK_TIMESTAMP_HEADER, SpfResult, VERIFICATION_ERRORS, WEBHOOK_VERSION, WebhookPayloadError, WebhookValidationError, WebhookVerificationError, X402Client, X402Error, buildForwardSubject, buildReplySubject, client, confirmedHeaders, createPrimitiveClient, createX402Client, decodeRawEmail, primitive as default, deriveEip3009Nonce, emailReceivedEventJsonSchema, formatAddress, generateDownloadToken, getDownloadTimeRemaining, handleWebhook, isDownloadExpired, isEmailReceivedEvent, isRawIncluded, normalizeReceivedEmail, parseHeaderAddress, parseWebhookEvent, receive, safeValidateEmailReceivedEvent, signStandardWebhooksPayload, signWebhookPayload, validateEmailAuth, validateEmailReceivedEvent, verifyDownloadToken, verifyRawEmailDownload, verifyStandardWebhooksSignature, verifyWebhookSignature };
|
package/dist/openapi/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as openapiDocument, t as operationManifest } from "../operations.generated-
|
|
1
|
+
import { n as openapiDocument, t as operationManifest } from "../operations.generated-DSMTMcWh.js";
|
|
2
2
|
export { openapiDocument, operationManifest };
|