@volr/react-ui 0.1.93 → 0.1.95

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,6 +1,6 @@
1
1
  # @volr/react-ui
2
2
 
3
- Pre-built UI components for Volr, built on top of `@volr/react` and `@volr/sdk-core`, with minimal, modern design.
3
+ Pre-built UI components for Volr Payment Gateway, built on top of `@volr/react` and `@volr/sdk-core`, with minimal, modern design.
4
4
 
5
5
  ## Installation
6
6
 
@@ -23,7 +23,7 @@ const volrConfig: VolrUIConfig = {
23
23
  projectApiKey: 'your-project-api-key',
24
24
  appName: 'My App',
25
25
  accentColor: '#3b82f6',
26
- enabledLoginMethods: ['email', 'social', 'siwe'],
26
+ enabledLoginMethods: ['email', 'social'],
27
27
  socialProviders: ['google', 'twitter'],
28
28
  };
29
29
 
@@ -36,12 +36,154 @@ function App() {
36
36
  }
37
37
  ```
38
38
 
39
- ### 2. Use useVolrModal Hook
39
+ ---
40
+
41
+ ## Payment Integration
42
+
43
+ Volr provides a simple, Stripe-like payment experience for Web3 applications.
44
+
45
+ ### Basic Payment
46
+
47
+ ```tsx
48
+ import { useVolrPay } from '@volr/react-ui';
49
+ // Or from @volr/react if not using UI components
50
+
51
+ function CheckoutButton() {
52
+ const { pay } = useVolrPay();
53
+
54
+ const handleCheckout = async () => {
55
+ const payment = await pay({
56
+ amount: 9.99,
57
+ item: {
58
+ name: 'Premium Plan',
59
+ description: 'Monthly subscription',
60
+ },
61
+ handlers: {
62
+ onSuccess: (result) => {
63
+ console.log('Payment confirmed!', result.txHash);
64
+ },
65
+ onError: (error) => {
66
+ console.error('Payment failed:', error.message);
67
+ },
68
+ },
69
+ });
70
+
71
+ // Optionally wait for confirmation
72
+ const result = await payment.wait();
73
+ };
74
+
75
+ return <button onClick={handleCheckout}>Subscribe $9.99</button>;
76
+ }
77
+ ```
78
+
79
+ ### Payment with Reference ID
80
+
81
+ Track payments with your own order ID:
82
+
83
+ ```tsx
84
+ const payment = await pay({
85
+ amount: 29.99,
86
+ item: { name: 'Pro License' },
87
+ referenceId: 'order_12345', // Your order ID
88
+ metadata: {
89
+ userId: 'user_abc',
90
+ plan: 'pro',
91
+ },
92
+ });
93
+ ```
94
+
95
+ ### Idempotent Payments
96
+
97
+ Prevent duplicate payments with idempotency key:
98
+
99
+ ```tsx
100
+ const payment = await pay({
101
+ amount: 49.99,
102
+ item: { name: 'Enterprise License' },
103
+ idempotencyKey: `order_${orderId}_${userId}`, // Unique per payment intent
104
+ });
105
+ ```
106
+
107
+ ### Check Payment Status
108
+
109
+ ```tsx
110
+ import { useVolrPay } from '@volr/react-ui';
111
+
112
+ function OrderStatus({ paymentId }: { paymentId: string }) {
113
+ const { checkPayment } = useVolrPay();
114
+ const [status, setStatus] = useState<string>('loading');
115
+
116
+ useEffect(() => {
117
+ checkPayment(paymentId).then((result) => {
118
+ setStatus(result.status); // 'CONFIRMED' | 'PENDING' | 'FAILED' | ...
119
+ });
120
+ }, [paymentId]);
121
+
122
+ return <div>Payment Status: {status}</div>;
123
+ }
124
+ ```
125
+
126
+ ### Payment History
127
+
128
+ ```tsx
129
+ import { useVolrPay } from '@volr/react-ui';
130
+
131
+ function PaymentHistory() {
132
+ const { getPaymentHistory } = useVolrPay();
133
+ const [payments, setPayments] = useState([]);
134
+
135
+ useEffect(() => {
136
+ getPaymentHistory({ take: 10 }).then((result) => {
137
+ setPayments(result.payments);
138
+ });
139
+ }, []);
140
+
141
+ return (
142
+ <ul>
143
+ {payments.map((p) => (
144
+ <li key={p.id}>
145
+ {p.itemName} - {p.amount} {p.token.symbol} - {p.status}
146
+ </li>
147
+ ))}
148
+ </ul>
149
+ );
150
+ }
151
+ ```
152
+
153
+ ### PayOptions Reference
154
+
155
+ | Property | Type | Required | Description |
156
+ |----------|------|----------|-------------|
157
+ | `amount` | `number` | ✅ | Amount in token units (before decimals) |
158
+ | `item.name` | `string` | ❌ | Item name displayed in modal |
159
+ | `item.description` | `string` | ❌ | Item description |
160
+ | `item.image` | `string` | ❌ | Item image URL (falls back to project logo) |
161
+ | `referenceId` | `string` | ❌ | Your order/reference ID |
162
+ | `metadata` | `Record<string, string>` | ❌ | Custom metadata (max 50 keys) |
163
+ | `idempotencyKey` | `string` | ❌ | Unique key to prevent duplicates |
164
+ | `expiresInSec` | `number` | ❌ | Expiration time (default: 900 = 15 min) |
165
+ | `handlers.onCreated` | `(payment) => void` | ❌ | Called when payment is created |
166
+ | `handlers.onProcessing` | `(payment) => void` | ❌ | Called when transaction is broadcasted |
167
+ | `handlers.onSuccess` | `(result) => void` | ❌ | Called when payment is confirmed |
168
+ | `handlers.onError` | `(error) => void` | ❌ | Called on error |
169
+ | `handlers.onCancel` | `() => void` | ❌ | Called when user cancels |
170
+
171
+ ### Payment Modal Flow
172
+
173
+ 1. **Payment Info** - Shows item details, amount, and user's balance
174
+ 2. **Processing** - Passkey signing → Transaction broadcast → On-chain confirmation
175
+ 3. **Result** - Success or failure with retry option
176
+
177
+ ---
178
+
179
+ ## Account & Authentication
180
+
181
+ ### Login / Account Modal
40
182
 
41
183
  ```tsx
