@lacasoft/openrelay-sdk 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.
@@ -0,0 +1,277 @@
1
+ import { SupportedChain, CreatePaymentIntentParams, PaymentIntent, WebhookEvent, X402MiddlewareOptions } from '@lacasoft/openrelay-protocol';
2
+ export { AuthError, CreatePaymentIntentParams, NetworkError, OpenRelayError, OpenRelayErrorCode, OpenRelaySDKError, PaymentIntent, RoutingError, SupportedChain, USDC_ADDRESSES, ValidationError, WebhookEvent, X402MiddlewareOptions, classifyError } from '@lacasoft/openrelay-protocol';
3
+ import { Address, Hex } from 'viem';
4
+
5
+ interface LogEntry {
6
+ request_id: string;
7
+ method: string;
8
+ path: string;
9
+ status: number;
10
+ latency_ms: number;
11
+ /** Nodeit wallet selected for routing, if returned by the API. */
12
+ node_route: string | null;
13
+ }
14
+ interface OpenRelayConfig {
15
+ apiKey: string;
16
+ baseUrl?: string;
17
+ timeout?: number;
18
+ merchantWallet?: string;
19
+ /** Optional structured-log hook called after every SDK request. */
20
+ logger?: (entry: LogEntry) => void;
21
+ }
22
+
23
+ interface BuildAuthorizationParams {
24
+ /** Payer address — the `from` of the USDC transfer. Must match the signer. */
25
+ payer: Address;
26
+ /** Amount in USDC base units (6 decimals). Must match the intent's amount. */
27
+ amount: bigint;
28
+ /** SettlementHub contract address — the `to` of the authorization. */
29
+ settlementHub: Address;
30
+ /** Which chain — picks USDC contract address + chainId. */
31
+ chain: SupportedChain;
32
+ /** Optional 32-byte random nonce. SDK generates one if omitted. */
33
+ nonce?: Hex;
34
+ /** Unix seconds; signature invalid before this. Default: 0 (always valid from start). */
35
+ validAfter?: bigint;
36
+ /** Unix seconds; signature invalid after this. Default: now + 30 minutes. */
37
+ validBefore?: bigint;
38
+ }
39
+ interface AuthorizationMessage {
40
+ from: Address;
41
+ to: Address;
42
+ value: bigint;
43
+ validAfter: bigint;
44
+ validBefore: bigint;
45
+ nonce: Hex;
46
+ }
47
+ interface AuthorizationTypedData {
48
+ domain: {
49
+ name: string;
50
+ version: string;
51
+ chainId: number;
52
+ verifyingContract: Address;
53
+ };
54
+ types: {
55
+ EIP712Domain: {
56
+ name: string;
57
+ type: string;
58
+ }[];
59
+ ReceiveWithAuthorization: {
60
+ name: string;
61
+ type: string;
62
+ }[];
63
+ };
64
+ primaryType: 'ReceiveWithAuthorization';
65
+ message: AuthorizationMessage;
66
+ }
67
+ declare function buildReceiveAuthorizationTypedData(params: BuildAuthorizationParams): AuthorizationTypedData;
68
+ interface SignedAuthorization {
69
+ /** Payer address (the `from` of the USDC transfer). */
70
+ payer: Address;
71
+ /** Authorization validity window. */
72
+ validAfter: bigint;
73
+ validBefore: bigint;
74
+ /** 32-byte random nonce, hex-encoded. */
75
+ nonce: Hex;
76
+ /** ECDSA signature components. */
77
+ v: number;
78
+ r: Hex;
79
+ s: Hex;
80
+ }
81
+ declare function signReceiveAuthorization(params: BuildAuthorizationParams, privateKey: Hex): Promise<SignedAuthorization>;
82
+ declare function splitSignature(signature: Hex): {
83
+ v: number;
84
+ r: Hex;
85
+ s: Hex;
86
+ };
87
+ declare function generateNonce(): Hex;
88
+
89
+ interface SubmitAuthorizationResponse {
90
+ /** Echoed intent id. */
91
+ intent_id: string;
92
+ /** Server-side estimate of when the operator will submit it on-chain. */
93
+ estimated_settlement_at: string | null;
94
+ /** Authorization persisted server-side, awaiting operator pickup. */
95
+ status: 'queued';
96
+ }
97
+ interface SubmitAuthorizationBatchResponse {
98
+ /** Per-authorization queueing result. Order matches the input. */
99
+ results: Array<{
100
+ intent_id: string;
101
+ status: 'queued' | 'rejected';
102
+ reason?: string;
103
+ }>;
104
+ queued: number;
105
+ rejected: number;
106
+ }
107
+ declare class PaymentIntents {
108
+ private config;
109
+ constructor(config: OpenRelayConfig);
110
+ /**
111
+ * Create a new payment intent.
112
+ *
113
+ * @example
114
+ * const intent = await relay.paymentIntents.create({
115
+ * amount: 1000, // $0.001000 USDC (6 decimals)
116
+ * currency: 'usdc',
117
+ * chain: 'base',
118
+ * metadata: { orderId: 'order_123' }
119
+ * })
120
+ */
121
+ create(params: CreatePaymentIntentParams): Promise<PaymentIntent>;
122
+ /**
123
+ * Retrieve a payment intent by ID.
124
+ */
125
+ retrieve(id: string): Promise<PaymentIntent>;
126
+ /**
127
+ * Cancel a payment intent (only valid while it is in 'created' state).
128
+ */
129
+ cancel(id: string): Promise<PaymentIntent>;
130
+ /**
131
+ * List payment intents for the authenticated merchant.
132
+ */
133
+ list(params?: {
134
+ limit?: number;
135
+ starting_after?: string;
136
+ }): Promise<{
137
+ data: PaymentIntent[];
138
+ has_more: boolean;
139
+ }>;
140
+ /**
141
+ * Build the EIP-712 typed-data structure for `ReceiveWithAuthorization`
142
+ * that USDC verifies on `payIntentWithAuthorization`. Hand the result to
143
+ * a wallet (viem `walletClient.signTypedData`, `window.ethereum`, etc.)
144
+ * to obtain a signature client-side.
145
+ *
146
+ * For server-side signing with a private key, prefer `signAuthorization`.
147
+ *
148
+ * @example (browser/wallet flow)
149
+ * const typed = relay.paymentIntents.buildAuthorizationTypedData({
150
+ * payer: '0xPayer...',
151
+ * amount: 5_000_000n, // 5 USDC (6 decimals)
152
+ * settlementHub: '0xHub...',
153
+ * chain: 'base-sepolia',
154
+ * })
155
+ * const signature = await walletClient.signTypedData(typed)
156
+ * const { v, r, s } = relay.paymentIntents.splitSignature(signature)
157
+ * await relay.paymentIntents.submitAuthorization(intentId, {
158
+ * payer: typed.message.from,
159
+ * validAfter: typed.message.validAfter,
160
+ * validBefore: typed.message.validBefore,
161
+ * nonce: typed.message.nonce,
162
+ * v, r, s,
163
+ * })
164
+ */
165
+ buildAuthorizationTypedData(params: BuildAuthorizationParams): AuthorizationTypedData;
166
+ /**
167
+ * Server-side convenience: build + sign the `ReceiveWithAuthorization`
168
+ * message in one call. Returns everything needed for `submitAuthorization`.
169
+ *
170
+ * @example
171
+ * const auth = await relay.paymentIntents.signAuthorization(
172
+ * { payer, amount: 5_000_000n, settlementHub, chain: 'base-sepolia' },
173
+ * privateKey,
174
+ * )
175
+ * await relay.paymentIntents.submitAuthorization(intentId, auth)
176
+ */
177
+ signAuthorization(params: BuildAuthorizationParams, privateKey: Hex): Promise<SignedAuthorization>;
178
+ /**
179
+ * Submit a signed authorization for a registered intent. The API queues
180
+ * it for the assigned operator to settle on-chain (via
181
+ * `SettlementHub.payIntentWithAuthorization`).
182
+ *
183
+ * The endpoint is implemented in Phase B3; this client method targets
184
+ * the documented path so SDK + API can be developed in parallel.
185
+ */
186
+ submitAuthorization(intentId: string, auth: SignedAuthorization): Promise<SubmitAuthorizationResponse>;
187
+ /**
188
+ * Submit multiple signed authorizations in one HTTP request. The operator
189
+ * may settle them via `SettlementHub.payIntentBatchWithAuthorization`
190
+ * (skip-on-failure). Useful for x402 micropayment flows where many small
191
+ * payments are aggregated.
192
+ *
193
+ * Hard cap: `MAX_BATCH_SIZE` (matches `SettlementHub.MAX_BATCH_SIZE`,
194
+ * imported from `@lacasoft/openrelay-protocol` SSOT — never hardcode the literal).
195
+ */
196
+ submitAuthorizationBatch(items: Array<{
197
+ intent_id: string;
198
+ authorization: SignedAuthorization;
199
+ }>): Promise<SubmitAuthorizationBatchResponse>;
200
+ /**
201
+ * Helper to split a 65-byte signature (e.g. from `walletClient.signTypedData`)
202
+ * into the {v, r, s} triple that `submitAuthorization` expects.
203
+ */
204
+ splitSignature(signature: Hex): {
205
+ v: number;
206
+ r: Hex;
207
+ s: Hex;
208
+ };
209
+ }
210
+
211
+ declare class Webhooks {
212
+ private config;
213
+ constructor(config: OpenRelayConfig);
214
+ register(url: string, events: string[]): Promise<{
215
+ id: string;
216
+ url: string;
217
+ secret: string;
218
+ }>;
219
+ /**
220
+ * Verify a webhook payload signature.
221
+ * Call this in your webhook handler to ensure the request is from OpenRelay.
222
+ *
223
+ * Validates: (1) signature format, (2) timestamp freshness against
224
+ * `toleranceSeconds` to mitigate replay, (3) HMAC equality with
225
+ * timing-safe compare.
226
+ *
227
+ * @example
228
+ * const event = relay.webhooks.verify(rawBody, req.headers['openrelay-signature'], secret)
229
+ */
230
+ verify(payload: string, signature: string, secret: string, toleranceSeconds?: number): WebhookEvent;
231
+ }
232
+
233
+ declare class X402 {
234
+ private config;
235
+ constructor(config: OpenRelayConfig);
236
+ /**
237
+ * Returns a Fastify preHandler hook that requires x402 payment.
238
+ *
239
+ * @example
240
+ * app.addHook('preHandler', relay.x402.middleware({
241
+ * price: 1000, // $0.001 USDC
242
+ * currency: 'usdc',
243
+ * chain: 'base',
244
+ * }))
245
+ */
246
+ middleware(opts: X402MiddlewareOptions): (req: Request, reply: Response) => Promise<Response | undefined>;
247
+ /**
248
+ * Returns a Next.js App Router compatible handler that wraps a route with x402.
249
+ *
250
+ * @example
251
+ * export const GET = relay.x402.handler({
252
+ * price: 1000,
253
+ * handler: async (req) => Response.json({ data: 'protected' })
254
+ * })
255
+ */
256
+ handler(opts: X402MiddlewareOptions & {
257
+ handler: (req: Request) => Promise<Response>;
258
+ }): (req: Request) => Promise<Response>;
259
+ /**
260
+ * Shared gate: extract X-PAYMENT, verify against the API, and either
261
+ * return a 402 Response (challenge or rejection) or null when payment
262
+ * is valid and the caller should proceed.
263
+ */
264
+ private gate;
265
+ private buildPaymentRequired;
266
+ private verify;
267
+ }
268
+
269
+ declare class OpenRelay {
270
+ private config;
271
+ readonly paymentIntents: PaymentIntents;
272
+ readonly webhooks: Webhooks;
273
+ readonly x402: X402;
274
+ constructor(config: OpenRelayConfig);
275
+ }
276
+
277
+ export { type AuthorizationMessage, type AuthorizationTypedData, type BuildAuthorizationParams, type LogEntry, OpenRelay, type OpenRelayConfig, type SignedAuthorization, type SubmitAuthorizationBatchResponse, type SubmitAuthorizationResponse, buildReceiveAuthorizationTypedData, generateNonce, signReceiveAuthorization, splitSignature };