@siglume/direct-request-payment 0.1.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/index.cjs ADDED
@@ -0,0 +1,555 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ DEFAULT_SIGLUME_API_BASE: () => DEFAULT_SIGLUME_API_BASE,
34
+ DEFAULT_WEBHOOK_TOLERANCE_SECONDS: () => DEFAULT_WEBHOOK_TOLERANCE_SECONDS,
35
+ DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND: () => DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND,
36
+ DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME: () => DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME,
37
+ DIRECT_REQUEST_PAYMENT_MODE: () => DIRECT_REQUEST_PAYMENT_MODE,
38
+ DIRECT_REQUEST_PAYMENT_RECEIPT_KIND: () => DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,
39
+ DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE: () => DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE,
40
+ DirectRequestPaymentClient: () => DirectRequestPaymentClient,
41
+ SiglumeApiError: () => SiglumeApiError,
42
+ SiglumeDirectRequestPaymentError: () => SiglumeDirectRequestPaymentError,
43
+ SiglumeWebhookPayloadError: () => SiglumeWebhookPayloadError,
44
+ SiglumeWebhookSignatureError: () => SiglumeWebhookSignatureError,
45
+ buildAllowanceExecutionPayload: () => buildAllowanceExecutionPayload,
46
+ buildPaymentExecutionPayload: () => buildPaymentExecutionPayload,
47
+ buildPreparedTransactionExecutionPayload: () => buildPreparedTransactionExecutionPayload,
48
+ buildWebhookSignatureHeader: () => buildWebhookSignatureHeader,
49
+ computeWebhookSignature: () => computeWebhookSignature,
50
+ createDirectRequestPaymentChallenge: () => createDirectRequestPaymentChallenge,
51
+ createDirectRequestPaymentChallengeSignature: () => createDirectRequestPaymentChallengeSignature,
52
+ createExternal402Challenge: () => createExternal402Challenge,
53
+ directRequestPaymentChallengeHash: () => directRequestPaymentChallengeHash,
54
+ directRequestPaymentRequestHash: () => directRequestPaymentRequestHash,
55
+ parseDirectRequestPaymentChallenge: () => parseDirectRequestPaymentChallenge,
56
+ parseDirectRequestPaymentWebhookEvent: () => parseDirectRequestPaymentWebhookEvent,
57
+ verifyDirectRequestPaymentChallenge: () => verifyDirectRequestPaymentChallenge,
58
+ verifyDirectRequestPaymentWebhook: () => verifyDirectRequestPaymentWebhook,
59
+ verifyExternal402Challenge: () => verifyExternal402Challenge,
60
+ verifyWebhookSignature: () => verifyWebhookSignature
61
+ });
62
+ module.exports = __toCommonJS(src_exports);
63
+ var DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
64
+ var DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME = "siglume-external-402-v1";
65
+ var DIRECT_REQUEST_PAYMENT_MODE = "external_402";
66
+ var DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = "api_store_direct_payment";
67
+ var DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = "api_store_direct_payment_allowance";
68
+ var DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = "api_store_direct_payment_requirement";
69
+ var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
70
+ var SiglumeDirectRequestPaymentError = class extends Error {
71
+ constructor(message) {
72
+ super(message);
73
+ this.name = "SiglumeDirectRequestPaymentError";
74
+ }
75
+ };
76
+ var SiglumeApiError = class extends SiglumeDirectRequestPaymentError {
77
+ status;
78
+ code;
79
+ data;
80
+ constructor(message, options) {
81
+ super(message);
82
+ this.name = "SiglumeApiError";
83
+ this.status = options.status;
84
+ this.code = options.code ?? "SIGLUME_API_ERROR";
85
+ this.data = options.data;
86
+ }
87
+ };
88
+ var SiglumeWebhookSignatureError = class extends SiglumeDirectRequestPaymentError {
89
+ constructor(message) {
90
+ super(message);
91
+ this.name = "SiglumeWebhookSignatureError";
92
+ }
93
+ };
94
+ var SiglumeWebhookPayloadError = class extends SiglumeDirectRequestPaymentError {
95
+ constructor(message) {
96
+ super(message);
97
+ this.name = "SiglumeWebhookPayloadError";
98
+ }
99
+ };
100
+ var DirectRequestPaymentClient = class {
101
+ auth_token;
102
+ base_url;
103
+ timeout_ms;
104
+ user_agent;
105
+ fetch_impl;
106
+ constructor(options = {}) {
107
+ const authToken = options.auth_token ?? envValue("SIGLUME_AUTH_TOKEN");
108
+ if (!authToken) {
109
+ throw new SiglumeDirectRequestPaymentError(
110
+ "A buyer Siglume bearer token is required for Direct Request Payment API calls. Developer Portal API keys are not accepted."
111
+ );
112
+ }
113
+ const fetchImpl = options.fetch ?? globalThis.fetch;
114
+ if (!fetchImpl) {
115
+ throw new SiglumeDirectRequestPaymentError("A fetch implementation is required in this runtime.");
116
+ }
117
+ this.auth_token = authToken;
118
+ this.base_url = (options.base_url ?? envValue("SIGLUME_API_BASE") ?? DEFAULT_SIGLUME_API_BASE).replace(/\/+$/, "");
119
+ this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15e3));
120
+ this.user_agent = options.user_agent ?? "@siglume/direct-request-payment/0.1.0";
121
+ this.fetch_impl = fetchImpl;
122
+ }
123
+ async createPaymentRequirement(input) {
124
+ const payload = {
125
+ mode: DIRECT_REQUEST_PAYMENT_MODE,
126
+ merchant: normalizeMerchant(input.merchant),
127
+ amount_minor: positiveInteger(input.amount_minor, "amount_minor"),
128
+ currency: normalizeCurrency(input.currency),
129
+ challenge: requireNonEmpty(input.challenge, "challenge")
130
+ };
131
+ if (input.token_symbol !== void 0) {
132
+ payload.token_symbol = normalizeToken(input.token_symbol);
133
+ }
134
+ if (input.allowance_amount_minor !== void 0) {
135
+ payload.allowance_amount_minor = positiveInteger(input.allowance_amount_minor, "allowance_amount_minor");
136
+ }
137
+ if (input.metadata !== void 0) {
138
+ payload.metadata = cloneJsonObject(input.metadata, "metadata");
139
+ }
140
+ return this.request("POST", "/market/api-store/direct-payments/requirements", payload);
141
+ }
142
+ async getPaymentRequirement(requirement_id) {
143
+ return this.request(
144
+ "GET",
145
+ `/market/api-store/direct-payments/requirements/${encodeURIComponent(requireNonEmpty(requirement_id, "requirement_id"))}`
146
+ );
147
+ }
148
+ async verifyPaymentRequirement(requirement_id, input) {
149
+ return this.request(
150
+ "POST",
151
+ `/market/api-store/direct-payments/requirements/${encodeURIComponent(requireNonEmpty(requirement_id, "requirement_id"))}/verify`,
152
+ input
153
+ );
154
+ }
155
+ async executePreparedTransaction(payload) {
156
+ return this.request(
157
+ "POST",
158
+ "/market/web3/transactions/execute-prepared",
159
+ payload
160
+ );
161
+ }
162
+ async executePaymentTransaction(requirement, options = {}) {
163
+ return this.executePreparedTransaction(buildPaymentExecutionPayload(requirement, options));
164
+ }
165
+ async executeAllowanceTransaction(requirement, options = {}) {
166
+ return this.executePreparedTransaction(buildAllowanceExecutionPayload(requirement, options));
167
+ }
168
+ async request(method, path, json_body) {
169
+ const controller = new AbortController();
170
+ const timeout = setTimeout(() => controller.abort(), this.timeout_ms);
171
+ try {
172
+ const headers = {
173
+ "Accept": "application/json",
174
+ "Authorization": `Bearer ${this.auth_token}`,
175
+ "User-Agent": this.user_agent
176
+ };
177
+ let body;
178
+ if (json_body !== void 0) {
179
+ headers["Content-Type"] = "application/json";
180
+ body = JSON.stringify(json_body);
181
+ }
182
+ const response = await this.fetch_impl(`${this.base_url}${path}`, {
183
+ method,
184
+ headers,
185
+ body,
186
+ signal: controller.signal
187
+ });
188
+ const rawText = await response.text();
189
+ const parsed = rawText ? parseJson(rawText) : {};
190
+ if (!response.ok) {
191
+ const error = isRecord(parsed) && isRecord(parsed.error) ? parsed.error : {};
192
+ const code = stringOrNull(error.code) ?? stringOrNull(parsed.code) ?? `HTTP_${response.status}`;
193
+ const message = stringOrNull(error.message) ?? stringOrNull(parsed.message) ?? response.statusText;
194
+ throw new SiglumeApiError(message, { status: response.status, code, data: parsed });
195
+ }
196
+ if (isRecord(parsed) && "data" in parsed) {
197
+ return parsed.data;
198
+ }
199
+ return parsed;
200
+ } finally {
201
+ clearTimeout(timeout);
202
+ }
203
+ }
204
+ };
205
+ async function createDirectRequestPaymentChallenge(input) {
206
+ const merchant = normalizeMerchant(input.merchant);
207
+ const amount_minor = positiveInteger(input.amount_minor, "amount_minor");
208
+ const currency = normalizeCurrency(input.currency);
209
+ const nonce = input.nonce ? normalizeChallengeNonce(input.nonce) : await randomNonce();
210
+ const signature = await createDirectRequestPaymentChallengeSignature(input.secret, {
211
+ merchant,
212
+ amount_minor,
213
+ currency,
214
+ nonce
215
+ });
216
+ const challenge = `${DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME}:${nonce}:${signature}`;
217
+ return {
218
+ scheme: DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME,
219
+ merchant,
220
+ amount_minor,
221
+ currency,
222
+ nonce,
223
+ signature,
224
+ challenge,
225
+ challenge_hash: await sha256Prefixed(challenge)
226
+ };
227
+ }
228
+ async function createDirectRequestPaymentChallengeSignature(secret, input) {
229
+ const normalizedSecret = requireNonEmpty(secret, "secret");
230
+ const merchant = normalizeMerchant(input.merchant);
231
+ const amount = positiveInteger(input.amount_minor, "amount_minor");
232
+ const currency = normalizeCurrency(input.currency);
233
+ const nonce = normalizeChallengeNonce(input.nonce);
234
+ const material = `${merchant}:${amount}:${currency}:${nonce}`;
235
+ return hmacSha256Hex(normalizedSecret, new TextEncoder().encode(material));
236
+ }
237
+ function parseDirectRequestPaymentChallenge(challenge) {
238
+ const parts = requireNonEmpty(challenge, "challenge").split(":");
239
+ if (parts.length !== 3) {
240
+ throw new SiglumeDirectRequestPaymentError("Direct Request Payment challenge must be scheme:nonce:signature.");
241
+ }
242
+ const [scheme, nonce, signature] = parts;
243
+ if (!scheme || !nonce || !signature) {
244
+ throw new SiglumeDirectRequestPaymentError("Direct Request Payment challenge is incomplete.");
245
+ }
246
+ return { scheme, nonce, signature };
247
+ }
248
+ async function verifyDirectRequestPaymentChallenge(secret, input) {
249
+ const parsed = parseDirectRequestPaymentChallenge(input.challenge);
250
+ if (parsed.scheme !== DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME) {
251
+ return false;
252
+ }
253
+ const expected = await createDirectRequestPaymentChallengeSignature(secret, {
254
+ merchant: input.merchant,
255
+ amount_minor: input.amount_minor,
256
+ currency: input.currency,
257
+ nonce: parsed.nonce
258
+ });
259
+ return timingSafeEqualHex(expected, parsed.signature);
260
+ }
261
+ async function directRequestPaymentChallengeHash(challenge) {
262
+ return sha256Prefixed(requireNonEmpty(challenge, "challenge"));
263
+ }
264
+ async function directRequestPaymentRequestHash(input) {
265
+ const material = `${normalizeMerchant(input.merchant)}${positiveInteger(input.amount_minor, "amount_minor")}${normalizeCurrency(input.currency)}${requireNonEmpty(input.challenge, "challenge")}`;
266
+ return sha256Prefixed(material);
267
+ }
268
+ function buildPaymentExecutionPayload(requirement, options = {}) {
269
+ return buildPreparedTransactionExecutionPayload(requirement, requirement.transaction_request, {
270
+ receipt_kind: DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,
271
+ await_finality: options.await_finality,
272
+ metadata: options.metadata
273
+ });
274
+ }
275
+ function buildAllowanceExecutionPayload(requirement, options = {}) {
276
+ const approveRequest = requirement.approve_transaction_request;
277
+ if (!approveRequest || Object.keys(approveRequest).length === 0) {
278
+ throw new SiglumeDirectRequestPaymentError("This payment requirement does not include an allowance approval transaction.");
279
+ }
280
+ return buildPreparedTransactionExecutionPayload(requirement, approveRequest, {
281
+ receipt_kind: DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND,
282
+ await_finality: options.await_finality,
283
+ metadata: options.metadata
284
+ });
285
+ }
286
+ function buildPreparedTransactionExecutionPayload(requirement, transaction_request, options) {
287
+ const metadata = {
288
+ ...isRecord(transaction_request.metadata_jsonb) ? transaction_request.metadata_jsonb : {},
289
+ ...options.metadata ?? {}
290
+ };
291
+ return {
292
+ transaction_request,
293
+ receipt_kind: requireNonEmpty(options.receipt_kind, "receipt_kind"),
294
+ reference_type: DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE,
295
+ reference_id: requirement.requirement_id,
296
+ metadata,
297
+ await_finality: Boolean(options.await_finality)
298
+ };
299
+ }
300
+ async function computeWebhookSignature(signing_secret, body, options) {
301
+ if (!signing_secret) {
302
+ throw new SiglumeWebhookSignatureError("SIGLUME webhook signing secret is required.");
303
+ }
304
+ const timestamp = Math.trunc(options.timestamp);
305
+ const bytes = bodyBytes(body);
306
+ const prefix = new TextEncoder().encode(`${timestamp}.`);
307
+ const payload = new Uint8Array(prefix.length + bytes.length);
308
+ payload.set(prefix, 0);
309
+ payload.set(bytes, prefix.length);
310
+ return hmacSha256Hex(signing_secret, payload);
311
+ }
312
+ async function buildWebhookSignatureHeader(signing_secret, body, options = {}) {
313
+ const timestamp = Math.trunc(options.timestamp ?? Date.now() / 1e3);
314
+ const signature = await computeWebhookSignature(signing_secret, body, { timestamp });
315
+ return `t=${timestamp},v1=${signature}`;
316
+ }
317
+ async function verifyWebhookSignature(signing_secret, body, signature_header, options = {}) {
318
+ const { timestamp, signature } = parseSignatureHeader(signature_header);
319
+ const toleranceSeconds = Math.max(1, Math.trunc(options.tolerance_seconds ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS));
320
+ const nowSeconds = Math.trunc(options.now ?? Date.now() / 1e3);
321
+ if (Math.abs(nowSeconds - timestamp) > toleranceSeconds) {
322
+ throw new SiglumeWebhookSignatureError("Webhook timestamp is outside the allowed tolerance window.");
323
+ }
324
+ const expected = await computeWebhookSignature(signing_secret, body, { timestamp });
325
+ if (!await timingSafeEqualHex(expected, signature)) {
326
+ throw new SiglumeWebhookSignatureError("Webhook signature did not match.");
327
+ }
328
+ return { timestamp, signature };
329
+ }
330
+ function parseDirectRequestPaymentWebhookEvent(payload) {
331
+ const event = requireRecord(payload, "webhook event");
332
+ const data = requireRecord(event.data, "webhook event data");
333
+ const parsed = {
334
+ ...event,
335
+ id: requireNonEmpty(stringOrNull(event.id) ?? "", "webhook event id"),
336
+ type: requireNonEmpty(stringOrNull(event.type) ?? "", "webhook event type"),
337
+ api_version: requireNonEmpty(stringOrNull(event.api_version) ?? "", "webhook api_version"),
338
+ occurred_at: requireNonEmpty(stringOrNull(event.occurred_at) ?? "", "webhook occurred_at"),
339
+ data: { ...data }
340
+ };
341
+ if (parsed.type === "direct_payment.confirmed" && parsed.data.mode !== DIRECT_REQUEST_PAYMENT_MODE) {
342
+ throw new SiglumeWebhookPayloadError("direct_payment.confirmed webhook must carry data.mode='external_402'.");
343
+ }
344
+ return parsed;
345
+ }
346
+ async function verifyDirectRequestPaymentWebhook(signing_secret, body, signature_header, options = {}) {
347
+ const verification = await verifyWebhookSignature(signing_secret, body, signature_header, options);
348
+ const text = new TextDecoder().decode(bodyBytes(body));
349
+ let parsed;
350
+ try {
351
+ parsed = JSON.parse(text);
352
+ } catch (error) {
353
+ throw new SiglumeWebhookPayloadError("Webhook body must contain valid JSON.");
354
+ }
355
+ return { event: parseDirectRequestPaymentWebhookEvent(parsed), verification };
356
+ }
357
+ var createExternal402Challenge = createDirectRequestPaymentChallenge;
358
+ var verifyExternal402Challenge = verifyDirectRequestPaymentChallenge;
359
+ function normalizeMerchant(value) {
360
+ const merchant = requireNonEmpty(value, "merchant").toLowerCase();
361
+ if (!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(merchant)) {
362
+ throw new SiglumeDirectRequestPaymentError("merchant must be a lowercase key using letters, numbers, dot, underscore, or hyphen.");
363
+ }
364
+ return merchant;
365
+ }
366
+ function normalizeCurrency(value) {
367
+ const currency = requireNonEmpty(value, "currency").toUpperCase();
368
+ if (currency !== "JPY" && currency !== "USD") {
369
+ throw new SiglumeDirectRequestPaymentError("currency must be JPY or USD.");
370
+ }
371
+ return currency;
372
+ }
373
+ function normalizeToken(value) {
374
+ const token = requireNonEmpty(value, "token_symbol").toUpperCase();
375
+ if (token !== "JPYC" && token !== "USDC") {
376
+ throw new SiglumeDirectRequestPaymentError("token_symbol must be JPYC or USDC.");
377
+ }
378
+ return token;
379
+ }
380
+ function positiveInteger(value, name) {
381
+ const parsed = Number(value);
382
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
383
+ throw new SiglumeDirectRequestPaymentError(`${name} must be a positive safe integer.`);
384
+ }
385
+ return parsed;
386
+ }
387
+ function requireNonEmpty(value, name) {
388
+ const text = String(value ?? "").trim();
389
+ if (!text) {
390
+ throw new SiglumeDirectRequestPaymentError(`${name} is required.`);
391
+ }
392
+ return text;
393
+ }
394
+ function normalizeChallengeNonce(value) {
395
+ const nonce = requireNonEmpty(value, "nonce");
396
+ if (nonce.includes(":")) {
397
+ throw new SiglumeDirectRequestPaymentError("nonce must not contain ':'.");
398
+ }
399
+ return nonce;
400
+ }
401
+ function cloneJsonObject(value, name) {
402
+ try {
403
+ const cloned = JSON.parse(JSON.stringify(value));
404
+ if (!isRecord(cloned)) {
405
+ throw new Error("not an object");
406
+ }
407
+ return cloned;
408
+ } catch (error) {
409
+ throw new SiglumeDirectRequestPaymentError(`${name} must be a JSON-serializable object.`);
410
+ }
411
+ }
412
+ function parseJson(rawText) {
413
+ try {
414
+ return JSON.parse(rawText);
415
+ } catch (error) {
416
+ throw new SiglumeApiError("Siglume API returned invalid JSON.", {
417
+ status: 502,
418
+ code: "INVALID_JSON_RESPONSE",
419
+ data: rawText
420
+ });
421
+ }
422
+ }
423
+ function stringOrNull(value) {
424
+ if (typeof value !== "string") {
425
+ return null;
426
+ }
427
+ const text = value.trim();
428
+ return text ? text : null;
429
+ }
430
+ function isRecord(value) {
431
+ return typeof value === "object" && value !== null && !Array.isArray(value);
432
+ }
433
+ function requireRecord(value, name) {
434
+ if (!isRecord(value)) {
435
+ throw new SiglumeWebhookPayloadError(`${name} must be an object.`);
436
+ }
437
+ return value;
438
+ }
439
+ function envValue(name) {
440
+ if (typeof process === "undefined") {
441
+ return void 0;
442
+ }
443
+ const value = process.env[name];
444
+ return value && value.trim() ? value.trim() : void 0;
445
+ }
446
+ function bodyBytes(body) {
447
+ if (body instanceof Uint8Array) {
448
+ return body;
449
+ }
450
+ if (body instanceof ArrayBuffer) {
451
+ return new Uint8Array(body);
452
+ }
453
+ if (typeof body === "string") {
454
+ return new TextEncoder().encode(body);
455
+ }
456
+ if (isRecord(body)) {
457
+ return new TextEncoder().encode(JSON.stringify(body));
458
+ }
459
+ throw new SiglumeWebhookPayloadError("Webhook body must be raw bytes, a string, or a JSON object.");
460
+ }
461
+ function parseSignatureHeader(signatureHeader) {
462
+ let timestamp = null;
463
+ let signature = null;
464
+ for (const item of String(signatureHeader ?? "").split(",")) {
465
+ const [key, value] = item.trim().split("=", 2);
466
+ if (key === "t") {
467
+ const parsed = Number.parseInt(value ?? "", 10);
468
+ if (!Number.isFinite(parsed)) {
469
+ throw new SiglumeWebhookSignatureError("Webhook signature timestamp is invalid.");
470
+ }
471
+ timestamp = parsed;
472
+ }
473
+ if (key === "v1") {
474
+ signature = String(value ?? "").trim();
475
+ }
476
+ }
477
+ if (timestamp === null || !signature) {
478
+ throw new SiglumeWebhookSignatureError("Webhook signature header is incomplete.");
479
+ }
480
+ return { timestamp, signature };
481
+ }
482
+ async function randomNonce() {
483
+ if (globalThis.crypto?.randomUUID) {
484
+ return globalThis.crypto.randomUUID();
485
+ }
486
+ const bytes = new Uint8Array(16);
487
+ if (globalThis.crypto?.getRandomValues) {
488
+ globalThis.crypto.getRandomValues(bytes);
489
+ } else if (typeof process !== "undefined" && process.versions?.node) {
490
+ const crypto = await import("crypto");
491
+ bytes.set(crypto.randomBytes(16));
492
+ } else {
493
+ throw new SiglumeDirectRequestPaymentError("Crypto random number generation is unavailable in this runtime.");
494
+ }
495
+ return bytesToHex(bytes);
496
+ }
497
+ async function hmacSha256Hex(secret, payload) {
498
+ if (globalThis.crypto?.subtle) {
499
+ const stablePayload = new Uint8Array(payload.byteLength);
500
+ stablePayload.set(payload);
501
+ const key = await globalThis.crypto.subtle.importKey(
502
+ "raw",
503
+ new TextEncoder().encode(secret),
504
+ { name: "HMAC", hash: "SHA-256" },
505
+ false,
506
+ ["sign"]
507
+ );
508
+ const digest = await globalThis.crypto.subtle.sign("HMAC", key, stablePayload);
509
+ return bytesToHex(new Uint8Array(digest));
510
+ }
511
+ if (typeof process !== "undefined" && process.versions?.node) {
512
+ const crypto = await import("crypto");
513
+ return crypto.createHmac("sha256", secret).update(Buffer.from(payload)).digest("hex");
514
+ }
515
+ throw new SiglumeDirectRequestPaymentError("Web Crypto is required for HMAC-SHA256 in this runtime.");
516
+ }
517
+ async function sha256Prefixed(material) {
518
+ const bytes = new TextEncoder().encode(material);
519
+ if (globalThis.crypto?.subtle) {
520
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
521
+ return `sha256:${bytesToHex(new Uint8Array(digest))}`;
522
+ }
523
+ if (typeof process !== "undefined" && process.versions?.node) {
524
+ const crypto = await import("crypto");
525
+ return `sha256:${crypto.createHash("sha256").update(Buffer.from(bytes)).digest("hex")}`;
526
+ }
527
+ throw new SiglumeDirectRequestPaymentError("Web Crypto is required for SHA-256 in this runtime.");
528
+ }
529
+ function bytesToHex(bytes) {
530
+ return [...bytes].map((item) => item.toString(16).padStart(2, "0")).join("");
531
+ }
532
+ function hexToBytes(hex) {
533
+ const normalized = String(hex ?? "").trim().toLowerCase();
534
+ if (normalized.length % 2 !== 0 || !/^[0-9a-f]*$/.test(normalized)) {
535
+ throw new SiglumeWebhookSignatureError("Hex digest is invalid.");
536
+ }
537
+ const bytes = new Uint8Array(normalized.length / 2);
538
+ for (let index = 0; index < normalized.length; index += 2) {
539
+ bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);
540
+ }
541
+ return bytes;
542
+ }
543
+ async function timingSafeEqualHex(left, right) {
544
+ const leftBytes = hexToBytes(left);
545
+ const rightBytes = hexToBytes(right);
546
+ if (leftBytes.length !== rightBytes.length) {
547
+ return false;
548
+ }
549
+ let diff = 0;
550
+ for (let index = 0; index < leftBytes.length; index += 1) {
551
+ diff |= leftBytes[index] ^ rightBytes[index];
552
+ }
553
+ return diff === 0;
554
+ }
555
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export const DEFAULT_SIGLUME_API_BASE = \"https://siglume.com/v1\";\r\nexport const DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME = \"siglume-external-402-v1\";\r\nexport const DIRECT_REQUEST_PAYMENT_MODE = \"external_402\";\r\nexport const DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = \"api_store_direct_payment\";\r\nexport const DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = \"api_store_direct_payment_allowance\";\r\nexport const DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = \"api_store_direct_payment_requirement\";\r\nexport const DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;\r\n\r\nexport type DirectRequestPaymentCurrency = \"JPY\" | \"USD\";\r\nexport type DirectRequestPaymentToken = \"JPYC\" | \"USDC\";\r\n\r\nexport interface DirectRequestPaymentChallengeInput {\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency | string;\r\n secret: string;\r\n nonce?: string;\r\n}\r\n\r\nexport interface DirectRequestPaymentChallenge {\r\n scheme: typeof DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME;\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency;\r\n nonce: string;\r\n signature: string;\r\n challenge: string;\r\n challenge_hash: string;\r\n}\r\n\r\nexport interface ParsedDirectRequestPaymentChallenge {\r\n scheme: string;\r\n nonce: string;\r\n signature: string;\r\n}\r\n\r\nexport interface Web3TransactionRequest {\r\n network?: string;\r\n chain_id?: number;\r\n from?: string;\r\n to?: string;\r\n data?: string;\r\n value?: string | number;\r\n metadata_jsonb?: Record<string, unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface DirectPaymentRequirement {\r\n direct_payment_requirement_id: string;\r\n requirement_id: string;\r\n id: string;\r\n mode: string;\r\n merchant?: string | null;\r\n challenge_hash?: string | null;\r\n buyer_user_id: string;\r\n agent_id?: string | null;\r\n product_listing_id: string;\r\n listing_id: string;\r\n access_grant_id?: string | null;\r\n capability_key: string;\r\n requirement_hash: string;\r\n request_hash: string;\r\n siglume_signature: string;\r\n token_symbol: string;\r\n currency: string;\r\n amount_minor: number;\r\n fee_bps: number;\r\n status: string;\r\n expires_at?: string | null;\r\n confirmed_at?: string | null;\r\n spent_at?: string | null;\r\n chain_receipt_id?: string | null;\r\n transaction_request: Web3TransactionRequest;\r\n approve_transaction_request?: Web3TransactionRequest | null;\r\n buyer_confirmation?: string | null;\r\n non_custodial: boolean;\r\n metadata_jsonb?: Record<string, unknown>;\r\n created_at?: string | null;\r\n updated_at?: string | null;\r\n}\r\n\r\nexport interface DirectPaymentRequirementCreateInput {\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency | string;\r\n challenge: string;\r\n token_symbol?: DirectRequestPaymentToken | string;\r\n allowance_amount_minor?: number;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport interface DirectPaymentVerifyInput {\r\n receipt_id?: string | null;\r\n chain_receipt_id?: string | null;\r\n await_finality?: boolean;\r\n await_required_status?: string | null;\r\n await_timeout_seconds?: number;\r\n await_poll_seconds?: number;\r\n}\r\n\r\nexport interface Web3PreparedTransactionExecutePayload {\r\n transaction_request: Web3TransactionRequest;\r\n receipt_kind: string;\r\n reference_type: typeof DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE;\r\n reference_id: string;\r\n metadata?: Record<string, unknown>;\r\n await_finality?: boolean;\r\n}\r\n\r\nexport interface Web3PreparedTransactionExecuteResult {\r\n receipt?: Record<string, unknown>;\r\n finalization?: Record<string, unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface DirectRequestPaymentClientOptions {\r\n auth_token?: string;\r\n base_url?: string;\r\n fetch?: typeof fetch;\r\n timeout_ms?: number;\r\n user_agent?: string;\r\n}\r\n\r\nexport interface SiglumeEnvelopeMeta {\r\n request_id?: string | null;\r\n trace_id?: string | null;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WebhookSignatureVerification {\r\n timestamp: number;\r\n signature: string;\r\n}\r\n\r\nexport interface DirectRequestPaymentWebhookEvent {\r\n id: string;\r\n type: \"direct_payment.confirmed\" | string;\r\n api_version: string;\r\n occurred_at: string;\r\n data: {\r\n mode?: string;\r\n merchant?: string;\r\n direct_payment_requirement_id?: string;\r\n requirement_id?: string;\r\n challenge_hash?: string;\r\n amount_minor?: number;\r\n currency?: string;\r\n token_symbol?: string;\r\n status?: string;\r\n [key: string]: unknown;\r\n };\r\n [key: string]: unknown;\r\n}\r\n\r\nexport class SiglumeDirectRequestPaymentError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"SiglumeDirectRequestPaymentError\";\r\n }\r\n}\r\n\r\nexport class SiglumeApiError extends SiglumeDirectRequestPaymentError {\r\n readonly status: number;\r\n readonly code: string;\r\n readonly data: unknown;\r\n\r\n constructor(message: string, options: { status: number; code?: string; data?: unknown }) {\r\n super(message);\r\n this.name = \"SiglumeApiError\";\r\n this.status = options.status;\r\n this.code = options.code ?? \"SIGLUME_API_ERROR\";\r\n this.data = options.data;\r\n }\r\n}\r\n\r\nexport class SiglumeWebhookSignatureError extends SiglumeDirectRequestPaymentError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"SiglumeWebhookSignatureError\";\r\n }\r\n}\r\n\r\nexport class SiglumeWebhookPayloadError extends SiglumeDirectRequestPaymentError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"SiglumeWebhookPayloadError\";\r\n }\r\n}\r\n\r\nexport class DirectRequestPaymentClient {\r\n readonly auth_token: string;\r\n readonly base_url: string;\r\n readonly timeout_ms: number;\r\n readonly user_agent: string;\r\n private readonly fetch_impl: typeof fetch;\r\n\r\n constructor(options: DirectRequestPaymentClientOptions = {}) {\r\n const authToken = options.auth_token ?? envValue(\"SIGLUME_AUTH_TOKEN\");\r\n if (!authToken) {\r\n throw new SiglumeDirectRequestPaymentError(\r\n \"A buyer Siglume bearer token is required for Direct Request Payment API calls. Developer Portal API keys are not accepted.\",\r\n );\r\n }\r\n const fetchImpl = options.fetch ?? globalThis.fetch;\r\n if (!fetchImpl) {\r\n throw new SiglumeDirectRequestPaymentError(\"A fetch implementation is required in this runtime.\");\r\n }\r\n this.auth_token = authToken;\r\n this.base_url = (options.base_url ?? envValue(\"SIGLUME_API_BASE\") ?? DEFAULT_SIGLUME_API_BASE).replace(/\\/+$/, \"\");\r\n this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15000));\r\n this.user_agent = options.user_agent ?? \"@siglume/direct-request-payment/0.1.0\";\r\n this.fetch_impl = fetchImpl;\r\n }\r\n\r\n async createPaymentRequirement(input: DirectPaymentRequirementCreateInput): Promise<DirectPaymentRequirement> {\r\n const payload: Record<string, unknown> = {\r\n mode: DIRECT_REQUEST_PAYMENT_MODE,\r\n merchant: normalizeMerchant(input.merchant),\r\n amount_minor: positiveInteger(input.amount_minor, \"amount_minor\"),\r\n currency: normalizeCurrency(input.currency),\r\n challenge: requireNonEmpty(input.challenge, \"challenge\"),\r\n };\r\n if (input.token_symbol !== undefined) {\r\n payload.token_symbol = normalizeToken(input.token_symbol);\r\n }\r\n if (input.allowance_amount_minor !== undefined) {\r\n payload.allowance_amount_minor = positiveInteger(input.allowance_amount_minor, \"allowance_amount_minor\");\r\n }\r\n if (input.metadata !== undefined) {\r\n payload.metadata = cloneJsonObject(input.metadata, \"metadata\");\r\n }\r\n return this.request<DirectPaymentRequirement>(\"POST\", \"/market/api-store/direct-payments/requirements\", payload);\r\n }\r\n\r\n async getPaymentRequirement(requirement_id: string): Promise<DirectPaymentRequirement> {\r\n return this.request<DirectPaymentRequirement>(\r\n \"GET\",\r\n `/market/api-store/direct-payments/requirements/${encodeURIComponent(requireNonEmpty(requirement_id, \"requirement_id\"))}`,\r\n );\r\n }\r\n\r\n async verifyPaymentRequirement(\r\n requirement_id: string,\r\n input: DirectPaymentVerifyInput,\r\n ): Promise<DirectPaymentRequirement> {\r\n return this.request<DirectPaymentRequirement>(\r\n \"POST\",\r\n `/market/api-store/direct-payments/requirements/${encodeURIComponent(requireNonEmpty(requirement_id, \"requirement_id\"))}/verify`,\r\n input,\r\n );\r\n }\r\n\r\n async executePreparedTransaction(\r\n payload: Web3PreparedTransactionExecutePayload,\r\n ): Promise<Web3PreparedTransactionExecuteResult> {\r\n return this.request<Web3PreparedTransactionExecuteResult>(\r\n \"POST\",\r\n \"/market/web3/transactions/execute-prepared\",\r\n payload,\r\n );\r\n }\r\n\r\n async executePaymentTransaction(\r\n requirement: DirectPaymentRequirement,\r\n options: { await_finality?: boolean; metadata?: Record<string, unknown> } = {},\r\n ): Promise<Web3PreparedTransactionExecuteResult> {\r\n return this.executePreparedTransaction(buildPaymentExecutionPayload(requirement, options));\r\n }\r\n\r\n async executeAllowanceTransaction(\r\n requirement: DirectPaymentRequirement,\r\n options: { await_finality?: boolean; metadata?: Record<string, unknown> } = {},\r\n ): Promise<Web3PreparedTransactionExecuteResult> {\r\n return this.executePreparedTransaction(buildAllowanceExecutionPayload(requirement, options));\r\n }\r\n\r\n async request<T>(method: string, path: string, json_body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), this.timeout_ms);\r\n try {\r\n const headers: Record<string, string> = {\r\n \"Accept\": \"application/json\",\r\n \"Authorization\": `Bearer ${this.auth_token}`,\r\n \"User-Agent\": this.user_agent,\r\n };\r\n let body: string | undefined;\r\n if (json_body !== undefined) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n body = JSON.stringify(json_body);\r\n }\r\n const response = await this.fetch_impl(`${this.base_url}${path}`, {\r\n method,\r\n headers,\r\n body,\r\n signal: controller.signal,\r\n });\r\n const rawText = await response.text();\r\n const parsed = rawText ? parseJson(rawText) : {};\r\n if (!response.ok) {\r\n const error = isRecord(parsed) && isRecord(parsed.error) ? parsed.error : {};\r\n const code = stringOrNull(error.code) ?? stringOrNull((parsed as Record<string, unknown>).code) ?? `HTTP_${response.status}`;\r\n const message = stringOrNull(error.message) ?? stringOrNull((parsed as Record<string, unknown>).message) ?? response.statusText;\r\n throw new SiglumeApiError(message, { status: response.status, code, data: parsed });\r\n }\r\n if (isRecord(parsed) && \"data\" in parsed) {\r\n return parsed.data as T;\r\n }\r\n return parsed as T;\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n }\r\n}\r\n\r\nexport async function createDirectRequestPaymentChallenge(\r\n input: DirectRequestPaymentChallengeInput,\r\n): Promise<DirectRequestPaymentChallenge> {\r\n const merchant = normalizeMerchant(input.merchant);\r\n const amount_minor = positiveInteger(input.amount_minor, \"amount_minor\");\r\n const currency = normalizeCurrency(input.currency);\r\n const nonce = input.nonce ? normalizeChallengeNonce(input.nonce) : await randomNonce();\r\n const signature = await createDirectRequestPaymentChallengeSignature(input.secret, {\r\n merchant,\r\n amount_minor,\r\n currency,\r\n nonce,\r\n });\r\n const challenge = `${DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME}:${nonce}:${signature}`;\r\n return {\r\n scheme: DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME,\r\n merchant,\r\n amount_minor,\r\n currency,\r\n nonce,\r\n signature,\r\n challenge,\r\n challenge_hash: await sha256Prefixed(challenge),\r\n };\r\n}\r\n\r\nexport async function createDirectRequestPaymentChallengeSignature(\r\n secret: string,\r\n input: {\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency | string;\r\n nonce: string;\r\n },\r\n): Promise<string> {\r\n const normalizedSecret = requireNonEmpty(secret, \"secret\");\r\n const merchant = normalizeMerchant(input.merchant);\r\n const amount = positiveInteger(input.amount_minor, \"amount_minor\");\r\n const currency = normalizeCurrency(input.currency);\r\n const nonce = normalizeChallengeNonce(input.nonce);\r\n const material = `${merchant}:${amount}:${currency}:${nonce}`;\r\n return hmacSha256Hex(normalizedSecret, new TextEncoder().encode(material));\r\n}\r\n\r\nexport function parseDirectRequestPaymentChallenge(challenge: string): ParsedDirectRequestPaymentChallenge {\r\n const parts = requireNonEmpty(challenge, \"challenge\").split(\":\");\r\n if (parts.length !== 3) {\r\n throw new SiglumeDirectRequestPaymentError(\"Direct Request Payment challenge must be scheme:nonce:signature.\");\r\n }\r\n const [scheme, nonce, signature] = parts;\r\n if (!scheme || !nonce || !signature) {\r\n throw new SiglumeDirectRequestPaymentError(\"Direct Request Payment challenge is incomplete.\");\r\n }\r\n return { scheme, nonce, signature };\r\n}\r\n\r\nexport async function verifyDirectRequestPaymentChallenge(\r\n secret: string,\r\n input: {\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency | string;\r\n challenge: string;\r\n },\r\n): Promise<boolean> {\r\n const parsed = parseDirectRequestPaymentChallenge(input.challenge);\r\n if (parsed.scheme !== DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME) {\r\n return false;\r\n }\r\n const expected = await createDirectRequestPaymentChallengeSignature(secret, {\r\n merchant: input.merchant,\r\n amount_minor: input.amount_minor,\r\n currency: input.currency,\r\n nonce: parsed.nonce,\r\n });\r\n return timingSafeEqualHex(expected, parsed.signature);\r\n}\r\n\r\nexport async function directRequestPaymentChallengeHash(challenge: string): Promise<string> {\r\n return sha256Prefixed(requireNonEmpty(challenge, \"challenge\"));\r\n}\r\n\r\nexport async function directRequestPaymentRequestHash(input: {\r\n merchant: string;\r\n amount_minor: number;\r\n currency: DirectRequestPaymentCurrency | string;\r\n challenge: string;\r\n}): Promise<string> {\r\n const material = `${normalizeMerchant(input.merchant)}${positiveInteger(input.amount_minor, \"amount_minor\")}${normalizeCurrency(input.currency)}${requireNonEmpty(input.challenge, \"challenge\")}`;\r\n return sha256Prefixed(material);\r\n}\r\n\r\nexport function buildPaymentExecutionPayload(\r\n requirement: DirectPaymentRequirement,\r\n options: { await_finality?: boolean; metadata?: Record<string, unknown> } = {},\r\n): Web3PreparedTransactionExecutePayload {\r\n return buildPreparedTransactionExecutionPayload(requirement, requirement.transaction_request, {\r\n receipt_kind: DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,\r\n await_finality: options.await_finality,\r\n metadata: options.metadata,\r\n });\r\n}\r\n\r\nexport function buildAllowanceExecutionPayload(\r\n requirement: DirectPaymentRequirement,\r\n options: { await_finality?: boolean; metadata?: Record<string, unknown> } = {},\r\n): Web3PreparedTransactionExecutePayload {\r\n const approveRequest = requirement.approve_transaction_request;\r\n if (!approveRequest || Object.keys(approveRequest).length === 0) {\r\n throw new SiglumeDirectRequestPaymentError(\"This payment requirement does not include an allowance approval transaction.\");\r\n }\r\n return buildPreparedTransactionExecutionPayload(requirement, approveRequest, {\r\n receipt_kind: DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND,\r\n await_finality: options.await_finality,\r\n metadata: options.metadata,\r\n });\r\n}\r\n\r\nexport function buildPreparedTransactionExecutionPayload(\r\n requirement: DirectPaymentRequirement,\r\n transaction_request: Web3TransactionRequest,\r\n options: {\r\n receipt_kind: string;\r\n await_finality?: boolean;\r\n metadata?: Record<string, unknown>;\r\n },\r\n): Web3PreparedTransactionExecutePayload {\r\n const metadata = {\r\n ...(isRecord(transaction_request.metadata_jsonb) ? transaction_request.metadata_jsonb : {}),\r\n ...(options.metadata ?? {}),\r\n };\r\n return {\r\n transaction_request,\r\n receipt_kind: requireNonEmpty(options.receipt_kind, \"receipt_kind\"),\r\n reference_type: DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE,\r\n reference_id: requirement.requirement_id,\r\n metadata,\r\n await_finality: Boolean(options.await_finality),\r\n };\r\n}\r\n\r\nexport async function computeWebhookSignature(\r\n signing_secret: string,\r\n body: Uint8Array | ArrayBuffer | string | Record<string, unknown>,\r\n options: { timestamp: number },\r\n): Promise<string> {\r\n if (!signing_secret) {\r\n throw new SiglumeWebhookSignatureError(\"SIGLUME webhook signing secret is required.\");\r\n }\r\n const timestamp = Math.trunc(options.timestamp);\r\n const bytes = bodyBytes(body);\r\n const prefix = new TextEncoder().encode(`${timestamp}.`);\r\n const payload = new Uint8Array(prefix.length + bytes.length);\r\n payload.set(prefix, 0);\r\n payload.set(bytes, prefix.length);\r\n return hmacSha256Hex(signing_secret, payload);\r\n}\r\n\r\nexport async function buildWebhookSignatureHeader(\r\n signing_secret: string,\r\n body: Uint8Array | ArrayBuffer | string | Record<string, unknown>,\r\n options: { timestamp?: number } = {},\r\n): Promise<string> {\r\n const timestamp = Math.trunc(options.timestamp ?? Date.now() / 1000);\r\n const signature = await computeWebhookSignature(signing_secret, body, { timestamp });\r\n return `t=${timestamp},v1=${signature}`;\r\n}\r\n\r\nexport async function verifyWebhookSignature(\r\n signing_secret: string,\r\n body: Uint8Array | ArrayBuffer | string | Record<string, unknown>,\r\n signature_header: string,\r\n options: { tolerance_seconds?: number; now?: number } = {},\r\n): Promise<WebhookSignatureVerification> {\r\n const { timestamp, signature } = parseSignatureHeader(signature_header);\r\n const toleranceSeconds = Math.max(1, Math.trunc(options.tolerance_seconds ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS));\r\n const nowSeconds = Math.trunc(options.now ?? Date.now() / 1000);\r\n if (Math.abs(nowSeconds - timestamp) > toleranceSeconds) {\r\n throw new SiglumeWebhookSignatureError(\"Webhook timestamp is outside the allowed tolerance window.\");\r\n }\r\n const expected = await computeWebhookSignature(signing_secret, body, { timestamp });\r\n if (!(await timingSafeEqualHex(expected, signature))) {\r\n throw new SiglumeWebhookSignatureError(\"Webhook signature did not match.\");\r\n }\r\n return { timestamp, signature };\r\n}\r\n\r\nexport function parseDirectRequestPaymentWebhookEvent(payload: unknown): DirectRequestPaymentWebhookEvent {\r\n const event = requireRecord(payload, \"webhook event\");\r\n const data = requireRecord(event.data, \"webhook event data\");\r\n const parsed = {\r\n ...event,\r\n id: requireNonEmpty(stringOrNull(event.id) ?? \"\", \"webhook event id\"),\r\n type: requireNonEmpty(stringOrNull(event.type) ?? \"\", \"webhook event type\"),\r\n api_version: requireNonEmpty(stringOrNull(event.api_version) ?? \"\", \"webhook api_version\"),\r\n occurred_at: requireNonEmpty(stringOrNull(event.occurred_at) ?? \"\", \"webhook occurred_at\"),\r\n data: { ...data },\r\n } as DirectRequestPaymentWebhookEvent;\r\n if (parsed.type === \"direct_payment.confirmed\" && parsed.data.mode !== DIRECT_REQUEST_PAYMENT_MODE) {\r\n throw new SiglumeWebhookPayloadError(\"direct_payment.confirmed webhook must carry data.mode='external_402'.\");\r\n }\r\n return parsed;\r\n}\r\n\r\nexport async function verifyDirectRequestPaymentWebhook(\r\n signing_secret: string,\r\n body: Uint8Array | ArrayBuffer | string | Record<string, unknown>,\r\n signature_header: string,\r\n options: { tolerance_seconds?: number; now?: number } = {},\r\n): Promise<{ event: DirectRequestPaymentWebhookEvent; verification: WebhookSignatureVerification }> {\r\n const verification = await verifyWebhookSignature(signing_secret, body, signature_header, options);\r\n const text = new TextDecoder().decode(bodyBytes(body));\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(text);\r\n } catch (error) {\r\n throw new SiglumeWebhookPayloadError(\"Webhook body must contain valid JSON.\");\r\n }\r\n return { event: parseDirectRequestPaymentWebhookEvent(parsed), verification };\r\n}\r\n\r\nexport const createExternal402Challenge = createDirectRequestPaymentChallenge;\r\nexport const verifyExternal402Challenge = verifyDirectRequestPaymentChallenge;\r\n\r\nfunction normalizeMerchant(value: string): string {\r\n const merchant = requireNonEmpty(value, \"merchant\").toLowerCase();\r\n if (!/^[a-z0-9][a-z0-9._-]{0,95}$/.test(merchant)) {\r\n throw new SiglumeDirectRequestPaymentError(\"merchant must be a lowercase key using letters, numbers, dot, underscore, or hyphen.\");\r\n }\r\n return merchant;\r\n}\r\n\r\nfunction normalizeCurrency(value: string): DirectRequestPaymentCurrency {\r\n const currency = requireNonEmpty(value, \"currency\").toUpperCase();\r\n if (currency !== \"JPY\" && currency !== \"USD\") {\r\n throw new SiglumeDirectRequestPaymentError(\"currency must be JPY or USD.\");\r\n }\r\n return currency;\r\n}\r\n\r\nfunction normalizeToken(value: string): DirectRequestPaymentToken {\r\n const token = requireNonEmpty(value, \"token_symbol\").toUpperCase();\r\n if (token !== \"JPYC\" && token !== \"USDC\") {\r\n throw new SiglumeDirectRequestPaymentError(\"token_symbol must be JPYC or USDC.\");\r\n }\r\n return token;\r\n}\r\n\r\nfunction positiveInteger(value: number, name: string): number {\r\n const parsed = Number(value);\r\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\r\n throw new SiglumeDirectRequestPaymentError(`${name} must be a positive safe integer.`);\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction requireNonEmpty(value: string, name: string): string {\r\n const text = String(value ?? \"\").trim();\r\n if (!text) {\r\n throw new SiglumeDirectRequestPaymentError(`${name} is required.`);\r\n }\r\n return text;\r\n}\r\n\r\nfunction normalizeChallengeNonce(value: string): string {\r\n const nonce = requireNonEmpty(value, \"nonce\");\r\n if (nonce.includes(\":\")) {\r\n throw new SiglumeDirectRequestPaymentError(\"nonce must not contain ':'.\");\r\n }\r\n return nonce;\r\n}\r\n\r\nfunction cloneJsonObject(value: Record<string, unknown>, name: string): Record<string, unknown> {\r\n try {\r\n const cloned = JSON.parse(JSON.stringify(value)) as unknown;\r\n if (!isRecord(cloned)) {\r\n throw new Error(\"not an object\");\r\n }\r\n return cloned;\r\n } catch (error) {\r\n throw new SiglumeDirectRequestPaymentError(`${name} must be a JSON-serializable object.`);\r\n }\r\n}\r\n\r\nfunction parseJson(rawText: string): unknown {\r\n try {\r\n return JSON.parse(rawText);\r\n } catch (error) {\r\n throw new SiglumeApiError(\"Siglume API returned invalid JSON.\", {\r\n status: 502,\r\n code: \"INVALID_JSON_RESPONSE\",\r\n data: rawText,\r\n });\r\n }\r\n}\r\n\r\nfunction stringOrNull(value: unknown): string | null {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n const text = value.trim();\r\n return text ? text : null;\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction requireRecord(value: unknown, name: string): Record<string, unknown> {\r\n if (!isRecord(value)) {\r\n throw new SiglumeWebhookPayloadError(`${name} must be an object.`);\r\n }\r\n return value;\r\n}\r\n\r\nfunction envValue(name: string): string | undefined {\r\n if (typeof process === \"undefined\") {\r\n return undefined;\r\n }\r\n const value = process.env[name];\r\n return value && value.trim() ? value.trim() : undefined;\r\n}\r\n\r\nfunction bodyBytes(body: Uint8Array | ArrayBuffer | string | Record<string, unknown>): Uint8Array {\r\n if (body instanceof Uint8Array) {\r\n return body;\r\n }\r\n if (body instanceof ArrayBuffer) {\r\n return new Uint8Array(body);\r\n }\r\n if (typeof body === \"string\") {\r\n return new TextEncoder().encode(body);\r\n }\r\n if (isRecord(body)) {\r\n return new TextEncoder().encode(JSON.stringify(body));\r\n }\r\n throw new SiglumeWebhookPayloadError(\"Webhook body must be raw bytes, a string, or a JSON object.\");\r\n}\r\n\r\nfunction parseSignatureHeader(signatureHeader: string): { timestamp: number; signature: string } {\r\n let timestamp: number | null = null;\r\n let signature: string | null = null;\r\n for (const item of String(signatureHeader ?? \"\").split(\",\")) {\r\n const [key, value] = item.trim().split(\"=\", 2);\r\n if (key === \"t\") {\r\n const parsed = Number.parseInt(value ?? \"\", 10);\r\n if (!Number.isFinite(parsed)) {\r\n throw new SiglumeWebhookSignatureError(\"Webhook signature timestamp is invalid.\");\r\n }\r\n timestamp = parsed;\r\n }\r\n if (key === \"v1\") {\r\n signature = String(value ?? \"\").trim();\r\n }\r\n }\r\n if (timestamp === null || !signature) {\r\n throw new SiglumeWebhookSignatureError(\"Webhook signature header is incomplete.\");\r\n }\r\n return { timestamp, signature };\r\n}\r\n\r\nasync function randomNonce(): Promise<string> {\r\n if (globalThis.crypto?.randomUUID) {\r\n return globalThis.crypto.randomUUID();\r\n }\r\n const bytes = new Uint8Array(16);\r\n if (globalThis.crypto?.getRandomValues) {\r\n globalThis.crypto.getRandomValues(bytes);\r\n } else if (typeof process !== \"undefined\" && process.versions?.node) {\r\n const crypto = await import(\"node:crypto\");\r\n bytes.set(crypto.randomBytes(16));\r\n } else {\r\n throw new SiglumeDirectRequestPaymentError(\"Crypto random number generation is unavailable in this runtime.\");\r\n }\r\n return bytesToHex(bytes);\r\n}\r\n\r\nasync function hmacSha256Hex(secret: string, payload: Uint8Array): Promise<string> {\r\n if (globalThis.crypto?.subtle) {\r\n const stablePayload = new Uint8Array(payload.byteLength);\r\n stablePayload.set(payload);\r\n const key = await globalThis.crypto.subtle.importKey(\r\n \"raw\",\r\n new TextEncoder().encode(secret),\r\n { name: \"HMAC\", hash: \"SHA-256\" },\r\n false,\r\n [\"sign\"],\r\n );\r\n const digest = await globalThis.crypto.subtle.sign(\"HMAC\", key, stablePayload);\r\n return bytesToHex(new Uint8Array(digest));\r\n }\r\n if (typeof process !== \"undefined\" && process.versions?.node) {\r\n const crypto = await import(\"node:crypto\");\r\n return crypto.createHmac(\"sha256\", secret).update(Buffer.from(payload)).digest(\"hex\");\r\n }\r\n throw new SiglumeDirectRequestPaymentError(\"Web Crypto is required for HMAC-SHA256 in this runtime.\");\r\n}\r\n\r\nasync function sha256Prefixed(material: string): Promise<string> {\r\n const bytes = new TextEncoder().encode(material);\r\n if (globalThis.crypto?.subtle) {\r\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\r\n return `sha256:${bytesToHex(new Uint8Array(digest))}`;\r\n }\r\n if (typeof process !== \"undefined\" && process.versions?.node) {\r\n const crypto = await import(\"node:crypto\");\r\n return `sha256:${crypto.createHash(\"sha256\").update(Buffer.from(bytes)).digest(\"hex\")}`;\r\n }\r\n throw new SiglumeDirectRequestPaymentError(\"Web Crypto is required for SHA-256 in this runtime.\");\r\n}\r\n\r\nfunction bytesToHex(bytes: Uint8Array): string {\r\n return [...bytes].map((item) => item.toString(16).padStart(2, \"0\")).join(\"\");\r\n}\r\n\r\nfunction hexToBytes(hex: string): Uint8Array {\r\n const normalized = String(hex ?? \"\").trim().toLowerCase();\r\n if (normalized.length % 2 !== 0 || !/^[0-9a-f]*$/.test(normalized)) {\r\n throw new SiglumeWebhookSignatureError(\"Hex digest is invalid.\");\r\n }\r\n const bytes = new Uint8Array(normalized.length / 2);\r\n for (let index = 0; index < normalized.length; index += 2) {\r\n bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);\r\n }\r\n return bytes;\r\n}\r\n\r\nasync function timingSafeEqualHex(left: string, right: string): Promise<boolean> {\r\n const leftBytes = hexToBytes(left);\r\n const rightBytes = hexToBytes(right);\r\n if (leftBytes.length !== rightBytes.length) {\r\n return false;\r\n }\r\n let diff = 0;\r\n for (let index = 0; index < leftBytes.length; index += 1) {\r\n diff |= leftBytes[index]! ^ rightBytes[index]!;\r\n }\r\n return diff === 0;\r\n}\r\n"],"mappings":"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","names":[]}