42
184
  import { useVolrModal, useVolr } from '@volr/react-ui';
43
185
 
44
- function Example() {
186
+ function AuthButton() {
45
187
  const { open } = useVolrModal();
46
188
  const { evmAddress, isLoggedIn, logout } = useVolr();
47
189
 
@@ -50,12 +192,7 @@ function Example() {
50
192
  {isLoggedIn ? (
51
193
  <>
52
194
  <p>Wallet: {evmAddress}</p>
53
- <button onClick={() => open({ mode: 'account' })}>
54
- My Account
55
- </button>
56
- <button onClick={() => open({ mode: 'deposit' })}>
57
- Deposit
58
- </button>
195
+ <button onClick={() => open({ mode: 'account' })}>My Account</button>
59
196
  <button onClick={logout}>Logout</button>
60
197
  </>
61
198
  ) : (
@@ -66,84 +203,118 @@ function Example() {
66
203
  }
67
204
  ```
68
205
 
69
- ### 3. Direct Asset Deposit
206
+ ### Deposit Modal
70
207
 
71
- Open deposit modal with a specific asset pre-selected:
208
+ Open deposit modal to let users top up their wallet:
72
209
 
73
210
  ```tsx
211
+ import { useVolrModal } from '@volr/react-ui';
212
+
74
213
  function DepositButton() {
75
214
  const { open } = useVolrModal();
76
215
 
77
- const handleDeposit = () => {
78
- open({
79
- mode: 'deposit',
80
- asset: { chainId: 8453, symbol: 'USDC' },
81
- });
82
- };
83
-
84
- return <button onClick={handleDeposit}>Deposit USDC</button>;
216
+ return (
217
+ <button onClick={() => open({ mode: 'deposit' })}>
218
+ Deposit
219
+ </button>
220
+ );
85
221
  }
222
+
223
+ // With specific asset pre-selected
224
+ <button onClick={() => open({ mode: 'deposit', asset: { chainId: 8453, symbol: 'USDC' } })}>
225
+ Deposit USDC
226
+ </button>
86
227
  ```
87
228
 
229
+ ---
230
+
88
231
  ## Configuration
89
232
 
90
233
  ### VolrUIProvider Props
91
234
 
92
235
  | Prop | Type | Default | Description |
93
236
  |------|------|---------|-------------|
94
- | `config` | `VolrUIConfig` | **Required** | Volr UI configuration (extends VolrConfig) |
95
237
  | `config.defaultChainId` | `number` | **Required** | Default chain ID |
96
238
  | `config.projectApiKey` | `string` | **Required** | Project API key |
97
239
  | `config.appName` | `string` | **Required** | Application name |
98
- | `config.accentColor` | `string` | `'#303030'` | Accent color for buttons and links |
99
- | `config.enabledLoginMethods` | `('email' \| 'social' \| 'siwe')[]` | `['email', 'social', 'siwe']` | Enabled login methods |
100
- | `config.socialProviders` | `('google' \| 'twitter' \| 'apple')[]` | `['google', 'twitter', 'apple']` | Enabled social providers |
240
+ | `config.accentColor` | `string` | `'#303030'` | Accent color for buttons |
241
+ | `config.enabledLoginMethods` | `('email' \| 'social' \| 'siwe')[]` | `['email', 'social', 'siwe']` | Login methods |
242
+ | `config.socialProviders` | `('google' \| 'twitter')[]` | `['google', 'twitter']` | Social providers |
101
243
  | `config.keyStorageType` | `'passkey' \| 'mpc'` | `'passkey'` | Key storage type |
102
- | `config.branding` | `BrandingConfig` | `undefined` | Custom branding configuration |
103
- | `config.providerPolicy` | `object` | `{ enforceOnFirstLogin: true }` | Provider policy settings |
244
+ | `config.branding` | `BrandingConfig` | `undefined` | Custom branding |
104
245
 
105
- > **Note:** Deposit assets are now configured via the Volr Dashboard, not in the SDK config.
246
+ > **Note:** Payment token and deposit assets are configured via the Volr Dashboard.
247
+
248
+ ---
106
249
 
107
250
  ## API Reference
108
251
 
109
- ### useVolrModal
252
+ ### useVolrPay
110
253
 
111
- Hook for controlling modals.
254
+ Hook for payment operations with PaymentModal integration.
112
255
 
113
256
  ```tsx
114
- import { useVolrModal } from '@volr/react-ui';
257
+ import { useVolrPay } from '@volr/react-ui';
115
258
 
116
- const { isOpen, mode, asset, open, close } = useVolrModal();
259
+ const {
260
+ pay, // (options: PayOptions) => Promise<PaymentHandle>
261
+ checkPayment, // (id: string) => Promise<PaymentResult>
262
+ getPaymentHistory, // (options?) => Promise<{ payments, total }>
263
+ isPaymentInProgress // boolean
264
+ } = useVolrPay();
265
+
266
+ // PaymentHandle returned from pay()
267
+ interface PaymentHandle {
268
+ id: string;
269
+ status: PaymentStatus;
270
+ wait: () => Promise<PaymentResult>; // Wait for completion
271
+ cancel: () => Promise<void>; // Cancel (PENDING only)
272
+ }
273
+ ```
117
274
 
118
- // Open account modal (default) - shows login if not logged in, account info if logged in
119
- open();
120
- open({ mode: 'account' });
275
+ ### useVolrPaymentApi (Advanced)
121
276
 
122
- // Open deposit modal
123
- open({ mode: 'deposit' });
277
+ Headless payment API for advanced use cases (no UI).
124
278
 
125
- // Open deposit with specific asset
126
- open({ mode: 'deposit', asset: { chainId: 8453, symbol: 'ETH' } });
279
+ ```tsx
280
+ import { useVolrPaymentApi } from '@volr/react-ui';
127
281
 
128
- // Close modal
129
- close();
282
+ const {
283
+ createPayment, // (options: PayOptions) => Promise<PaymentResult>
284
+ checkPayment, // (id: string) => Promise<PaymentResult>
285
+ getPaymentHistory, // (options?) => Promise<{ payments, total }>
286
+ updatePaymentToProcessing,// (id, txId) => Promise<PaymentResult>
287
+ cancelPayment, // (id) => Promise<PaymentResult>
288
+ pollPaymentStatus, // (id) => Promise<PaymentResult>
289
+ isLoading, // boolean
290
+ } = useVolrPaymentApi();
130
291
  ```
131
292
 
132
- | Property | Type | Description |
133
- |----------|------|-------------|
134
- | `isOpen` | `boolean` | Whether modal is open |
135
- | `mode` | `'account' \| 'deposit'` | Current modal mode |
136
- | `asset` | `{ chainId: number; symbol: string } \| null` | Selected asset for deposit |
137
- | `open` | `(options?) => void` | Open modal with optional mode/asset |
138
- | `close` | `() => void` | Close modal |
293
+ ### useVolrModal
294
+
295
+ Hook for controlling modals.
296
+
297
+ ```tsx
298
+ import { useVolrModal } from '@volr/react-ui';
299
+
300
+ const { isOpen, mode, open, close } = useVolrModal();
301
+
302
+ open(); // Account modal (login or account info)
303
+ open({ mode: 'account' }); // Same as above
304
+ open({ mode: 'deposit' }); // Deposit modal
305
+ open({ mode: 'deposit', asset: {...} }); // Deposit with specific asset
306
+ open({ mode: 'payment', payment: {...} }); // Payment modal (internal)
307
+ close();
308
+ ```
139
309
 
140
310
  ### useVolr
141
311
 
312
+ Hook for wallet and user state.
313
+
142
314
  ```tsx
143
315
  import { useVolr } from '@volr/react-ui';
144
316
 
145
317
  const {
146
- evm, // (chainId: number) => EvmClient
147
318
  evmAddress, // `0x${string}` | undefined
148
319
  email, // string | undefined
149
320
  isLoggedIn, // boolean
@@ -154,156 +325,94 @@ const {
154
325
  } = useVolr();
155
326
  ```
156
327
 
157
- ### EvmClient
158
-
159
- Returned by `evm(chainId)`.
328
+ ---
160
329
 
161
- ```tsx
162
- const client = evm(8453);
163
-
164
- // Read contract
165
- const balance = await client.readContract({
166
- address: tokenAddress,
167
- abi: erc20Abi,
168
- functionName: 'balanceOf',
169
- args: [userAddress],
170
- });
330
+ ## Advanced: Web3 Transactions
171
331
 
172
- // Send single transaction
173
- const result = await client.sendTransaction({
174
- to: '0x...',
175
- data: '0x...',
176
- value: 0n,
177
- });
332
+ For advanced use cases beyond payments, you can send arbitrary transactions.
178
333
 
179
- // Send batch (with ABI)
180
- const result = await client.sendBatch([
181
- {
182
- target: tokenAddress,
183
- abi: erc20Abi,
184
- functionName: 'transfer',
185
- args: [recipient, amount],
186
- gasLimit: 100000n,
187
- },
188
- ]);
189
- ```
334
+ ### EvmClient
190
335
 
191
- ## Modal Modes
336
+ ```tsx
337
+ import { useVolr } from '@volr/react-ui';
192
338
 
193
- ### Account Mode (`mode: 'account'`)
339
+ function SendToken() {
340
+ const { evm, evmAddress } = useVolr();
194
341
 
195
- - **Not logged in**: Shows login screen (email, social, SIWE)
196
- - **Logged in**: Shows account info (wallet address, email) and logout button
342
+ const handleSend = async () => {
343
+ const client = evm(8453); // Base chain
197
344
 
198
- ### Deposit Mode (`mode: 'deposit'`)
345
+ // Read contract
346
+ const balance = await client.readContract({
347
+ address: tokenAddress,
348
+ abi: erc20Abi,
349
+ functionName: 'balanceOf',
350
+ args: [evmAddress],
351
+ });
199
352
 
200
- - **Not logged in**: Shows login first, then deposit screen
201
- - **Logged in**: Shows deposit QR code and address
202
- - **With asset**: Pre-selects the specified asset
353
+ // Send transaction
354
+ const result = await client.sendTransaction({
355
+ to: '0x...',
356
+ data: '0x...',
357
+ value: 0n,
358
+ });
203
359
 
204
- ## Features
360
+ // Send batch
361
+ const result = await client.sendBatch([
362
+ {
363
+ target: tokenAddress,
364
+ abi: erc20Abi,
365
+ functionName: 'transfer',
366
+ args: [recipient, amount],
367
+ gasLimit: 100000n,
368
+ },
369
+ ]);
370
+ };
371
+ }
372
+ ```
205
373
 
206
- - **Email Login**: Email verification with 6-digit code
207
- - **Social Login**: Google, Twitter, Apple OAuth
208
- - **SIWE**: Sign-In with Ethereum (wallet login)
209
- - **Passkey Wallet**: Automatic passkey-based wallet creation
210
- - **Deposit**: QR code-based crypto deposits
211
- - **Minimal Design**: Clean, modern UI
212
- - **Customizable**: Accent color and enabled methods
213
- - **Type-Safe**: Full TypeScript support
374
+ ---
214
375
 
215
- ## Login Flow
376
+ ## Login Flows
216
377
 
217
378
  ### Email Login
218
- 1. User clicks "Email Login"
219
- 2. Enter email address
220
- 3. Receive 6-digit verification code
221
- 4. Enter code
222
- 5. **New users**: Passkey setup
223
- 6. **Existing users**: Success
224
-
225
- ### Social Login (Google, Twitter, Apple)
226
- 1. User clicks social login button
227
- 2. Redirect to OAuth provider
228
- 3. Authorize and return
229
- 4. **New users**: Passkey setup
230
- 5. **Existing users**: Success
231
-
232
- ### Wallet Login (SIWE)
233
- 1. User clicks "Wallet Login"
234
- 2. Connect MetaMask or other wallet
235
- 3. Sign SIWE message
236
- 4. **New users**: Passkey setup
237
- 5. **Existing users**: Success
238
-
239
- ## Examples
240
-
241
- ### Login/Account Button
242
-
243
- ```tsx
244
- import { useVolrModal, useVolr } from '@volr/react-ui';
245
-
246
- function AuthButton() {
247
- const { open } = useVolrModal();
248
- const { isLoggedIn, evmAddress } = useVolr();
249
-
250
- if (isLoggedIn) {
251
- return (
252
- <button onClick={() => open({ mode: 'account' })}>
253
- {evmAddress?.slice(0, 6)}...{evmAddress?.slice(-4)}
254
- </button>
255
- );
256
- }
257
-
258
- return <button onClick={() => open()}>Connect</button>;
259
- }
260
- ```
379
+ 1. Enter email Receive 6-digit code → Enter code → Passkey setup (new users)
261
380
 
262
- ### Deposit Button
381
+ ### Social Login (Google, Twitter)
382
+ 1. Click social button → OAuth redirect → Authorize → Passkey setup (new users)
263
383
 
264
- ```tsx
265
- import { useVolrModal, useVolr } from '@volr/react-ui';
384
+ ### Wallet Login (SIWE)
385
+ 1. Click Wallet Login Connect wallet → Sign message → Passkey setup (new users)
266
386
 
267
- function DepositButton() {
268
- const { open } = useVolrModal();
269
- const { isLoggedIn } = useVolr();
387
+ ---
270
388
 
271
- return (
272
- <button
273
- onClick={() => open({ mode: 'deposit' })}
274
- disabled={!isLoggedIn}
275
- >
276
- Deposit
277
- </button>
278
- );
279
- }
280
- ```
389
+ ## Examples
281
390
 
282
391
  ### Email Only Config
283
392
 
284
393
  ```tsx
285
394
  const volrConfig: VolrUIConfig = {
286
395
  defaultChainId: 8453,
287
- projectApiKey: 'your-project-api-key',
396
+ projectApiKey: 'your-api-key',
288
397
  appName: 'My App',
289
- accentColor: '#6366f1',
290
398
  enabledLoginMethods: ['email'],
291
399
  };
292
400
  ```
293
401
 
294
- ### Google and Apple Only
402
+ ### Social Only Config
295
403
 
296
404
  ```tsx
297
405
  const volrConfig: VolrUIConfig = {
298
406
  defaultChainId: 8453,
299
- projectApiKey: 'your-project-api-key',
407
+ projectApiKey: 'your-api-key',
300
408
  appName: 'My App',
301
- accentColor: '#8b5cf6',
302
409
  enabledLoginMethods: ['social'],
303
- socialProviders: ['google', 'apple'],
410
+ socialProviders: ['google'],
304
411
  };
305
412
  ```
306
413
 
414
+ ---
415
+
307
416
  ## License
308
417
 
309
418
  MIT