@voyage_ai/v402-web-ts 0.1.6 → 0.2.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
@@ -193,12 +193,12 @@ This feature will be provided by the v402pay platform with configurable options
193
193
  Visit [v402pay Platform](https://v402pay.com) to create your merchant account:
194
194
 
195
195
  1. Register an account
196
- 2. Create merchant configuration:
196
+ 2. Create checkout configuration:
197
197
  - **Callback URL**: API endpoint called after successful payment
198
198
  - **Payment Price**: Fee per access (e.g., 0.01 USDC)
199
- - **Supported Networks**: Solana, Ethereum, Polygon, etc.
199
+ - **Supported Networks**: Solana, Ethereum, Base, etc.
200
200
  - **Recipient Address**: Your receiving wallet address
201
- 3. Get your **merchantId** (for frontend integration)
201
+ 3. Get your **checkoutId** (for frontend integration)
202
202
 
203
203
  ### 2. Install SDK
204
204
 
@@ -206,30 +206,78 @@ Visit [v402pay Platform](https://v402pay.com) to create your merchant account:
206
206
  npm install @voyage_ai/v402-web-ts
207
207
  ```
208
208
 
209
- ### 3. Two Usage Methods
209
+ ### 3. Three Usage Methods
210
210
 
211
- ## Method 1: Use Built-in Components (Recommended, Ready to Use)
211
+ ## Method 1: Use V402Checkout Component (Recommended, 1 Line of Code)
212
212
 
213
- Perfect for quick integration with pre-built UI components handling wallet connection and payment logic.
213
+ The easiest way - complete payment UI with wallet connection, payment processing, and result display built-in.
214
+
215
+ ```tsx
216
+ import React from 'react';
217
+ import { V402Checkout } from '@voyage_ai/v402-web-ts/react';
218
+ import '@voyage_ai/v402-web-ts/react/styles.css';
219
+ import 'antd/dist/reset.css'; // Ant Design styles
220
+
221
+ export default function PaymentPage() {
222
+ return (
223
+ <V402Checkout
224
+ checkoutId="your-checkout-id" // Get from v402pay platform
225
+ headerInfo={{
226
+ title: 'Premium Content Access',
227
+ subtitle: 'mysite.com',
228
+ tooltipText: 'One-time payment for lifetime access'
229
+ }}
230
+ onPaymentComplete={(result) => {
231
+ console.log('✅ Payment successful!', result);
232
+ // Handle post-payment logic (redirect, show content, etc.)
233
+ }}
234
+ additionalParams={{
235
+ userId: '123',
236
+ // Any custom params to pass to your callback API
237
+ }}
238
+ expectedNetwork="evm" // Optional: 'evm' or 'svm'
239
+ isModal={false} // Optional: true for modal mode, false for full page
240
+ />
241
+ );
242
+ }
243
+ ```
244
+
245
+ **Props:**
246
+ - `checkoutId` (required): Your checkout ID from v402pay platform
247
+ - `headerInfo` (optional): Customize header display
248
+ - `onPaymentComplete` (optional): Callback when payment succeeds
249
+ - `additionalParams` (optional): Custom parameters to pass to your callback API
250
+ - `expectedNetwork` (optional): Force specific network type ('evm' or 'svm')
251
+ - `isModal` (optional): Display as modal (true) or full page (false)
252
+
253
+ ## Method 2: Use Built-in Hooks (Custom UI)
254
+
255
+ Perfect for building custom UI while leveraging built-in payment logic.
214
256
 
215
257
  ```tsx
216
258
  import React from 'react';
217
259
  import {
218
- useWallet,
260
+ usePageNetwork, // Auto-manage network for the page
219
261
  usePayment,
220
262
  usePaymentInfo,
221
263
  WalletConnect
222
264
  } from '@voyage_ai/v402-web-ts/react';
223
- import { makePayment } from '@voyage_ai/v402-web-ts';
265
+ import { makePayment, NetworkType } from '@voyage_ai/v402-web-ts';
224
266
  import '@voyage_ai/v402-web-ts/react/styles.css';
225
267
 
226
- export default function PaymentPage() {
227
- const merchantId = 'your-merchant-id'; // Get from v402pay
268
+ export default function CustomPaymentPage() {
269
+ const checkoutId = 'your-checkout-id';
270
+
271
+ // Fetch payment info to get supported networks
272
+ const { supportedNetworks, isLoading, paymentInfo } = usePaymentInfo(checkoutId);
273
+
274
+ // Auto-manage wallet for this page's expected network
275
+ const { address, networkType, disconnect } = usePageNetwork(
276
+ supportedNetworks[0] || NetworkType.EVM,
277
+ { autoSwitch: true }
278
+ );
228
279
 
229
- // Use React Hooks to manage state
230
- const { address, networkType } = useWallet();
231
280
  const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
232
- const { supportedNetworks, isLoading } = usePaymentInfo(merchantId);
233
281
 
234
282
  const handlePayment = async () => {
235
283
  if (!networkType) return;
@@ -238,11 +286,8 @@ export default function PaymentPage() {
238
286
  setError(null);
239
287
 
240
288
  try {
241
- // Initiate payment
242
- const response = await makePayment(networkType, merchantId);
289
+ const response = await makePayment(networkType, checkoutId);
243
290
  const data = await response.json();
244
-
245
- // Payment successful, data contains your callback API response
246
291
  setResult(data);
247
292
  console.log('✅ Payment successful!', data);
248
293
  } catch (err: any) {
@@ -256,24 +301,23 @@ export default function PaymentPage() {
256
301
  <div>
257
302
  <h1>Purchase Content</h1>
258
303
 
259
- {/* Wallet Connection Component (Built-in UI) */}
260
- {!isLoading && (
261
- <WalletConnect
262
- supportedNetworks={supportedNetworks}
263
- />
304
+ {/* Wallet Connection */}
305
+ {!isLoading && !address && (
306
+ <WalletConnect supportedNetworks={supportedNetworks} />
264
307
  )}
265
308
 
266
- {/* Payment Button */}
309
+ {/* Connected State */}
267
310
  {address && (
268
- <button
269
- onClick={handlePayment}
270
- disabled={isProcessing}
271
- >
272
- {isProcessing ? 'Processing...' : 'Pay Now'}
273
- </button>
311
+ <div>
312
+ <p>Connected: {address}</p>
313
+ <button onClick={disconnect}>Disconnect</button>
314
+ <button onClick={handlePayment} disabled={isProcessing}>
315
+ {isProcessing ? 'Processing...' : 'Pay Now'}
316
+ </button>
317
+ </div>
274
318
  )}
275
319
 
276
- {/* Display Result */}
320
+ {/* Result */}
277
321
  {result && (
278
322
  <div>
279
323
  <h2>Payment Successful! 🎉</h2>
@@ -287,9 +331,9 @@ export default function PaymentPage() {
287
331
  }
288
332
  ```
289
333
 
290
- ## Method 2: Custom Wallet Integration
334
+ ## Method 3: Direct Handler Integration (Advanced)
291
335
 
292
- If you already have your own wallet connection logic, you can directly call the payment handler functions.
336
+ If you have your own wallet connection logic, directly call the payment handler functions.
293
337
 
294
338
  ```typescript
295
339
  import {
@@ -300,20 +344,24 @@ import {
300
344
 
301
345
  // Solana Payment Example
302
346
  async function paySolana() {
303
- const merchantId = 'your-merchant-id';
347
+ const checkoutId = 'your-checkout-id';
348
+ const endpoint = 'https://v402.onvoyage.ai/api/pay';
304
349
 
305
350
  // Ensure user has connected Phantom wallet
306
351
  const wallet = window.solana;
307
- if (!wallet) {
308
- throw new Error('Please install Phantom wallet');
352
+ if (!wallet?.isConnected) {
353
+ await wallet.connect();
309
354
  }
310
355
 
311
- await wallet.connect();
312
-
313
- // Call SVM payment
356
+ // Call SVM payment handler
314
357
  const response = await handleSvmPayment(
315
- merchantId,
316
- wallet // Pass your wallet adapter
358
+ endpoint,
359
+ {
360
+ wallet,
361
+ network: 'solana-mainnet', // or 'solana-devnet'
362
+ checkoutId,
363
+ additionalParams: { userId: '123' } // Optional
364
+ }
317
365
  );
318
366
 
319
367
  const result = await response.json();
@@ -322,31 +370,29 @@ async function paySolana() {
322
370
 
323
371
  // Ethereum Payment Example
324
372
  async function payEthereum() {
325
- const merchantId = 'your-merchant-id';
326
- const { ethers } = await import('ethers');
373
+ const checkoutId = 'your-checkout-id';
374
+ const endpoint = 'https://v402.onvoyage.ai/api/pay';
327
375
 
328
- // Connect MetaMask
329
- const provider = new ethers.BrowserProvider(window.ethereum);
330
- const signer = await provider.getSigner();
331
-
332
- // Create wallet adapter
376
+ // Get wallet adapter
333
377
  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);
378
+ address: await window.ethereum.request({ method: 'eth_requestAccounts' })[0],
379
+ signTypedData: async (domain: any, types: any, message: any) => {
380
+ // Implement EIP-712 signing
337
381
  },
338
382
  switchChain: async (chainId: string) => {
339
- await window.ethereum.request({
340
- method: 'wallet_switchEthereumChain',
341
- params: [{ chainId }],
342
- });
343
- },
383
+ // Implement chain switching
384
+ }
344
385
  };
345
386
 
346
- // Call EVM payment
387
+ // Call EVM payment handler
347
388
  const response = await handleEvmPayment(
348
- merchantId,
349
- walletAdapter
389
+ endpoint,
390
+ {
391
+ wallet: walletAdapter,
392
+ network: 'base-mainnet', // or 'ethereum-mainnet', 'polygon-mainnet', etc.
393
+ checkoutId,
394
+ additionalParams: { userId: '123' } // Optional
395
+ }
350
396
  );
351
397
 
352
398
  const result = await response.json();
@@ -360,7 +406,7 @@ async function payEthereum() {
360
406
 
361
407
  #### `useWallet()`
362
408
 
363
- Manage wallet connection state.
409
+ Manage wallet connection state (external store, no Provider needed).
364
410
 
365
411
  ```typescript
366
412
  const {
@@ -368,54 +414,129 @@ const {
368
414
  networkType, // Network type (NetworkType | null)
369
415
  isConnecting, // Is connecting (boolean)
370
416
  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
417
+ connect, // Connect wallet: (networkType: NetworkType) => Promise<void>
418
+ switchNetwork, // Switch network: (networkType: NetworkType) => Promise<void>
419
+ ensureNetwork, // Ensure network: (networkType: NetworkType) => Promise<void>
420
+ disconnect, // Disconnect wallet: () => void
421
+ clearError // Clear error: () => void
374
422
  } = useWallet();
375
423
  ```
376
424
 
425
+ **Features:**
426
+ - ✅ No Context Provider needed (uses React 18's `useSyncExternalStore`)
427
+ - ✅ Supports EVM and SVM wallet coexistence
428
+ - ✅ Auto-persists wallet addresses per network
429
+ - ✅ Prevents auto-reconnect after manual disconnect
430
+
431
+ #### `usePageNetwork(expectedNetwork, options?)`
432
+
433
+ Page-level network management - automatically ensures correct network for the page.
434
+
435
+ ```typescript
436
+ const wallet = usePageNetwork(
437
+ NetworkType.EVM, // Expected network type for this page
438
+ {
439
+ autoSwitch: true, // Auto-switch to expected network (default: true)
440
+ switchOnMount: true, // Switch on component mount (default: true)
441
+ }
442
+ );
443
+ // Returns same interface as useWallet()
444
+ ```
445
+
446
+ **Use Cases:**
447
+ - EVM-only pages: `usePageNetwork(NetworkType.EVM)`
448
+ - SVM-only pages: `usePageNetwork(NetworkType.SVM)`
449
+ - Automatic network management when switching between pages
450
+
451
+ **Example:**
452
+ ```tsx
453
+ // Page A - EVM only
454
+ function EvmPage() {
455
+ const { address } = usePageNetwork(NetworkType.EVM);
456
+ return <div>EVM Address: {address}</div>;
457
+ }
458
+
459
+ // Page B - SVM only
460
+ function SvmPage() {
461
+ const { address } = usePageNetwork(NetworkType.SVM);
462
+ return <div>SVM Address: {address}</div>;
463
+ }
464
+ ```
465
+
377
466
  #### `usePayment()`
378
467
 
379
- Manage payment state.
468
+ Manage payment state (state only, no payment logic).
380
469
 
381
470
  ```typescript
382
471
  const {
383
- isProcessing, // Is processing (boolean)
384
- result, // Payment result (any)
385
- error, // Error message (string | null)
472
+ isProcessing, // Is processing (boolean)
473
+ result, // Payment result (any)
474
+ error, // Error message (string | null)
386
475
  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
476
+ setResult, // Set result
477
+ setError, // Set error
478
+ clearResult, // Clear result
479
+ clearError, // Clear error
480
+ reset // Reset all states
392
481
  } = usePayment();
393
482
  ```
394
483
 
395
- #### `usePaymentInfo(merchantId: string)`
484
+ #### `usePaymentInfo(checkoutId, endpoint?, additionalParams?)`
396
485
 
397
- Fetch merchant payment configuration.
486
+ Fetch checkout payment configuration from backend.
398
487
 
399
488
  ```typescript
400
489
  const {
401
- supportedNetworks, // Supported networks list (NetworkType[])
490
+ supportedNetworks, // Supported network types (NetworkType[])
402
491
  isLoading, // Is loading (boolean)
403
- error // Error message (string | null)
404
- } = usePaymentInfo('your-merchant-id');
492
+ error, // Error message (string | null)
493
+ paymentInfo // Raw payment info from backend (any)
494
+ } = usePaymentInfo(
495
+ 'your-checkout-id',
496
+ 'https://v402.onvoyage.ai/api/pay', // Optional
497
+ { userId: '123' } // Optional
498
+ );
405
499
  ```
406
500
 
407
501
  ### React Components
408
502
 
503
+ #### `<V402Checkout />`
504
+
505
+ Complete checkout component with built-in wallet connection, payment UI, and result display.
506
+
507
+ ```tsx
508
+ <V402Checkout
509
+ checkoutId="your-checkout-id" // Required
510
+ headerInfo={{ // Optional
511
+ title: 'Payment Title',
512
+ subtitle: 'yoursite.com',
513
+ tooltipText: 'Payment description'
514
+ }}
515
+ isModal={false} // Optional: modal or full page
516
+ onPaymentComplete={(result) => {}} // Optional: callback
517
+ additionalParams={{ userId: '123' }} // Optional: custom params
518
+ expectedNetwork={NetworkType.EVM} // Optional: force network
519
+ />
520
+ ```
521
+
522
+ **Props:**
523
+ - `checkoutId` (required): Your checkout ID from v402pay
524
+ - `headerInfo` (optional): Customize header display
525
+ - `isModal` (optional): Display as modal (true) or full page (false)
526
+ - `onPaymentComplete` (optional): Callback function on successful payment
527
+ - `additionalParams` (optional): Custom parameters to pass to callback API
528
+ - `expectedNetwork` (optional): Force specific network type
529
+
409
530
  #### `<WalletConnect />`
410
531
 
411
- Ready-to-use wallet connection component.
532
+ Standalone wallet connection component (used internally by V402Checkout).
412
533
 
413
534
  ```tsx
414
535
  <WalletConnect
415
- supportedNetworks={[NetworkType.SOLANA, NetworkType.EVM]} // Optional
416
- className="custom-class" // Optional
417
- onConnect={(address, networkType) => {}} // Optional
418
- onDisconnect={() => {}} // Optional
536
+ supportedNetworks={[NetworkType.SOLANA, NetworkType.EVM]}
537
+ className="custom-class"
538
+ onConnect={(address, networkType) => {}}
539
+ onDisconnect={() => {}}
419
540
  />
420
541
  ```
421
542
 
@@ -427,7 +548,7 @@ Ready-to-use wallet connection component.
427
548
 
428
549
  ### Core Functions
429
550
 
430
- #### `makePayment(networkType, merchantId)`
551
+ #### `makePayment(networkType, checkoutId, endpoint?, additionalParams?)`
431
552
 
432
553
  Unified payment entry function that automatically handles different chain payment logic.
433
554
 
@@ -435,14 +556,16 @@ Unified payment entry function that automatically handles different chain paymen
435
556
  import { makePayment, NetworkType } from '@voyage_ai/v402-web-ts';
436
557
 
437
558
  const response = await makePayment(
438
- NetworkType.SOLANA, // or NetworkType.EVM
439
- 'your-merchant-id'
559
+ NetworkType.EVM, // or NetworkType.SVM
560
+ 'your-checkout-id',
561
+ 'https://v402.onvoyage.ai/api/pay', // Optional
562
+ { userId: '123' } // Optional
440
563
  );
441
564
 
442
565
  const result = await response.json();
443
566
  ```
444
567
 
445
- #### `handleSvmPayment(merchantId, walletAdapter)`
568
+ #### `handleSvmPayment(endpoint, options)`
446
569
 
447
570
  Handle Solana (SVM) chain payments.
448
571
 
@@ -450,12 +573,23 @@ Handle Solana (SVM) chain payments.
450
573
  import { handleSvmPayment } from '@voyage_ai/v402-web-ts';
451
574
 
452
575
  const response = await handleSvmPayment(
453
- 'your-merchant-id',
454
- window.solana // Phantom wallet
576
+ 'https://v402.onvoyage.ai/api/pay',
577
+ {
578
+ wallet: window.solana, // Phantom wallet
579
+ network: 'solana-mainnet', // or 'solana-devnet'
580
+ checkoutId: 'your-checkout-id',
581
+ additionalParams: { userId: '123' } // Optional
582
+ }
455
583
  );
456
584
  ```
457
585
 
458
- #### `handleEvmPayment(merchantId, walletAdapter)`
586
+ **Options:**
587
+ - `wallet`: Solana wallet adapter (Phantom, Solflare, etc.)
588
+ - `network`: Network name (e.g., 'solana-mainnet', 'solana-devnet')
589
+ - `checkoutId`: Your checkout ID
590
+ - `additionalParams`: Custom parameters for your callback API
591
+
592
+ #### `handleEvmPayment(endpoint, options)`
459
593
 
460
594
  Handle Ethereum (EVM) chain payments.
461
595
 
@@ -463,27 +597,54 @@ Handle Ethereum (EVM) chain payments.
463
597
  import { handleEvmPayment } from '@voyage_ai/v402-web-ts';
464
598
 
465
599
  const response = await handleEvmPayment(
466
- 'your-merchant-id',
467
- evmWalletAdapter // Must implement WalletAdapter interface
600
+ 'https://v402.onvoyage.ai/api/pay',
601
+ {
602
+ wallet: evmWalletAdapter, // EVM wallet adapter
603
+ network: 'base-mainnet', // Network name
604
+ checkoutId: 'your-checkout-id',
605
+ additionalParams: { userId: '123' } // Optional
606
+ }
468
607
  );
469
608
  ```
470
609
 
610
+ **Options:**
611
+ - `wallet`: EVM wallet adapter (must implement EvmWalletAdapter interface)
612
+ - `network`: Network name (e.g., 'ethereum-mainnet', 'base-mainnet', 'polygon-mainnet')
613
+ - `checkoutId`: Your checkout ID
614
+ - `additionalParams`: Custom parameters for your callback API
615
+
471
616
  ### Type Definitions
472
617
 
473
618
  ```typescript
474
- // Network Type
619
+ // Network Type (用于区分钱包类型)
475
620
  enum NetworkType {
476
- SOLANA = 'solana',
477
- SVM = 'svm',
478
- EVM = 'evm',
479
- ETHEREUM = 'ethereum'
621
+ EVM = 'evm', // Ethereum Virtual Machine
622
+ SVM = 'svm', // Solana Virtual Machine
623
+ SOLANA = 'solana' // Alias for SVM
480
624
  }
481
625
 
482
- // Wallet Adapter Interface (for custom integration)
626
+ // Solana Wallet Adapter Interface
483
627
  interface WalletAdapter {
484
- getAddress: () => Promise<string>;
485
- signTypedData?: (domain: any, types: any, value: any) => Promise<string>;
628
+ publicKey?: { toString(): string };
629
+ address?: string;
630
+ signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction>;
631
+ }
632
+
633
+ // EVM Wallet Adapter Interface
634
+ interface EvmWalletAdapter {
635
+ address: string;
636
+ signTypedData: (domain: any, types: any, message: any) => Promise<string>;
486
637
  switchChain?: (chainId: string) => Promise<void>;
638
+ getChainId?: () => Promise<string>;
639
+ }
640
+
641
+ // Payment Info from Backend
642
+ interface PaymentInfo {
643
+ amount: string;
644
+ currency: string;
645
+ network: string; // Network name (e.g., 'base-mainnet', 'solana-devnet')
646
+ asset: string;
647
+ maxAmountRequired: number;
487
648
  }
488
649
  ```
489
650
 
@@ -517,6 +678,46 @@ import { makePayment } from '@voyage_ai/v402-web-ts';
517
678
 
518
679
  ## 🔧 Advanced Usage
519
680
 
681
+ ### Multi-Network Support in One App
682
+
683
+ The SDK supports EVM and SVM wallets coexisting in the same application.
684
+
685
+ ```tsx
686
+ import { usePageNetwork, NetworkType } from '@voyage_ai/v402-web-ts/react';
687
+
688
+ // Page 1: EVM Network
689
+ function EthereumPage() {
690
+ const { address, networkType } = usePageNetwork(NetworkType.EVM);
691
+
692
+ return (
693
+ <div>
694
+ <h2>Ethereum Payment Page</h2>
695
+ <p>Connected: {address}</p>
696
+ {/* EVM payment logic */}
697
+ </div>
698
+ );
699
+ }
700
+
701
+ // Page 2: SVM Network
702
+ function SolanaPage() {
703
+ const { address, networkType } = usePageNetwork(NetworkType.SVM);
704
+
705
+ return (
706
+ <div>
707
+ <h2>Solana Payment Page</h2>
708
+ <p>Connected: {address}</p>
709
+ {/* SVM payment logic */}
710
+ </div>
711
+ );
712
+ }
713
+ ```
714
+
715
+ **Key Features:**
716
+ - ✅ Wallets cached separately per network
717
+ - ✅ Switching pages automatically switches wallet
718
+ - ✅ Disconnect on one network doesn't affect the other
719
+ - ✅ Refresh page maintains correct network context
720
+
520
721
  ### Monitor Wallet State Changes
521
722
 
522
723
  ```typescript
@@ -535,15 +736,17 @@ function MyComponent() {
535
736
  }
536
737
  ```
537
738
 
538
- ### Handle Payment Callback
739
+ ### Handle Payment Response
740
+
741
+ The payment response includes both your callback API data and payment metadata:
539
742
 
540
743
  ```typescript
541
744
  const handlePayment = async () => {
542
745
  try {
543
- const response = await makePayment(networkType, merchantId);
746
+ const response = await makePayment(networkType, checkoutId);
544
747
  const data = await response.json();
545
748
 
546
- // data contains your callback API response
749
+ // data is your callback API response
547
750
  // For example:
548
751
  // {
549
752
  // "success": true,
@@ -552,12 +755,17 @@ const handlePayment = async () => {
552
755
  // "expiresAt": "2024-12-31"
553
756
  // }
554
757
 
758
+ // Payment metadata in response headers
759
+ const paymentResponse = response.headers.get('X-PAYMENT-RESPONSE');
760
+ if (paymentResponse) {
761
+ const paymentData = JSON.parse(paymentResponse);
762
+ console.log('Transaction Hash:', paymentData.txHash);
763
+ }
764
+
555
765
  if (data.success) {
556
- // Handle success logic
557
766
  showContent(data.content);
558
767
  }
559
768
  } catch (error) {
560
- // Handle error
561
769
  console.error('Payment failed:', error);
562
770
  }
563
771
  };
@@ -566,55 +774,117 @@ const handlePayment = async () => {
566
774
  ### Error Handling
567
775
 
568
776
  ```typescript
569
- import { usePayment } from '@voyage_ai/v402-web-ts/react';
777
+ import { useWallet, usePayment } from '@voyage_ai/v402-web-ts/react';
778
+ import { useEffect } from 'react';
570
779
 
571
780
  function PaymentComponent() {
572
- const { error, clearError } = usePayment();
781
+ const { error: walletError, clearError: clearWalletError } = useWallet();
782
+ const { error: paymentError, clearError: clearPaymentError } = usePayment();
783
+
784
+ useEffect(() => {
785
+ if (walletError) {
786
+ console.error('Wallet error:', walletError);
787
+ // Handle wallet connection errors
788
+ }
789
+ }, [walletError]);
573
790
 
574
791
  useEffect(() => {
575
- if (error) {
576
- // Show error message
577
- alert(error);
792
+ if (paymentError) {
793
+ console.error('Payment error:', paymentError);
794
+ // Handle payment errors
578
795
 
579
- // Auto clear error after 3 seconds
796
+ // Auto clear after 3 seconds
580
797
  setTimeout(() => {
581
- clearError();
798
+ clearPaymentError();
582
799
  }, 3000);
583
800
  }
584
- }, [error]);
801
+ }, [paymentError]);
585
802
  }
586
803
  ```
587
804
 
588
- ## 🌐 Supported Networks
805
+ **Common Error Scenarios:**
806
+ - Wallet not installed: `Please install MetaMask/Phantom wallet`
807
+ - User rejected: `User rejected the connection/transaction`
808
+ - Network mismatch: `Chain changed. Please reconnect your wallet.`
809
+ - Insufficient funds: Backend returns payment failure
810
+ - Invalid checkout: `Failed to load payment information`
589
811
 
590
- ### Solana (SVM)
591
- - Solana Mainnet
592
- - Solana Devnet
812
+ ## 🌐 Network Types vs Network Names
593
813
 
594
- ### Ethereum (EVM)
595
- - Ethereum Mainnet
596
- - Polygon
597
- - Base
598
- - Avalanche
599
- - BSC (Binance Smart Chain)
600
- - Arbitrum
601
- - Optimism
814
+ ### Important Distinction
815
+
816
+ The SDK distinguishes between **Network Type** (wallet type) and **Network Name** (specific blockchain):
817
+
818
+ #### Network Type (钱包类型)
819
+ Used for wallet management - which wallet to connect:
820
+
821
+ ```typescript
822
+ enum NetworkType {
823
+ EVM = 'evm', // Ethereum Virtual Machine wallets (MetaMask, etc.)
824
+ SVM = 'svm', // Solana Virtual Machine wallets (Phantom, etc.)
825
+ SOLANA = 'solana' // Alias for SVM
826
+ }
827
+ ```
828
+
829
+ **Usage:** `usePageNetwork(NetworkType.EVM)`, `connect(NetworkType.SVM)`
830
+
831
+ #### Network Name (具体网络)
832
+ Specific blockchain for the payment transaction:
833
+
834
+ **SVM Networks:**
835
+ - `solana-mainnet`
836
+ - `solana-devnet`
837
+
838
+ **EVM Networks:**
839
+ - `ethereum-mainnet`
840
+ - `base-mainnet`
841
+ - `polygon-mainnet`
842
+ - `avalanche-mainnet`
843
+ - `bsc-mainnet` (Binance Smart Chain)
844
+ - `arbitrum-mainnet`
845
+ - `optimism-mainnet`
602
846
  - And other EVM-compatible chains
603
847
 
848
+ **Usage:** Used in `handleSvmPayment()`, `handleEvmPayment()`, and backend payment configuration
849
+
850
+ ### Example
851
+
852
+ ```typescript
853
+ // Network Type: EVM (which wallet to use)
854
+ const { address } = usePageNetwork(NetworkType.EVM);
855
+
856
+ // Network Name: base-mainnet (which blockchain to pay on)
857
+ const response = await handleEvmPayment(endpoint, {
858
+ wallet: evmAdapter,
859
+ network: 'base-mainnet', // ← Network Name
860
+ checkoutId: 'xxx'
861
+ });
862
+ ```
863
+
604
864
  ## 📦 Dependencies
605
865
 
606
- ### Peer Dependencies
866
+ ### Required Dependencies
607
867
 
608
868
  ```json
609
869
  {
610
870
  "react": ">=18.0.0",
611
871
  "@solana/web3.js": "^1.95.0",
612
872
  "@solana/spl-token": "^0.4.0",
613
- "ethers": "^6.0.0"
873
+ "antd": "^5.0.0" // For V402Checkout component
874
+ }
875
+ ```
876
+
877
+ ### Optional Dependencies
878
+
879
+ ```json
880
+ {
881
+ "ethers": "^6.0.0" // Only needed if using EVM networks
614
882
  }
615
883
  ```
616
884
 
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.
885
+ **Note**:
886
+ - If you only use `V402Checkout` component, all dependencies are included
887
+ - For custom integration, install only the wallets you need (Solana or EVM)
618
888
 
619
889
  ## 🤝 Contributing
620
890
 
@@ -630,9 +900,72 @@ MIT License
630
900
  - [GitHub Repository](https://github.com/voyage_ai/v402-web-ts)
631
901
  - [npm Package](https://www.npmjs.com/package/@voyage_ai/v402-web-ts)
632
902
 
633
- ## 💡 Example Project
903
+ ## 💡 Quick Examples
904
+
905
+ ### Minimal Integration (1 Line)
906
+
907
+ ```tsx
908
+ import { V402Checkout } from '@voyage_ai/v402-web-ts/react';
909
+ import '@voyage_ai/v402-web-ts/react/styles.css';
910
+
911
+ export default function App() {
912
+ return <V402Checkout checkoutId="your-checkout-id" />;
913
+ }
914
+ ```
915
+
916
+ ### With Custom Callback
634
917
 
635
- Check out the complete example project: [v402pay-example](https://github.com/voyage_ai/v402pay-example)
918
+ ```tsx
919
+ import { V402Checkout } from '@voyage_ai/v402-web-ts/react';
920
+
921
+ export default function App() {
922
+ return (
923
+ <V402Checkout
924
+ checkoutId="your-checkout-id"
925
+ onPaymentComplete={(result) => {
926
+ // Redirect to success page
927
+ window.location.href = `/content/${result.contentId}`;
928
+ }}
929
+ />
930
+ );
931
+ }
932
+ ```
933
+
934
+ ### Modal Mode
935
+
936
+ ```tsx
937
+ import { useState } from 'react';
938
+ import { V402Checkout } from '@voyage_ai/v402-web-ts/react';
939
+ import { Modal } from 'antd';
940
+
941
+ export default function App() {
942
+ const [isModalOpen, setIsModalOpen] = useState(false);
943
+
944
+ return (
945
+ <>
946
+ <button onClick={() => setIsModalOpen(true)}>
947
+ Purchase Content
948
+ </button>
949
+
950
+ <Modal
951
+ open={isModalOpen}
952
+ onCancel={() => setIsModalOpen(false)}
953
+ footer={null}
954
+ width={520}
955
+ >
956
+ <V402Checkout
957
+ checkoutId="your-checkout-id"
958
+ isModal={true}
959
+ onPaymentComplete={(result) => {
960
+ setIsModalOpen(false);
961
+ // Handle success
962
+ }}
963
+ />
964
+ </Modal>
965
+ </>
966
+ );
967
+ }
968
+ ```
636
969
 
637
970
  ---
638
971