@voyage_ai/v402-web-ts 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1 +1,639 @@
1
- # v402-web-ts
1
+ # @voyage_ai/v402-web-ts
2
+
3
+ Frontend browser SDK for quick integration with v402pay platform, supporting payment functionality on Solana (SVM) and Ethereum (EVM) chains.
4
+
5
+ ## 📖 What is v402pay?
6
+
7
+ v402pay is a decentralized payment platform that helps developers quickly integrate Web3 payment features. After a successful payment, the platform automatically calls your configured callback interface to complete the delivery process.
8
+
9
+ ### Payment Flow
10
+
11
+ v402pay uses a TCC-like two-phase commit pattern to ensure charges only occur after business logic succeeds:
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ Start[User requests content] --> Check{Has Payment<br/>Info?}
16
+ Check -->|No| Return402["x402: Return 402<br/>Payment Required"]
17
+ Return402 --> SDK[SDK initiates<br/>payment]
18
+ SDK --> Wallet[User connects<br/>wallet]
19
+ Wallet --> Sign[User signs<br/>offline]
20
+ Sign --> Request2[Second request<br/>with signature]
21
+
22
+ Check -->|Yes| Request2
23
+ Request2 --> Verify["Phase 1: Verify<br/>Check payment"]
24
+ Verify --> VerifyCheck{Valid?}
25
+ VerifyCheck -->|Invalid| Return402
26
+ VerifyCheck -->|Valid| Execute["Phase 2: Execute<br/>Pass to business"]
27
+
28
+ Execute --> Business[Business logic<br/>Query & generate]
29
+ Business --> Response["Phase 3: Check<br/>Validate status"]
30
+ Response --> StatusCheck{Status OK?}
31
+
32
+ StatusCheck -->|Failed| NoSettle[NO charge<br/>Return error]
33
+ NoSettle --> End1[User sees error]
34
+
35
+ StatusCheck -->|Success| Settle["Phase 4: Settle<br/>Broadcast tx"]
36
+ Settle --> Chain[Blockchain<br/>confirmation]
37
+ Chain --> Record[Record txHash]
38
+ Record --> Display[User sees<br/>content & tx]
39
+
40
+ style Start fill:#e3f2fd
41
+ style Verify fill:#e1f5ff
42
+ style Execute fill:#e8f5e9
43
+ style Response fill:#fff4e1
44
+ style Settle fill:#fce4ec
45
+ style VerifyCheck fill:#f5f5f5
46
+ style StatusCheck fill:#f5f5f5
47
+ style NoSettle fill:#ffcdd2
48
+ style Display fill:#c8e6c9
49
+ ```
50
+
51
+ **Key Features:**
52
+
53
+ 1. **Two-Phase Commit**: Verify payment first, execute business logic, then settle based on business result
54
+ 2. **Business First**: No charge if business logic fails, avoiding charge-but-no-delivery scenarios
55
+ 3. **Offline Signing**: User signs transaction offline; only broadcasts on-chain after business success
56
+ 4. **Atomicity**: Either both business and payment succeed, or neither does
57
+
58
+ ### Delivery Modes
59
+
60
+ #### Current: Immediate Delivery ⚡
61
+
62
+ The current implementation uses **immediate delivery** mode:
63
+
64
+ - **When it happens**: Business callback is triggered immediately after payment verification (Phase 2)
65
+ - **Settlement timing**: On-chain settlement happens after business logic completes
66
+ - **Best for**:
67
+ - Digital content delivery (articles, videos, API access)
68
+ - Services without inventory management
69
+ - Use cases where settlement failure has minimal platform impact
70
+ - **Benefits**:
71
+ - ✅ Fast user experience
72
+ - ✅ Lower latency
73
+ - ✅ User safety guaranteed (no charge if business fails)
74
+
75
+ **Trade-off**: If settlement fails after business execution, the platform bears minor risk as content was already delivered.
76
+
77
+ ##### Sequence Diagram
78
+
79
+ ```mermaid
80
+ sequenceDiagram
81
+ participant User
82
+ participant SDK as v402pay platform
83
+ participant x402 as v402(Provided by x402)
84
+ participant Business as Your Business
85
+ participant Chain as Blockchain
86
+
87
+ Note over User,Business: First Request - No Payment Info
88
+ User->>Business: 1. Request content (no payment)
89
+ Business->>x402: Check payment
90
+ x402->>x402: No payment found
91
+ x402-->>User: 402 Payment Required<br/>(amount, address, params)
92
+
93
+ Note over User,SDK: User Payment Flow
94
+ User->>SDK: 2. Initiate payment
95
+ SDK->>User: Connect wallet (Phantom/MetaMask)
96
+ User->>SDK: 3. Sign transaction (offline)
97
+ Note right of SDK: Signature created,<br/>not on-chain yet
98
+
99
+ Note over User,Business: Second Request - With Payment Signature
100
+ User->>Business: 4. Request with payment signature
101
+ Business->>x402: Verify payment
102
+
103
+ rect rgb(240, 248, 255)
104
+ Note right of x402: Phase 1: Verify
105
+ x402->>x402: Check signature validity
106
+ x402->>x402: Check amount & address
107
+ x402->>x402: ✅ Verification passed
108
+ end
109
+
110
+ rect rgb(240, 255, 240)
111
+ Note right of x402: Phase 2: Execute
112
+ x402->>Business: Pass through request
113
+ Business->>Business: 5. Query database
114
+ Business->>Business: Generate content
115
+ end
116
+
117
+ rect rgb(255, 250, 240)
118
+ Note right of x402: Phase 3: Check Response
119
+ Business-->>x402: 200 OK + business data
120
+ x402->>x402: Status < 400, proceed
121
+ end
122
+
123
+ rect rgb(255, 240, 245)
124
+ Note right of x402: Phase 4: Settle
125
+ x402->>Chain: 6. Broadcast signed transaction
126
+ Chain->>Chain: Process & confirm transaction
127
+ Chain-->>x402: Transaction hash + confirmation
128
+ x402->>x402: 7. Record to database<br/>(txHash, status)
129
+ end
130
+
131
+ x402-->>User: 200 OK + business data<br/>+ X-PAYMENT-RESPONSE
132
+ User->>User: 8. Display content & tx info
133
+ ```
134
+
135
+ **Key Points:**
136
+
137
+ 1. **Two Requests**: First request returns 402, second request includes payment signature
138
+ 2. **Offline Signing**: User signs in wallet without broadcasting to blockchain
139
+ 3. **Verify → Execute → Check → Settle**: Four-phase process ensures safety
140
+ 4. **Immediate Delivery**: Your business service executes and returns content immediately after verification
141
+ 5. **Settlement After Business**: On-chain transaction only happens after business confirms success
142
+ 6. **User Safety**: If business fails (status >= 400), no settlement occurs, no charge
143
+
144
+ #### Roadmap: Delayed Delivery 🔮
145
+
146
+ We're planning to offer **delayed delivery** mode as an optional feature:
147
+
148
+ ```mermaid
149
+ flowchart TD
150
+ A["Phase 1: Verify<br/>Payment verified"] --> B["Lock Inventory<br/>NOT delivered yet"]
151
+ B --> C["Phase 4: Settle<br/>Settlement on-chain"]
152
+ C --> D{Settlement Result}
153
+ D -->|Success| E["v402pay triggers<br/>Delivery Callback API"]
154
+ D -->|Failed| F["v402pay triggers<br/>Rollback Callback API"]
155
+ E --> G[Deliver content/goods]
156
+ F --> H[Release locked inventory]
157
+
158
+ style A fill:#e1f5ff
159
+ style B fill:#fff9c4
160
+ style C fill:#fff4e1
161
+ style D fill:#f0f0f0
162
+ style E fill:#e8f5e9
163
+ style F fill:#ffebee
164
+ style G fill:#c8e6c9
165
+ style H fill:#ffcdd2
166
+ ```
167
+
168
+ - **When it happens**: Business callback is triggered only after on-chain settlement succeeds
169
+ - **Inventory locking**: Inventory is locked during verification, released on rollback
170
+ - **Best for**:
171
+ - Physical goods delivery
172
+ - Asset-based businesses (NFTs, tokens, securities)
173
+ - High-value transactions requiring strong consistency
174
+ - Scenarios where inventory management is critical
175
+ - **Benefits**:
176
+ - ✅ Zero platform risk (no delivery before payment confirmation)
177
+ - ✅ Strong consistency guarantees
178
+ - ✅ Distributed transaction safety
179
+ - ✅ Automatic rollback on failure
180
+
181
+ **How it works**:
182
+ 1. **Verify Phase**: Lock resources/inventory, but don't deliver yet
183
+ 2. **Settle Phase**: Attempt on-chain settlement
184
+ 3. **On Success**: v402pay platform triggers your delivery callback API
185
+ 4. **On Failure**: v402pay platform triggers your rollback callback API to release locks
186
+
187
+ This feature will be provided by the v402pay platform with configurable options for different merchant needs.
188
+
189
+ ## 🚀 Quick Start
190
+
191
+ ### 1. Register on v402pay Platform
192
+
193
+ Visit [v402pay Platform](https://v402pay.com) to create your merchant account:
194
+
195
+ 1. Register an account
196
+ 2. Create merchant configuration:
197
+ - **Callback URL**: API endpoint called after successful payment
198
+ - **Payment Price**: Fee per access (e.g., 0.01 USDC)
199
+ - **Supported Networks**: Solana, Ethereum, Polygon, etc.
200
+ - **Recipient Address**: Your receiving wallet address
201
+ 3. Get your **merchantId** (for frontend integration)
202
+
203
+ ### 2. Install SDK
204
+
205
+ ```bash
206
+ npm install @voyage_ai/v402-web-ts
207
+ ```
208
+
209
+ ### 3. Two Usage Methods
210
+
211
+ ## Method 1: Use Built-in Components (Recommended, Ready to Use)
212
+
213
+ Perfect for quick integration with pre-built UI components handling wallet connection and payment logic.
214
+
215
+ ```tsx
216
+ import React from 'react';
217
+ import {
218
+ useWallet,
219
+ usePayment,
220
+ usePaymentInfo,
221
+ WalletConnect
222
+ } from '@voyage_ai/v402-web-ts/react';
223
+ import { makePayment } from '@voyage_ai/v402-web-ts';
224
+ import '@voyage_ai/v402-web-ts/react/styles.css';
225
+
226
+ export default function PaymentPage() {
227
+ const merchantId = 'your-merchant-id'; // Get from v402pay
228
+
229
+ // Use React Hooks to manage state
230
+ const { address, networkType } = useWallet();
231
+ const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
232
+ const { supportedNetworks, isLoading } = usePaymentInfo(merchantId);
233
+
234
+ const handlePayment = async () => {
235
+ if (!networkType) return;
236
+
237
+ setIsProcessing(true);
238
+ setError(null);
239
+
240
+ try {
241
+ // Initiate payment
242
+ const response = await makePayment(networkType, merchantId);
243
+ const data = await response.json();
244
+
245
+ // Payment successful, data contains your callback API response
246
+ setResult(data);
247
+ console.log('✅ Payment successful!', data);
248
+ } catch (err: any) {
249
+ setError(err.message || 'Payment failed');
250
+ } finally {
251
+ setIsProcessing(false);
252
+ }
253
+ };
254
+
255
+ return (
256
+ <div>
257
+ <h1>Purchase Content</h1>
258
+
259
+ {/* Wallet Connection Component (Built-in UI) */}
260
+ {!isLoading && (
261
+ <WalletConnect
262
+ supportedNetworks={supportedNetworks}
263
+ />
264
+ )}
265
+
266
+ {/* Payment Button */}
267
+ {address && (
268
+ <button
269
+ onClick={handlePayment}
270
+ disabled={isProcessing}
271
+ >
272
+ {isProcessing ? 'Processing...' : 'Pay Now'}
273
+ </button>
274
+ )}
275
+
276
+ {/* Display Result */}
277
+ {result && (
278
+ <div>
279
+ <h2>Payment Successful! 🎉</h2>
280
+ <pre>{JSON.stringify(result, null, 2)}</pre>
281
+ </div>
282
+ )}
283
+
284
+ {error && <p style={{ color: 'red' }}>{error}</p>}
285
+ </div>
286
+ );
287
+ }
288
+ ```
289
+
290
+ ## Method 2: Custom Wallet Integration
291
+
292
+ If you already have your own wallet connection logic, you can directly call the payment handler functions.
293
+
294
+ ```typescript
295
+ import {
296
+ handleSvmPayment, // Solana payment
297
+ handleEvmPayment, // Ethereum payment
298
+ NetworkType
299
+ } from '@voyage_ai/v402-web-ts';
300
+
301
+ // Solana Payment Example
302
+ async function paySolana() {
303
+ const merchantId = 'your-merchant-id';
304
+
305
+ // Ensure user has connected Phantom wallet
306
+ const wallet = window.solana;
307
+ if (!wallet) {
308
+ throw new Error('Please install Phantom wallet');
309
+ }
310
+
311
+ await wallet.connect();
312
+
313
+ // Call SVM payment
314
+ const response = await handleSvmPayment(
315
+ merchantId,
316
+ wallet // Pass your wallet adapter
317
+ );
318
+
319
+ const result = await response.json();
320
+ console.log('Payment result:', result);
321
+ }
322
+
323
+ // Ethereum Payment Example
324
+ async function payEthereum() {
325
+ const merchantId = 'your-merchant-id';
326
+ const { ethers } = await import('ethers');
327
+
328
+ // Connect MetaMask
329
+ const provider = new ethers.BrowserProvider(window.ethereum);
330
+ const signer = await provider.getSigner();
331
+
332
+ // Create wallet adapter
333
+ const walletAdapter = {
334
+ getAddress: async () => await signer.getAddress(),
335
+ signTypedData: async (domain: any, types: any, value: any) => {
336
+ return await signer.signTypedData(domain, types, value);
337
+ },
338
+ switchChain: async (chainId: string) => {
339
+ await window.ethereum.request({
340
+ method: 'wallet_switchEthereumChain',
341
+ params: [{ chainId }],
342
+ });
343
+ },
344
+ };
345
+
346
+ // Call EVM payment
347
+ const response = await handleEvmPayment(
348
+ merchantId,
349
+ walletAdapter
350
+ );
351
+
352
+ const result = await response.json();
353
+ console.log('Payment result:', result);
354
+ }
355
+ ```
356
+
357
+ ## 📚 API Documentation
358
+
359
+ ### React Hooks
360
+
361
+ #### `useWallet()`
362
+
363
+ Manage wallet connection state.
364
+
365
+ ```typescript
366
+ const {
367
+ address, // Wallet address (string | null)
368
+ networkType, // Network type (NetworkType | null)
369
+ isConnecting, // Is connecting (boolean)
370
+ error, // Error message (string | null)
371
+ connect, // Connect wallet function (networkType: NetworkType) => Promise<void>
372
+ disconnect, // Disconnect function () => void
373
+ clearError // Clear error function () => void
374
+ } = useWallet();
375
+ ```
376
+
377
+ #### `usePayment()`
378
+
379
+ Manage payment state.
380
+
381
+ ```typescript
382
+ const {
383
+ isProcessing, // Is processing (boolean)
384
+ result, // Payment result (any)
385
+ error, // Error message (string | null)
386
+ setIsProcessing, // Set processing state
387
+ setResult, // Set result
388
+ setError, // Set error
389
+ clearResult, // Clear result
390
+ clearError, // Clear error
391
+ reset // Reset all states
392
+ } = usePayment();
393
+ ```
394
+
395
+ #### `usePaymentInfo(merchantId: string)`
396
+
397
+ Fetch merchant payment configuration.
398
+
399
+ ```typescript
400
+ const {
401
+ supportedNetworks, // Supported networks list (NetworkType[])
402
+ isLoading, // Is loading (boolean)
403
+ error // Error message (string | null)
404
+ } = usePaymentInfo('your-merchant-id');
405
+ ```
406
+
407
+ ### React Components
408
+
409
+ #### `<WalletConnect />`
410
+
411
+ Ready-to-use wallet connection component.
412
+
413
+ ```tsx
414
+ <WalletConnect
415
+ supportedNetworks={[NetworkType.SOLANA, NetworkType.EVM]} // Optional
416
+ className="custom-class" // Optional
417
+ onConnect={(address, networkType) => {}} // Optional
418
+ onDisconnect={() => {}} // Optional
419
+ />
420
+ ```
421
+
422
+ **Props:**
423
+ - `supportedNetworks`: Array of supported network types
424
+ - `className`: Custom CSS class name
425
+ - `onConnect`: Callback on successful connection
426
+ - `onDisconnect`: Callback on disconnect
427
+
428
+ ### Core Functions
429
+
430
+ #### `makePayment(networkType, merchantId)`
431
+
432
+ Unified payment entry function that automatically handles different chain payment logic.
433
+
434
+ ```typescript
435
+ import { makePayment, NetworkType } from '@voyage_ai/v402-web-ts';
436
+
437
+ const response = await makePayment(
438
+ NetworkType.SOLANA, // or NetworkType.EVM
439
+ 'your-merchant-id'
440
+ );
441
+
442
+ const result = await response.json();
443
+ ```
444
+
445
+ #### `handleSvmPayment(merchantId, walletAdapter)`
446
+
447
+ Handle Solana (SVM) chain payments.
448
+
449
+ ```typescript
450
+ import { handleSvmPayment } from '@voyage_ai/v402-web-ts';
451
+
452
+ const response = await handleSvmPayment(
453
+ 'your-merchant-id',
454
+ window.solana // Phantom wallet
455
+ );
456
+ ```
457
+
458
+ #### `handleEvmPayment(merchantId, walletAdapter)`
459
+
460
+ Handle Ethereum (EVM) chain payments.
461
+
462
+ ```typescript
463
+ import { handleEvmPayment } from '@voyage_ai/v402-web-ts';
464
+
465
+ const response = await handleEvmPayment(
466
+ 'your-merchant-id',
467
+ evmWalletAdapter // Must implement WalletAdapter interface
468
+ );
469
+ ```
470
+
471
+ ### Type Definitions
472
+
473
+ ```typescript
474
+ // Network Type
475
+ enum NetworkType {
476
+ SOLANA = 'solana',
477
+ SVM = 'svm',
478
+ EVM = 'evm',
479
+ ETHEREUM = 'ethereum'
480
+ }
481
+
482
+ // Wallet Adapter Interface (for custom integration)
483
+ interface WalletAdapter {
484
+ getAddress: () => Promise<string>;
485
+ signTypedData?: (domain: any, types: any, value: any) => Promise<string>;
486
+ switchChain?: (chainId: string) => Promise<void>;
487
+ }
488
+ ```
489
+
490
+ ## 🎨 Custom Styling
491
+
492
+ The SDK provides default styles that you can override:
493
+
494
+ ```css
495
+ /* Override wallet connect button style */
496
+ .x402-wallet-button {
497
+ background-color: your-color;
498
+ border-radius: 8px;
499
+ }
500
+
501
+ /* Override wallet card style */
502
+ .x402-wallet-card {
503
+ border: 2px solid your-color;
504
+ }
505
+ ```
506
+
507
+ Or don't import default styles and fully customize:
508
+
509
+ ```tsx
510
+ // Don't import default styles
511
+ // import '@voyage_ai/v402-web-ts/react/styles.css';
512
+
513
+ // Use your own components and styles
514
+ import { useWallet, usePayment } from '@voyage_ai/v402-web-ts/react';
515
+ import { makePayment } from '@voyage_ai/v402-web-ts';
516
+ ```
517
+
518
+ ## 🔧 Advanced Usage
519
+
520
+ ### Monitor Wallet State Changes
521
+
522
+ ```typescript
523
+ import { useWallet } from '@voyage_ai/v402-web-ts/react';
524
+ import { useEffect } from 'react';
525
+
526
+ function MyComponent() {
527
+ const { address, networkType } = useWallet();
528
+
529
+ useEffect(() => {
530
+ if (address) {
531
+ console.log('Wallet connected:', address, networkType);
532
+ // Execute your logic
533
+ }
534
+ }, [address, networkType]);
535
+ }
536
+ ```
537
+
538
+ ### Handle Payment Callback
539
+
540
+ ```typescript
541
+ const handlePayment = async () => {
542
+ try {
543
+ const response = await makePayment(networkType, merchantId);
544
+ const data = await response.json();
545
+
546
+ // data contains your callback API response
547
+ // For example:
548
+ // {
549
+ // "success": true,
550
+ // "content": "Your purchased content",
551
+ // "downloadUrl": "https://...",
552
+ // "expiresAt": "2024-12-31"
553
+ // }
554
+
555
+ if (data.success) {
556
+ // Handle success logic
557
+ showContent(data.content);
558
+ }
559
+ } catch (error) {
560
+ // Handle error
561
+ console.error('Payment failed:', error);
562
+ }
563
+ };
564
+ ```
565
+
566
+ ### Error Handling
567
+
568
+ ```typescript
569
+ import { usePayment } from '@voyage_ai/v402-web-ts/react';
570
+
571
+ function PaymentComponent() {
572
+ const { error, clearError } = usePayment();
573
+
574
+ useEffect(() => {
575
+ if (error) {
576
+ // Show error message
577
+ alert(error);
578
+
579
+ // Auto clear error after 3 seconds
580
+ setTimeout(() => {
581
+ clearError();
582
+ }, 3000);
583
+ }
584
+ }, [error]);
585
+ }
586
+ ```
587
+
588
+ ## 🌐 Supported Networks
589
+
590
+ ### Solana (SVM)
591
+ - Solana Mainnet
592
+ - Solana Devnet
593
+
594
+ ### Ethereum (EVM)
595
+ - Ethereum Mainnet
596
+ - Polygon
597
+ - Base
598
+ - Avalanche
599
+ - BSC (Binance Smart Chain)
600
+ - Arbitrum
601
+ - Optimism
602
+ - And other EVM-compatible chains
603
+
604
+ ## 📦 Dependencies
605
+
606
+ ### Peer Dependencies
607
+
608
+ ```json
609
+ {
610
+ "react": ">=18.0.0",
611
+ "@solana/web3.js": "^1.95.0",
612
+ "@solana/spl-token": "^0.4.0",
613
+ "ethers": "^6.0.0"
614
+ }
615
+ ```
616
+
617
+ **Note**: If you only use Solana, you don't need to install `ethers`; if you only use EVM, you don't need Solana-related packages.
618
+
619
+ ## 🤝 Contributing
620
+
621
+ Issues and Pull Requests are welcome!
622
+
623
+ ## 📄 License
624
+
625
+ MIT License
626
+
627
+ ## 🔗 Links
628
+
629
+ - [v402pay Platform](https://v402pay.com)
630
+ - [GitHub Repository](https://github.com/voyage_ai/v402-web-ts)
631
+ - [npm Package](https://www.npmjs.com/package/@voyage_ai/v402-web-ts)
632
+
633
+ ## 💡 Example Project
634
+
635
+ Check out the complete example project: [v402pay-example](https://github.com/voyage_ai/v402pay-example)
636
+
637
+ ---
638
+
639
+ For questions, please visit [v402pay Documentation](https://docs.v402pay.com) or contact technical support.
package/dist/index.d.mts CHANGED
@@ -26,6 +26,7 @@ interface EvmWalletAdapter {
26
26
  address: string;
27
27
  signTypedData: (domain: any, types: any, message: any) => Promise<string>;
28
28
  switchChain?: (chainId: string) => Promise<void>;
29
+ getChainId?: () => Promise<string>;
29
30
  }
30
31
  /**
31
32
  * Network type enum - for wallet detection
package/dist/index.d.ts CHANGED
@@ -26,6 +26,7 @@ interface EvmWalletAdapter {
26
26
  address: string;
27
27
  signTypedData: (domain: any, types: any, message: any) => Promise<string>;
28
28
  switchChain?: (chainId: string) => Promise<void>;
29
+ getChainId?: () => Promise<string>;
29
30
  }
30
31
  /**
31
32
  * Network type enum - for wallet detection