@weave-sdk/widget 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +492 -0
  2. package/package.json +3 -2
package/README.md ADDED
@@ -0,0 +1,492 @@
1
+ # @weave-sdk/widget
2
+
3
+ Accept any currency, settle anywhere. Drop-in payment widget that routes crypto across 30+ chains and settles in NGN or your preferred asset.
4
+
5
+ ## Features
6
+
7
+ - **Universal Payment Orchestration** — Customers pay in 30+ chains or fiat; you receive NGN to bank or crypto to wallet
8
+ - **Automatic Routing** — Multi-hop settlement via ChainRails, NEAR Intents, and Paycrest
9
+ - **Multiple Payment Methods** — Crypto wallets (self/external), bank transfers, stablecoin swaps
10
+ - **Customizable** — Organic/minimal themes, accent colors, corner radius — zero-code styling
11
+ - **Real-Time Exchange Rates** — Live pricing on every quote
12
+ - **Webhook Signatures** — HMAC-SHA256 verified async notifications
13
+ - **Framework Support** — React, Next.js, vanilla HTML/JS
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @weave-sdk/widget
19
+ # or
20
+ pnpm add @weave-sdk/widget
21
+ # or
22
+ yarn add @weave-sdk/widget
23
+ ```
24
+
25
+ The widget is distributed as a single package with built-in styles.
26
+
27
+ ## Quick Start
28
+
29
+ ### React
30
+
31
+ ```tsx
32
+ import { WeaveCheckout } from '@weave-sdk/widget';
33
+
34
+ export default function CheckoutPage() {
35
+ return (
36
+ <WeaveCheckout
37
+ apiKey="pk_live_your_api_key"
38
+ theme="organic"
39
+ accentColor="#3D6B50"
40
+ borderRadius={16}
41
+ merchant={{
42
+ name: 'Acme Store',
43
+ amount: 5000,
44
+ currency: 'NGN',
45
+ description: 'Order #1042',
46
+ }}
47
+ onSuccess={(txn) => console.log('Paid', txn.orderId)}
48
+ onError={(err) => console.error(err.message)}
49
+ onClose={() => console.log('closed')}
50
+ />
51
+ );
52
+ }
53
+ ```
54
+
55
+ ### Next.js (App Router)
56
+
57
+ ```tsx
58
+ 'use client';
59
+ // The widget uses window + wallet APIs — must be client-only.
60
+ import dynamic from 'next/dynamic';
61
+
62
+ const WeaveCheckout = dynamic(
63
+ () => import('@weave-sdk/widget').then(m => m.WeaveCheckout),
64
+ { ssr: false }
65
+ );
66
+
67
+ export default function CheckoutPage() {
68
+ return (
69
+ <WeaveCheckout
70
+ apiKey="pk_live_..."
71
+ theme="organic"
72
+ accentColor="#3D6B50"
73
+ borderRadius={16}
74
+ merchant={{ name: 'Acme Store', amount: 5000, currency: 'NGN' }}
75
+ onSuccess={(txn) => console.log('paid', txn.orderId)}
76
+ onError={(err) => console.error(err.message)}
77
+ onClose={() => router.back()}
78
+ />
79
+ );
80
+ }
81
+ ```
82
+
83
+ ### HTML / Vanilla JavaScript
84
+
85
+ ```html
86
+ <div id="weave-checkout"></div>
87
+
88
+ <script src="https://unpkg.com/@weave-sdk/widget/dist/umd.js"></script>
89
+ <script>
90
+ Weave.mount('#weave-checkout', {
91
+ apiKey: 'pk_live_...',
92
+ theme: 'organic',
93
+ accentColor: '#3D6B50',
94
+ borderRadius: 16,
95
+ merchant: {
96
+ name: 'Acme Store',
97
+ amount: 5000,
98
+ currency: 'NGN',
99
+ description: 'Order #1042',
100
+ },
101
+ onSuccess: (txn) => console.log('Paid', txn.orderId),
102
+ onError: (err) => console.error(err.message),
103
+ onClose: () => console.log('closed'),
104
+ });
105
+ </script>
106
+ ```
107
+
108
+ ## Widget Props
109
+
110
+ ### Required
111
+
112
+ #### `merchant`
113
+ Payment context object.
114
+
115
+ ```typescript
116
+ merchant: {
117
+ name: string; // Business/store name
118
+ amount: number; // Payment amount
119
+ currency: string; // Settlement currency (e.g. 'NGN')
120
+ description?: string; // Order description
121
+ amountIn?: 'source' | 'dest'; // 'source' = exact deposit, 'dest' = exact payout
122
+ sourceAssetKey?: string; // Lock to asset, e.g. 'crypto:ETHEREUM:USDC'
123
+ destAssetKey?: string; // Lock payout to asset, e.g. 'fiat:NGN'
124
+ destInstrument?: any; // Explicit payout instrument
125
+ }
126
+ ```
127
+
128
+ ### Optional
129
+
130
+ #### `apiKey`
131
+ Publishable API key (`pk_live_...` or `pk_test_...`). Falls back to `window.__WEAVE_API_KEY__` or `VITE_WEAVE_PUBLIC_KEY` env var.
132
+
133
+ Type: `string`
134
+
135
+ #### `theme`
136
+ Visual theme. Default: `'organic'`
137
+
138
+ - `'organic'` — Soft curves, warm palette
139
+ - `'minimal'` — Flat, minimal
140
+
141
+ Type: `'organic' | 'minimal'`
142
+
143
+ #### `accentColor`
144
+ Brand accent color. Can be a named color or hex code.
145
+
146
+ Type: `string` — e.g. `'#3D6B50'` or `'forest'` or `'tan'`
147
+
148
+ #### `borderRadius`
149
+ Corner radius of the widget frame in pixels. Default: `16`
150
+
151
+ Type: `number`
152
+
153
+ #### `userAddress`
154
+ Pre-fill a customer wallet address (for crypto sources).
155
+
156
+ Type: `string`
157
+
158
+ #### `apiBase`
159
+ Override the API base URL (for proxying or local testing).
160
+
161
+ Type: `string`
162
+
163
+ #### `onSuccess`
164
+ Callback when the order reaches `completed` status.
165
+
166
+ Type: `(txn: { orderId: string; status: string; }) => void`
167
+
168
+ #### `onError`
169
+ Callback on unrecoverable errors.
170
+
171
+ Type: `(err: Error) => void`
172
+
173
+ #### `onClose`
174
+ Callback when the user dismisses without completing.
175
+
176
+ Type: `() => void`
177
+
178
+ ## Settlement Corridors
179
+
180
+ Weave automatically routes through the optimal provider based on source and destination assets.
181
+
182
+ | Provider | Route | Flow | Settlement Time |
183
+ |----------|-------|------|------------------|
184
+ | **Paystack** | `fiat:NGN → fiat:NGN` | external | T+1 business day (bank transfer) |
185
+ | **Paycrest** | `crypto:BASE:USDC ↔ fiat:NGN` | automatic | 30s – 2min |
186
+ | **NEAR Intents** | 30+ chains `→ crypto:BASE:USDC` | external | 30 – 90s |
187
+ | **ChainRails** | EVM chains `→ crypto:BASE:USDC` | self | ~60s |
188
+
189
+ ### Payment Flows
190
+
191
+ - **`external`** — Deposit address generated. Customer sends from any wallet.
192
+ - **`self`** — Connected EVM wallet flow. Customer signs transaction directly.
193
+ - **`automatic`** — Provider-determined (usually for terminal-stage hops like crypto → fiat).
194
+
195
+ ## Styling
196
+
197
+ Styles are automatically included when you import the component. Override with CSS:
198
+
199
+ ```css
200
+ :root {
201
+ --weave-accent: #3D6B50;
202
+ --weave-radius: 16px;
203
+ --weave-font: 'Inter', sans-serif;
204
+ --weave-bg: #ffffff;
205
+ --weave-text: #000000;
206
+ }
207
+ ```
208
+
209
+ ## Testing
210
+
211
+ Use sandbox mode with `pk_test_...` keys:
212
+
213
+ ```tsx
214
+ <WeaveCheckout
215
+ apiKey="pk_test_your_test_key"
216
+ merchant={{ name: 'Test Store', amount: 100, currency: 'NGN' }}
217
+ />
218
+ ```
219
+
220
+ **Sandbox behavior:**
221
+ - Orders auto-complete instantly
222
+ - No real provider calls
223
+ - Webhooks suppressed
224
+ - Excluded from revenue metrics
225
+
226
+ ## Supported Assets
227
+
228
+ ### Source Assets (What Customers Pay With)
229
+
230
+ | Asset | Chains | Min |
231
+ |-------|--------|-----|
232
+ | SOL | Solana | 0.01 |
233
+ | ETH | Ethereum, Arbitrum, Base | 0.001 |
234
+ | USDC | Solana, Ethereum, Arbitrum, Base | 1 |
235
+ | USDT | Ethereum, Arbitrum, Base | 1 |
236
+ | NGN (fiat) | Nigeria (bank) | 100 |
237
+
238
+ ### Destination Assets (What You Receive)
239
+
240
+ | Asset | Type | Min Settlement |
241
+ |-------|------|-----------------|
242
+ | NGN | Fiat (bank) | 1,000 |
243
+ | USDC | Crypto (Base) | 1 |
244
+ | SOL | Crypto (Solana) | 0.01 |
245
+ | ETH | Crypto (Ethereum) | 0.001 |
246
+
247
+ ## API Keys
248
+
249
+ Every request must include an `x-api-key` header.
250
+
251
+ ### Publishable Keys (`pk_live_…` or `pk_test_…`)
252
+
253
+ Safe for browser/client code. Used in the widget.
254
+
255
+ - Create orders
256
+ - Fetch quotes
257
+ - Never grants account read access
258
+
259
+ ### Secret Keys (`sk_live_…`)
260
+
261
+ Server-side only. Never expose in client code, logs, or version control.
262
+
263
+ ```bash
264
+ # Example: server-to-server API call
265
+ curl https://api.paywithweave.com/api/v1/orders/:id \
266
+ -H "x-public-key: pk_live_..." \
267
+ -H "x-secret-key: sk_live_..."
268
+ ```
269
+
270
+ ## Webhooks
271
+
272
+ Configure your webhook endpoint in **Settings → Developer → Webhooks**.
273
+
274
+ ### Events
275
+
276
+ - `order.completed` — All route steps settled. Funds delivered to your payout destination.
277
+ - `order.failed` — Payment failed, expired, or refunded. No funds moved.
278
+
279
+ ### Payload
280
+
281
+ ```json
282
+ {
283
+ "event": "order.completed",
284
+ "data": {
285
+ "id": "clxq8a4...",
286
+ "reference": "your-internal-id",
287
+ "status": "completed",
288
+ "sourceAssetKey": "crypto:ETHEREUM:USDC",
289
+ "destAssetKey": "fiat:NGN",
290
+ "sourceAmount": 50.38,
291
+ "destAmount": 74250,
292
+ "createdAt": "2026-05-01T10:00:00.000Z"
293
+ }
294
+ }
295
+ ```
296
+
297
+ ### Signature Verification
298
+
299
+ Verify the `X-Weave-Signature` header (HMAC-SHA256 over `{timestamp}.{rawBody}`).
300
+
301
+ ```typescript
302
+ import crypto from 'crypto';
303
+
304
+ const signature = req.headers['x-weave-signature'];
305
+ const timestamp = req.headers['x-weave-timestamp'];
306
+ const sig = signature.startsWith('sha256=') ? signature.slice(7) : signature;
307
+
308
+ const expected = crypto
309
+ .createHmac('sha256', process.env.WEAVE_WEBHOOK_SECRET)
310
+ .update(`${timestamp}.${req.rawBody.toString()}`)
311
+ .digest('hex');
312
+
313
+ if (!crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'))) {
314
+ return res.status(401).send('Invalid signature');
315
+ }
316
+
317
+ // Process webhook
318
+ const { event, data } = JSON.parse(req.body);
319
+ if (event === 'order.completed') {
320
+ await fulfillOrder(data.id); // dedupe on data.id
321
+ }
322
+
323
+ res.json({ received: true });
324
+ ```
325
+
326
+ **Best practices:**
327
+ 1. Always verify signatures before processing
328
+ 2. Hash the **raw body bytes** (not re-stringified JSON)
329
+ 3. Strip the `sha256=` prefix before comparing
330
+ 4. Reject deliveries older than ~5 minutes (check `X-Weave-Timestamp`)
331
+ 5. Dedupe on `data.id` — handle duplicate webhooks gracefully
332
+
333
+ ## API Reference
334
+
335
+ ### `GET /quotes`
336
+
337
+ Get a live exchange rate and fee breakdown for any asset pair.
338
+
339
+ ```bash
340
+ curl "https://api.paywithweave.com/api/v1/quotes?from=crypto:ETHEREUM:USDC&to=fiat:NGN&amount=50" \
341
+ -H "x-api-key: pk_live_..."
342
+ ```
343
+
344
+ **Query Parameters:**
345
+ - `from` (required) — Source asset key
346
+ - `to` (required) — Destination asset key
347
+ - `amount` (required) — Amount in source units
348
+ - `amountIn` (optional) — `'source'` or `'dest'`. Default: `'source'`
349
+
350
+ ### `POST /orders`
351
+
352
+ Create a payment order.
353
+
354
+ ```bash
355
+ curl https://api.paywithweave.com/api/v1/orders \
356
+ -X POST -H "x-api-key: pk_live_..." \
357
+ -H "Content-Type: application/json" \
358
+ -d '{
359
+ "source": {
360
+ "inline": {
361
+ "kind": "crypto_wallet",
362
+ "assetKey": "crypto:ETHEREUM:USDC",
363
+ "walletAddress": "0xCustomer..."
364
+ }
365
+ },
366
+ "amount": 50,
367
+ "flow": "external",
368
+ "refundAddress": "0xCustomer..."
369
+ }'
370
+ ```
371
+
372
+ **Body Fields:**
373
+ - `source.inline.kind` (required) — `'crypto_wallet'` or `'bank_account'`
374
+ - `source.inline.assetKey` (required) — Source asset
375
+ - `source.inline.walletAddress` (optional) — Wallet address (for crypto)
376
+ - `amount` (required) — Payment amount
377
+ - `amountIn` (optional) — `'source'` or `'dest'`
378
+ - `flow` (optional) — `'external'` or `'self'`
379
+ - `refundAddress` (optional) — Refund wallet
380
+ - `reference` (optional) — Your unique ID (for idempotency)
381
+ - `dest` (optional) — Override payout destination
382
+
383
+ ### `GET /orders/:id`
384
+
385
+ Fetch a single order. Triggers a live sync from the active provider.
386
+
387
+ ```bash
388
+ curl https://api.paywithweave.com/api/v1/orders/ord_abc123 \
389
+ -H "x-api-key: pk_live_..."
390
+ ```
391
+
392
+ ### `GET /orders`
393
+
394
+ List your last 50 orders (newest first).
395
+
396
+ ```bash
397
+ curl https://api.paywithweave.com/api/v1/orders \
398
+ -H "x-api-key: pk_live_..."
399
+ ```
400
+
401
+ ### `GET /institutions`
402
+
403
+ List supported banks for a currency (for onramp flows).
404
+
405
+ ```bash
406
+ curl "https://api.paywithweave.com/api/v1/institutions?currency=NGN" \
407
+ -H "x-api-key: pk_live_..."
408
+ ```
409
+
410
+ ## Order Statuses
411
+
412
+ - **`awaiting_deposit`** — Created. Waiting for customer to send funds.
413
+ - **`processing`** — Deposit detected. Bridge/settlement in progress.
414
+ - **`completed`** — Funds delivered to your payout destination.
415
+ - **`failed`** — Payment failed or expired. No funds moved.
416
+ - **`expired`** — No deposit received within the session window.
417
+
418
+ ## Troubleshooting
419
+
420
+ ### Widget won't load
421
+
422
+ - Verify your API key is valid
423
+ - Check that CORS is configured for your domain
424
+ - Ensure JavaScript is enabled
425
+ - Check browser console (`F12`) for errors
426
+
427
+ ### Payment fails
428
+
429
+ - Confirm destination address is valid
430
+ - Verify merchant currency is supported
431
+ - Check customer has sufficient balance
432
+ - Try on a different network
433
+
434
+ ### INSUFFICIENT_BALANCE
435
+
436
+ - Account for network fees
437
+ - Verify balance is on the correct network
438
+ - Confirm customer selected the correct wallet
439
+
440
+ ### Network errors
441
+
442
+ - Check internet connection
443
+ - Verify destination network is not congested
444
+ - Wait and retry
445
+ - Check [Status](https://status.paywithweave.com) for incidents
446
+
447
+ ### Webhook not received
448
+
449
+ - Verify webhook URL in Settings
450
+ - Confirm server is accessible from the internet
451
+ - Check firewall allows inbound HTTPS
452
+ - View webhook logs in Settings → Developer
453
+
454
+ ## Browser Support
455
+
456
+ - Chrome 90+
457
+ - Firefox 88+
458
+ - Safari 14+
459
+ - Edge 90+
460
+
461
+ Required APIs:
462
+ - Fetch
463
+ - LocalStorage
464
+ - postMessage (iframe)
465
+ - Web Crypto API
466
+
467
+ ## TypeScript Support
468
+
469
+ Full type definitions included:
470
+
471
+ ```tsx
472
+ import { WeaveCheckout } from '@weave-sdk/widget';
473
+ import type { Transaction, MerchantConfig } from '@weave-sdk/widget';
474
+ ```
475
+
476
+ ## Security
477
+
478
+ - All communication over HTTPS
479
+ - Webhook signatures via HMAC-SHA256
480
+ - API keys scoped by context (publishable vs. secret)
481
+ - Sandbox traffic isolated from live
482
+ - No credit card processing
483
+ - Provider webhooks verified before state mutation
484
+
485
+ ## License
486
+
487
+ Proprietary. All rights reserved.
488
+
489
+ ## Support
490
+
491
+ - **Email:** admin@dewdroplabs.com
492
+ - **Docs:** https://app.paywithweave.com/docs
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@weave-sdk/widget",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "The official Weave payment widget for React and plain HTML.",
5
5
  "main": "./dist/index.umd.js",
6
6
  "module": "./src/index.tsx",
7
7
  "types": "./src/index.tsx",
8
8
  "files": [
9
- "dist"
9
+ "dist",
10
+ "README.md"
10
11
  ],
11
12
  "exports": {
12
13
  ".": {