@voyage_ai/v402-web-ts 0.1.0 → 0.1.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.
- package/README.md +639 -1
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +600 -229
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +600 -229
- package/dist/index.mjs.map +1 -1
- package/dist/react/components/WalletConnect.tsx +47 -20
- package/dist/react/hooks/usePaymentInfo.ts +38 -4
- package/dist/react/hooks/useWallet.ts +35 -8
- package/dist/react/index.d.mts +16 -55
- package/dist/react/index.d.ts +16 -55
- package/dist/react/index.js +270 -399
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +272 -400
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/index.ts +5 -9
- package/dist/react/store/walletStore.ts +29 -0
- package/dist/react/styles/inline-styles.ts +238 -0
- package/dist/react/styles.css +8 -1
- package/package.json +8 -6
- package/dist/react/components/PaymentButton.tsx +0 -112
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
|
|
@@ -441,6 +442,7 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
|
|
|
441
442
|
* @param endpoint - API endpoint
|
|
442
443
|
* @param networkType - Network type (from useWallet)
|
|
443
444
|
* @param merchantId - @see our website to apply
|
|
445
|
+
* @param additionalParams - Optional additional parameters to send with the request (default: {})
|
|
444
446
|
* @returns Response from the payment
|
|
445
447
|
*
|
|
446
448
|
* @example
|
|
@@ -448,8 +450,19 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
|
|
|
448
450
|
* const response = await makePayment('/api/endpoint', networkType);
|
|
449
451
|
* const data = await response.json();
|
|
450
452
|
* ```
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```tsx
|
|
456
|
+
* // With additional parameters
|
|
457
|
+
* const response = await makePayment(
|
|
458
|
+
* '/api/endpoint',
|
|
459
|
+
* networkType,
|
|
460
|
+
* merchantId,
|
|
461
|
+
* { userId: '123', customField: 'value' }
|
|
462
|
+
* );
|
|
463
|
+
* ```
|
|
451
464
|
*/
|
|
452
|
-
declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string): Promise<Response>;
|
|
465
|
+
declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>): Promise<Response>;
|
|
453
466
|
|
|
454
467
|
/**
|
|
455
468
|
* Network utilities
|
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
|
|
@@ -441,6 +442,7 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
|
|
|
441
442
|
* @param endpoint - API endpoint
|
|
442
443
|
* @param networkType - Network type (from useWallet)
|
|
443
444
|
* @param merchantId - @see our website to apply
|
|
445
|
+
* @param additionalParams - Optional additional parameters to send with the request (default: {})
|
|
444
446
|
* @returns Response from the payment
|
|
445
447
|
*
|
|
446
448
|
* @example
|
|
@@ -448,8 +450,19 @@ declare function getWalletDisplayName(networkType: NetworkType): string;
|
|
|
448
450
|
* const response = await makePayment('/api/endpoint', networkType);
|
|
449
451
|
* const data = await response.json();
|
|
450
452
|
* ```
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```tsx
|
|
456
|
+
* // With additional parameters
|
|
457
|
+
* const response = await makePayment(
|
|
458
|
+
* '/api/endpoint',
|
|
459
|
+
* networkType,
|
|
460
|
+
* merchantId,
|
|
461
|
+
* { userId: '123', customField: 'value' }
|
|
462
|
+
* );
|
|
463
|
+
* ```
|
|
451
464
|
*/
|
|
452
|
-
declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string): Promise<Response>;
|
|
465
|
+
declare function makePayment(networkType: NetworkType, merchantId: string, endpoint?: string, additionalParams?: Record<string, any>): Promise<Response>;
|
|
453
466
|
|
|
454
467
|
/**
|
|
455
468
|
* Network utilities
|