@mixrpay/merchant-sdk 0.3.3 → 0.3.6
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.
Potentially problematic release.
This version of @mixrpay/merchant-sdk might be problematic. Click here for more details.
- package/README.md +32 -397
- package/dist/index.d.mts +169 -1
- package/dist/index.d.ts +169 -1
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +97 -3
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/express.mjs.map +1 -1
- package/dist/middleware/fastify.js.map +1 -1
- package/dist/middleware/fastify.mjs.map +1 -1
- package/dist/middleware/nextjs.js.map +1 -1
- package/dist/middleware/nextjs.mjs.map +1 -1
- package/package.json +2 -14
package/README.md
CHANGED
|
@@ -1,465 +1,100 @@
|
|
|
1
1
|
# @mixrpay/merchant-sdk
|
|
2
2
|
|
|
3
|
-
Accept payments from AI agents and web apps
|
|
3
|
+
Accept payments from AI agents and web apps.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @mixrpay/merchant-sdk
|
|
9
|
-
# or
|
|
10
|
-
yarn add @mixrpay/merchant-sdk
|
|
11
|
-
# or
|
|
12
|
-
pnpm add @mixrpay/merchant-sdk
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
### 1. Set Environment Variables
|
|
11
|
+
## Setup
|
|
18
12
|
|
|
19
13
|
```bash
|
|
20
14
|
# .env
|
|
21
|
-
MIXRPAY_PUBLIC_KEY=pk_live_...
|
|
22
|
-
MIXRPAY_SECRET_KEY=sk_live_...
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
MIXRPAY_MERCHANT_ADDRESS=0xYourWalletAddress
|
|
15
|
+
MIXRPAY_PUBLIC_KEY=pk_live_...
|
|
16
|
+
MIXRPAY_SECRET_KEY=sk_live_...
|
|
17
|
+
MIXRPAY_WEBHOOK_SECRET=whsec_...
|
|
18
|
+
MIXRPAY_HMAC_SECRET=hmac_...
|
|
26
19
|
```
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
Get credentials from [Developer Settings](https://www.mixrpay.com/seller/developers).
|
|
29
22
|
|
|
30
|
-
|
|
23
|
+
## API Middleware
|
|
24
|
+
|
|
25
|
+
### Express
|
|
31
26
|
|
|
32
27
|
```typescript
|
|
33
28
|
import express from 'express';
|
|
34
29
|
import { mixrpay } from '@mixrpay/merchant-sdk/express';
|
|
35
30
|
|
|
36
31
|
const app = express();
|
|
32
|
+
app.use(express.json());
|
|
37
33
|
|
|
38
|
-
// Accepts payments from Widget, Agent SDK, and x402 agents
|
|
39
34
|
app.post('/api/generate', mixrpay({ priceUsd: 0.05 }), (req, res) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.log(`Payment: $${amountUsd} via ${method} from ${payer}`);
|
|
44
|
-
|
|
45
|
-
const result = processRequest(req.body);
|
|
46
|
-
res.json(result);
|
|
35
|
+
const { payer, amountUsd } = req.mixrPayment!;
|
|
36
|
+
res.json({ result: 'success' });
|
|
47
37
|
});
|
|
48
|
-
|
|
49
|
-
// Dynamic pricing based on request
|
|
50
|
-
app.post('/api/ai', mixrpay({
|
|
51
|
-
getPrice: (req) => req.body?.premium ? 0.10 : 0.05
|
|
52
|
-
}), handler);
|
|
53
38
|
```
|
|
54
39
|
|
|
55
|
-
|
|
40
|
+
### Next.js
|
|
56
41
|
|
|
57
42
|
```typescript
|
|
58
|
-
// app/api/generate/route.ts
|
|
59
43
|
import { withMixrPay, MixrPayment } from '@mixrpay/merchant-sdk/nextjs';
|
|
60
44
|
import { NextRequest, NextResponse } from 'next/server';
|
|
61
45
|
|
|
62
46
|
async function handler(req: NextRequest, payment: MixrPayment) {
|
|
63
|
-
// payment contains: { payer, amountUsd, method, sessionId?, chargeId?, txHash? }
|
|
64
|
-
console.log(`Paid by ${payment.payer}: $${payment.amountUsd} via ${payment.method}`);
|
|
65
|
-
|
|
66
47
|
return NextResponse.json({ result: 'success' });
|
|
67
48
|
}
|
|
68
49
|
|
|
69
50
|
export const POST = withMixrPay({ priceUsd: 0.05 }, handler);
|
|
70
51
|
```
|
|
71
52
|
|
|
72
|
-
|
|
53
|
+
### Fastify
|
|
73
54
|
|
|
74
55
|
```typescript
|
|
75
56
|
import Fastify from 'fastify';
|
|
76
57
|
import { mixrpayPlugin, mixrpay } from '@mixrpay/merchant-sdk/fastify';
|
|
77
58
|
|
|
78
59
|
const app = Fastify();
|
|
60
|
+
app.register(mixrpayPlugin);
|
|
79
61
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
publicKey: process.env.MIXRPAY_PUBLIC_KEY,
|
|
83
|
-
secretKey: process.env.MIXRPAY_SECRET_KEY,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Use on routes
|
|
87
|
-
app.post('/api/generate', {
|
|
88
|
-
preHandler: mixrpay({ priceUsd: 0.05 })
|
|
89
|
-
}, async (req, reply) => {
|
|
90
|
-
return { result: 'success', payer: req.mixrPayment?.payer };
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Accepted Payment Methods
|
|
95
|
-
|
|
96
|
-
The middleware automatically handles **three payment methods**:
|
|
97
|
-
|
|
98
|
-
| Header | Source | Description |
|
|
99
|
-
|--------|--------|-------------|
|
|
100
|
-
| `X-Mixr-Session` | Agent SDK | Session-based payment (recommended for MixrPay clients) |
|
|
101
|
-
| `X-Mixr-Payment` | Widget | Widget payment proof JWT |
|
|
102
|
-
| `X-PAYMENT` | x402 | External agent payment via x402 protocol |
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
app.post('/api/generate', mixrpay({ priceUsd: 0.05 }), (req, res) => {
|
|
106
|
-
const { method } = req.mixrPayment!;
|
|
107
|
-
|
|
108
|
-
switch (method) {
|
|
109
|
-
case 'session':
|
|
110
|
-
console.log('Payment from Agent SDK');
|
|
111
|
-
break;
|
|
112
|
-
case 'widget':
|
|
113
|
-
console.log('Payment from Widget user');
|
|
114
|
-
break;
|
|
115
|
-
case 'x402':
|
|
116
|
-
console.log('Payment from external x402 agent');
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
res.json({ result: 'success' });
|
|
62
|
+
app.post('/api/generate', { preHandler: mixrpay({ priceUsd: 0.05 }) }, async (req) => {
|
|
63
|
+
return { result: 'success' };
|
|
121
64
|
});
|
|
122
65
|
```
|
|
123
66
|
|
|
124
|
-
##
|
|
125
|
-
|
|
126
|
-
### Session-Based Flow (Agent SDK / Widget)
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
Agent/User Your API MixrPay
|
|
130
|
-
│ │ │
|
|
131
|
-
│ 1. Request with │ │
|
|
132
|
-
│ X-Mixr-Session header │ │
|
|
133
|
-
├───────────────────────────▶│ │
|
|
134
|
-
│ │ 2. Validate session │
|
|
135
|
-
│ ├──────────────────────────▶│
|
|
136
|
-
│ │◀──────────────────────────┤
|
|
137
|
-
│ 3. Response │ │
|
|
138
|
-
│◀───────────────────────────┤ │
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### x402 Flow (External Agents)
|
|
142
|
-
|
|
143
|
-
```
|
|
144
|
-
Agent Your API Facilitator
|
|
145
|
-
│ │ │
|
|
146
|
-
│ 1. Request (no payment) │ │
|
|
147
|
-
├───────────────────────────▶│ │
|
|
148
|
-
│◀── 402 Payment Required ───┤ │
|
|
149
|
-
│ │ │
|
|
150
|
-
│ 2. Request with │ │
|
|
151
|
-
│ X-PAYMENT header │ │
|
|
152
|
-
├───────────────────────────▶│ │
|
|
153
|
-
│ │ 3. Verify & settle │
|
|
154
|
-
│ ├──────────────────────────▶│
|
|
155
|
-
│ │◀──────────────────────────┤
|
|
156
|
-
│ 4. Response │ │
|
|
157
|
-
│◀───────────────────────────┤ │
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## Configuration Options
|
|
161
|
-
|
|
162
|
-
### MixrPayOptions
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
interface MixrPayOptions {
|
|
166
|
-
/** Price in USD (e.g., 0.05 for 5 cents) */
|
|
167
|
-
priceUsd?: number;
|
|
168
|
-
|
|
169
|
-
/** Dynamic pricing function */
|
|
170
|
-
getPrice?: (req: Request) => number | Promise<number>;
|
|
171
|
-
|
|
172
|
-
/** Your public key (defaults to MIXRPAY_PUBLIC_KEY env var) */
|
|
173
|
-
publicKey?: string;
|
|
174
|
-
|
|
175
|
-
/** Your secret key (defaults to MIXRPAY_SECRET_KEY env var) */
|
|
176
|
-
secretKey?: string;
|
|
177
|
-
|
|
178
|
-
/** Wallet address for x402 (defaults to MIXRPAY_MERCHANT_ADDRESS env var) */
|
|
179
|
-
merchantAddress?: string;
|
|
180
|
-
|
|
181
|
-
/** x402 facilitator URL (default: https://x402.org/facilitator) */
|
|
182
|
-
facilitator?: string;
|
|
183
|
-
|
|
184
|
-
/** Description shown to payer */
|
|
185
|
-
description?: string;
|
|
186
|
-
|
|
187
|
-
/** Callback after successful payment */
|
|
188
|
-
onPayment?: (payment: MixrPayment) => void | Promise<void>;
|
|
189
|
-
|
|
190
|
-
/** Skip payment for certain requests */
|
|
191
|
-
skip?: (req: Request) => boolean | Promise<boolean>;
|
|
192
|
-
|
|
193
|
-
/** Test mode - accepts test payments */
|
|
194
|
-
testMode?: boolean;
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### Payment Result
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
interface MixrPayment {
|
|
202
|
-
/** Whether payment is valid */
|
|
203
|
-
valid: boolean;
|
|
204
|
-
|
|
205
|
-
/** Payment method used */
|
|
206
|
-
method: 'session' | 'widget' | 'x402';
|
|
207
|
-
|
|
208
|
-
/** Payer's wallet address */
|
|
209
|
-
payer: string;
|
|
210
|
-
|
|
211
|
-
/** Amount paid in USD */
|
|
212
|
-
amountUsd: number;
|
|
213
|
-
|
|
214
|
-
/** Session ID (for session-based payments) */
|
|
215
|
-
sessionId?: string;
|
|
216
|
-
|
|
217
|
-
/** Charge record ID */
|
|
218
|
-
chargeId?: string;
|
|
219
|
-
|
|
220
|
-
/** Settlement transaction hash (for x402) */
|
|
221
|
-
txHash?: string;
|
|
222
|
-
|
|
223
|
-
/** When payment was made */
|
|
224
|
-
timestamp: Date;
|
|
225
|
-
|
|
226
|
-
/** Error message if invalid */
|
|
227
|
-
error?: string;
|
|
228
|
-
|
|
229
|
-
/** Whether payment was pre-charged by the agent (session only) */
|
|
230
|
-
preCharged?: boolean;
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### Pre-Charged Sessions
|
|
235
|
-
|
|
236
|
-
When AI agents use the Agent SDK, they can pre-charge before calling your API by passing `X-Mixr-Charged: <amount>`. The middleware detects this and validates the session without double-charging:
|
|
237
|
-
|
|
238
|
-
```typescript
|
|
239
|
-
// Agent SDK calls your API with pre-charged session
|
|
240
|
-
// Headers: { 'X-Mixr-Session': 'sess_abc', 'X-Mixr-Charged': '0.05' }
|
|
241
|
-
|
|
242
|
-
app.post('/api/query', mixrpay({ priceUsd: 0.05 }), (req, res) => {
|
|
243
|
-
const { preCharged, amountUsd, payer } = req.mixrPayment!;
|
|
244
|
-
|
|
245
|
-
if (preCharged) {
|
|
246
|
-
// Agent pre-charged - session validated only, no additional charge made
|
|
247
|
-
console.log(`Pre-charged payment of $${amountUsd} from ${payer}`);
|
|
248
|
-
} else {
|
|
249
|
-
// Middleware charged the session
|
|
250
|
-
console.log(`Charged $${amountUsd} from ${payer}`);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
res.json({ result: 'success' });
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Advanced Usage
|
|
258
|
-
|
|
259
|
-
### Dynamic Pricing
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
app.post('/api/ai', mixrpay({
|
|
263
|
-
getPrice: async (req) => {
|
|
264
|
-
const { model, tokens } = req.body;
|
|
265
|
-
|
|
266
|
-
// Price based on model and usage
|
|
267
|
-
const rates = { 'gpt-4': 0.03, 'gpt-3.5': 0.002 };
|
|
268
|
-
const rate = rates[model] || 0.01;
|
|
269
|
-
|
|
270
|
-
return rate * (tokens / 1000);
|
|
271
|
-
}
|
|
272
|
-
}), handler);
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### Skip Payment for Certain Requests
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
app.post('/api/query', mixrpay({
|
|
279
|
-
priceUsd: 0.05,
|
|
280
|
-
skip: async (req) => {
|
|
281
|
-
// Free for authenticated premium users
|
|
282
|
-
const user = await getUser(req.headers.authorization);
|
|
283
|
-
return user?.isPremium || false;
|
|
284
|
-
}
|
|
285
|
-
}), handler);
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Payment Callbacks
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
app.post('/api/query', mixrpay({
|
|
292
|
-
priceUsd: 0.05,
|
|
293
|
-
onPayment: async (payment) => {
|
|
294
|
-
// Log to your analytics
|
|
295
|
-
await analytics.track('payment_received', {
|
|
296
|
-
payer: payment.payer,
|
|
297
|
-
amount: payment.amountUsd,
|
|
298
|
-
method: payment.method,
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// Store in database
|
|
302
|
-
await db.payments.create({
|
|
303
|
-
data: {
|
|
304
|
-
payer: payment.payer,
|
|
305
|
-
amount: payment.amountUsd,
|
|
306
|
-
chargeId: payment.chargeId,
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
}), handler);
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### Manual Verification
|
|
314
|
-
|
|
315
|
-
```typescript
|
|
316
|
-
import { verifyMixrPayment } from '@mixrpay/merchant-sdk';
|
|
67
|
+
## Widget
|
|
317
68
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
69
|
+
```html
|
|
70
|
+
<script
|
|
71
|
+
src="https://www.mixrpay.com/widget.js"
|
|
72
|
+
data-seller-public-key="pk_live_..."
|
|
73
|
+
data-user-token="{{ userToken }}">
|
|
74
|
+
</script>
|
|
324
75
|
|
|
325
|
-
|
|
326
|
-
console.log(`Valid payment from ${result.payer} via ${result.method}`);
|
|
327
|
-
}
|
|
76
|
+
<mixr-balance></mixr-balance>
|
|
328
77
|
```
|
|
329
78
|
|
|
330
|
-
|
|
79
|
+
Generate user tokens server-side using your HMAC secret. See [Widget docs](https://www.mixrpay.com/seller/widget).
|
|
331
80
|
|
|
332
|
-
|
|
81
|
+
## Webhooks
|
|
333
82
|
|
|
334
83
|
```typescript
|
|
335
84
|
import { verifySessionWebhook } from '@mixrpay/merchant-sdk';
|
|
336
85
|
|
|
337
86
|
app.post('/webhooks/mixrpay', (req, res) => {
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
// Verify signature using your webhook secret from the dashboard
|
|
342
|
-
if (!verifySessionWebhook(payload, signature, process.env.WEBHOOK_SECRET!)) {
|
|
87
|
+
const sig = req.headers['x-mixrpay-signature'] as string;
|
|
88
|
+
if (!verifySessionWebhook(JSON.stringify(req.body), sig, process.env.MIXRPAY_WEBHOOK_SECRET!)) {
|
|
343
89
|
return res.status(401).json({ error: 'Invalid signature' });
|
|
344
90
|
}
|
|
345
|
-
|
|
346
|
-
const event = req.body;
|
|
347
|
-
|
|
348
|
-
switch (event.event) {
|
|
349
|
-
case 'session.created':
|
|
350
|
-
// New session authorized
|
|
351
|
-
console.log(`Session created: ${event.session_id} from ${event.user_wallet}`);
|
|
352
|
-
console.log(`Spending limit: $${event.spending_limit_usd}`);
|
|
353
|
-
break;
|
|
354
|
-
|
|
355
|
-
case 'session.charged':
|
|
356
|
-
// Successful charge against a session
|
|
357
|
-
console.log(`Charged $${event.amount_usd} from ${event.user_wallet}`);
|
|
358
|
-
console.log(`Remaining: $${event.remaining_usd}`);
|
|
359
|
-
// Update your database, trigger fulfillment, etc.
|
|
360
|
-
break;
|
|
361
|
-
|
|
362
|
-
case 'session.revoked':
|
|
363
|
-
// User revoked their session
|
|
364
|
-
console.log(`Session revoked: ${event.session_id}`);
|
|
365
|
-
break;
|
|
366
|
-
|
|
367
|
-
case 'session.expired':
|
|
368
|
-
// Session expired
|
|
369
|
-
console.log(`Session expired: ${event.session_id}`);
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
91
|
res.json({ received: true });
|
|
374
92
|
});
|
|
375
93
|
```
|
|
376
94
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
## Testing
|
|
380
|
-
|
|
381
|
-
Enable test mode to accept test payments during development:
|
|
382
|
-
|
|
383
|
-
```typescript
|
|
384
|
-
app.post('/api/query', mixrpay({
|
|
385
|
-
priceUsd: 0.05,
|
|
386
|
-
testMode: process.env.NODE_ENV !== 'production',
|
|
387
|
-
}), handler);
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
## Environment Variables
|
|
391
|
-
|
|
392
|
-
| Variable | Description | Required |
|
|
393
|
-
|----------|-------------|----------|
|
|
394
|
-
| `MIXRPAY_PUBLIC_KEY` | Your merchant public key (pk_...) | Yes |
|
|
395
|
-
| `MIXRPAY_SECRET_KEY` | Your merchant secret key | Yes |
|
|
396
|
-
| `MIXRPAY_MERCHANT_ADDRESS` | Wallet address for x402 payments | For x402 |
|
|
397
|
-
|
|
398
|
-
## Supported Chains
|
|
399
|
-
|
|
400
|
-
| Chain | Chain ID | USDC Contract |
|
|
401
|
-
|-------|----------|---------------|
|
|
402
|
-
| Base Mainnet | 8453 | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
|
|
403
|
-
| Base Sepolia | 84532 | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
|
|
404
|
-
|
|
405
|
-
## Error Handling
|
|
406
|
-
|
|
407
|
-
The middleware returns appropriate HTTP status codes:
|
|
408
|
-
|
|
409
|
-
- `402 Payment Required` - No payment or invalid payment
|
|
410
|
-
- `403 Forbidden` - Session limit exceeded or revoked
|
|
411
|
-
- `500 Internal Server Error` - Configuration issues
|
|
412
|
-
|
|
413
|
-
Error responses include details:
|
|
414
|
-
|
|
415
|
-
```json
|
|
416
|
-
{
|
|
417
|
-
"error": "payment_required",
|
|
418
|
-
"message": "No valid payment provided",
|
|
419
|
-
"paymentInfo": {
|
|
420
|
-
"priceUsd": 0.05,
|
|
421
|
-
"recipient": "0x...",
|
|
422
|
-
"acceptedMethods": ["X-Mixr-Session", "X-Mixr-Payment", "X-PAYMENT"]
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
## TypeScript Support
|
|
428
|
-
|
|
429
|
-
Full TypeScript support with type definitions included.
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
import type { MixrPayOptions, MixrPayment } from '@mixrpay/merchant-sdk';
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
### Widget Custom Elements (React/JSX)
|
|
436
|
-
|
|
437
|
-
If you're using the MixrPay widget with TypeScript and React, import the type declarations:
|
|
438
|
-
|
|
439
|
-
```typescript
|
|
440
|
-
// In your app's entry file or a .d.ts file
|
|
441
|
-
import '@mixrpay/merchant-sdk/widget-elements';
|
|
442
|
-
|
|
443
|
-
// Now these work without TypeScript errors:
|
|
444
|
-
<mixr-balance data-theme="dark" />
|
|
445
|
-
<mixr-wallet />
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
## Migration from x402-Only
|
|
449
|
-
|
|
450
|
-
If you were using the old x402-only middleware:
|
|
451
|
-
|
|
452
|
-
```typescript
|
|
453
|
-
// Before (x402 only)
|
|
454
|
-
import { x402 } from '@mixrpay/merchant-sdk/express';
|
|
455
|
-
app.post('/api/query', x402({ price: 0.05 }), handler);
|
|
456
|
-
|
|
457
|
-
// After (unified - backwards compatible)
|
|
458
|
-
import { mixrpay } from '@mixrpay/merchant-sdk/express';
|
|
459
|
-
app.post('/api/query', mixrpay({ priceUsd: 0.05 }), handler);
|
|
460
|
-
```
|
|
95
|
+
## Documentation
|
|
461
96
|
|
|
462
|
-
|
|
97
|
+
[mixrpay.com/seller/docs](https://www.mixrpay.com/seller/docs)
|
|
463
98
|
|
|
464
99
|
## License
|
|
465
100
|
|
package/dist/index.d.mts
CHANGED
|
@@ -77,6 +77,68 @@ interface SessionGrant {
|
|
|
77
77
|
*/
|
|
78
78
|
declare function verifySessionWebhook(payload: string, signature: string, secret: string): boolean;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* MixrPay Merchant SDK - Utilities
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get the MixrPay widget script URL.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```html
|
|
89
|
+
* <script src="${getWidgetUrl()}"
|
|
90
|
+
* data-seller-public-key="pk_live_..."
|
|
91
|
+
* data-user-token="..."></script>
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function getWidgetUrl(): string;
|
|
95
|
+
/**
|
|
96
|
+
* MixrPay API base URL
|
|
97
|
+
*/
|
|
98
|
+
declare const MIXRPAY_API_URL = "https://www.mixrpay.com";
|
|
99
|
+
/**
|
|
100
|
+
* Widget script URL (for convenience)
|
|
101
|
+
*/
|
|
102
|
+
declare const WIDGET_SCRIPT_URL = "https://www.mixrpay.com/widget.js";
|
|
103
|
+
/**
|
|
104
|
+
* Convert USD dollars to USDC minor units (6 decimals)
|
|
105
|
+
*/
|
|
106
|
+
declare function usdToMinor(usd: number): bigint;
|
|
107
|
+
/**
|
|
108
|
+
* Convert USDC minor units to USD dollars
|
|
109
|
+
*/
|
|
110
|
+
declare function minorToUsd(minor: bigint): number;
|
|
111
|
+
interface EnvValidationResult {
|
|
112
|
+
valid: boolean;
|
|
113
|
+
errors: string[];
|
|
114
|
+
warnings: string[];
|
|
115
|
+
config: {
|
|
116
|
+
publicKey: string | null;
|
|
117
|
+
secretKey: string | null;
|
|
118
|
+
hmacSecret: string | null;
|
|
119
|
+
webhookSecret: string | null;
|
|
120
|
+
merchantAddress: string | null;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate MixrPay environment variables and provide helpful feedback.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* import { validateEnv } from '@mixrpay/merchant-sdk';
|
|
129
|
+
*
|
|
130
|
+
* const result = validateEnv();
|
|
131
|
+
* if (!result.valid) {
|
|
132
|
+
* console.error('MixrPay configuration errors:', result.errors);
|
|
133
|
+
* }
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function validateEnv(env?: Record<string, string | undefined>): EnvValidationResult;
|
|
137
|
+
/**
|
|
138
|
+
* Log environment validation results to console with formatting.
|
|
139
|
+
*/
|
|
140
|
+
declare function logEnvValidation(result?: EnvValidationResult): void;
|
|
141
|
+
|
|
80
142
|
/**
|
|
81
143
|
* MixrPay Widget Custom Element Type Declarations
|
|
82
144
|
*
|
|
@@ -149,6 +211,43 @@ interface MixrState {
|
|
|
149
211
|
// Global API Types
|
|
150
212
|
// =============================================================================
|
|
151
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Session state object returned by window.Mixr.getSessionState()
|
|
216
|
+
*/
|
|
217
|
+
interface MixrSessionState {
|
|
218
|
+
/** Whether user has an active session */
|
|
219
|
+
hasSession: boolean;
|
|
220
|
+
/** Current session ID */
|
|
221
|
+
sessionId: string | null;
|
|
222
|
+
/** Remaining spending limit in USD */
|
|
223
|
+
remainingUsd: number;
|
|
224
|
+
/** Total spending limit in USD */
|
|
225
|
+
spendingLimitUsd: number;
|
|
226
|
+
/** Session expiration date */
|
|
227
|
+
expiresAt: Date | null;
|
|
228
|
+
/** Session status */
|
|
229
|
+
status: 'active' | 'expired' | 'revoked' | null;
|
|
230
|
+
/** Session type */
|
|
231
|
+
type: 'session_key' | 'authorization' | null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Diagnostic result from Mixr.diagnose()
|
|
236
|
+
*/
|
|
237
|
+
interface MixrDiagnosticResult {
|
|
238
|
+
config: {
|
|
239
|
+
hasPublicKey: boolean;
|
|
240
|
+
hasUserToken: boolean;
|
|
241
|
+
hasWidgetToken: boolean;
|
|
242
|
+
mode: 'wallet_auth' | 'domain_verified' | 'hmac';
|
|
243
|
+
};
|
|
244
|
+
state: MixrState;
|
|
245
|
+
session: MixrSessionState;
|
|
246
|
+
issues: string[];
|
|
247
|
+
warnings: string[];
|
|
248
|
+
isLocalhost: boolean;
|
|
249
|
+
}
|
|
250
|
+
|
|
152
251
|
/**
|
|
153
252
|
* MixrPay global API available on window.Mixr
|
|
154
253
|
*/
|
|
@@ -165,6 +264,12 @@ interface MixrAPI {
|
|
|
165
264
|
/** Get current widget state */
|
|
166
265
|
getState(): MixrState;
|
|
167
266
|
|
|
267
|
+
/** Get current session state */
|
|
268
|
+
getSessionState(): MixrSessionState;
|
|
269
|
+
|
|
270
|
+
/** Fetch fresh session state from server */
|
|
271
|
+
getSession(): Promise<MixrSessionState>;
|
|
272
|
+
|
|
168
273
|
/** Refresh user balance and state */
|
|
169
274
|
refresh(): Promise<void>;
|
|
170
275
|
|
|
@@ -175,6 +280,69 @@ interface MixrAPI {
|
|
|
175
280
|
* @param element - The element that triggered the charge (for UI feedback)
|
|
176
281
|
*/
|
|
177
282
|
charge(feature: string, priceUsd: string, element: HTMLElement): Promise<void>;
|
|
283
|
+
|
|
284
|
+
/** Check if user is authenticated */
|
|
285
|
+
isAuthenticated(): boolean;
|
|
286
|
+
|
|
287
|
+
/** Get user's wallet address */
|
|
288
|
+
getWalletAddress(): string | null;
|
|
289
|
+
|
|
290
|
+
/** Check if user can afford a given amount */
|
|
291
|
+
canAfford(amountUsd: number): boolean;
|
|
292
|
+
|
|
293
|
+
/** Check if widget is ready for transactions */
|
|
294
|
+
isReady(minBalance?: number): boolean;
|
|
295
|
+
|
|
296
|
+
/** Get detailed readiness status */
|
|
297
|
+
getReadinessStatus(minBalance?: number): {
|
|
298
|
+
ready: boolean;
|
|
299
|
+
issues: string[];
|
|
300
|
+
balanceUsd: number;
|
|
301
|
+
sessionId: string | null;
|
|
302
|
+
sessionRemaining: number;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/** Trigger wallet connection (for wallet-auth mode) */
|
|
306
|
+
connect(): void;
|
|
307
|
+
|
|
308
|
+
/** Disconnect and clear local session */
|
|
309
|
+
disconnect(): void;
|
|
310
|
+
|
|
311
|
+
/** Prompt user to authorize a spending session */
|
|
312
|
+
authorizeSession(spendingLimitUsd?: number, durationDays?: number): Promise<boolean>;
|
|
313
|
+
|
|
314
|
+
/** Check if wallet is non-custodial */
|
|
315
|
+
isNonCustodial(): boolean;
|
|
316
|
+
|
|
317
|
+
/** Get current theme */
|
|
318
|
+
getTheme(): 'dark' | 'light';
|
|
319
|
+
|
|
320
|
+
/** Set theme */
|
|
321
|
+
setTheme(theme: 'dark' | 'light' | 'auto'): void;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Configure widget callbacks
|
|
325
|
+
*/
|
|
326
|
+
setConfig(config: {
|
|
327
|
+
onSessionChange?: (session: MixrSessionState) => void;
|
|
328
|
+
onStateChange?: (state: MixrState) => void;
|
|
329
|
+
defaultSessionLimit?: number;
|
|
330
|
+
defaultSessionDuration?: number;
|
|
331
|
+
}): void;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Diagnostic tool for debugging widget issues.
|
|
335
|
+
* Call Mixr.diagnose() in browser console to see widget status.
|
|
336
|
+
*/
|
|
337
|
+
diagnose(): MixrDiagnosticResult;
|
|
338
|
+
|
|
339
|
+
/** Enable debug mode for verbose logging */
|
|
340
|
+
enableDebug(): void;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Make an authenticated fetch request with MixrPay headers
|
|
344
|
+
*/
|
|
345
|
+
fetch(url: string, options?: RequestInit & { autoPrompt?: boolean }): Promise<Response>;
|
|
178
346
|
}
|
|
179
347
|
|
|
180
348
|
// =============================================================================
|
|
@@ -286,4 +454,4 @@ declare global {
|
|
|
286
454
|
}
|
|
287
455
|
}
|
|
288
456
|
|
|
289
|
-
export { PaymentReceipt, type SessionGrant, verifyPaymentReceipt, verifySessionWebhook };
|
|
457
|
+
export { type EnvValidationResult, MIXRPAY_API_URL, PaymentReceipt, type SessionGrant, WIDGET_SCRIPT_URL, getWidgetUrl, logEnvValidation, minorToUsd, usdToMinor, validateEnv, verifyPaymentReceipt, verifySessionWebhook };
|