@provex/react 1.2.3
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 +441 -0
- package/dist/index.cjs +2756 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1857 -0
- package/dist/index.d.ts +1857 -0
- package/dist/index.js +2722 -0
- package/dist/index.js.map +1 -0
- package/dist/styles/default.css +325 -0
- package/package.json +63 -0
- package/src/index.ts +115 -0
package/README.md
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# @provex/react
|
|
2
|
+
|
|
3
|
+
Portable React buy-flow component and hooks for the Provex protocol. Framework-agnostic (no Chakra, no styled-components) — works in any React app.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @provex/react @provex/indexer-client react viem
|
|
9
|
+
# or
|
|
10
|
+
yarn add @provex/react @provex/indexer-client react viem
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer Dependencies
|
|
14
|
+
|
|
15
|
+
| Package | Version |
|
|
16
|
+
|---------|---------|
|
|
17
|
+
| `react` | `^18.0.0` |
|
|
18
|
+
| `viem` | `^2.0.0` |
|
|
19
|
+
| `wagmi` | `^2.0.0` (optional — only needed for `useWagmiWallet`) |
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Wrap your app with ProvexProvider
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { ProvexProvider } from '@provex/react'
|
|
27
|
+
import { createPonderAdapter } from '@provex/indexer-client'
|
|
28
|
+
import { pulsechain } from 'viem/chains'
|
|
29
|
+
|
|
30
|
+
const indexer = createPonderAdapter()
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
return (
|
|
34
|
+
<ProvexProvider
|
|
35
|
+
config={{
|
|
36
|
+
apiUrl: 'https://app.provex.com',
|
|
37
|
+
chain: pulsechain, // viem Chain object
|
|
38
|
+
}}
|
|
39
|
+
indexer={indexer}
|
|
40
|
+
>
|
|
41
|
+
<YourApp />
|
|
42
|
+
</ProvexProvider>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Add the buy widget
|
|
48
|
+
|
|
49
|
+
**With wagmi (easiest):**
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { ProvexBuyWagmi } from '@provex/react'
|
|
53
|
+
import '@provex/react/styles'
|
|
54
|
+
|
|
55
|
+
function BuyPage() {
|
|
56
|
+
return (
|
|
57
|
+
<ProvexBuyWagmi
|
|
58
|
+
onIntentSignaled={(hash, chainId) => console.log('Order placed:', hash)}
|
|
59
|
+
onComplete={(hash, chainId) => console.log('Purchase complete:', hash)}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`ProvexBuyWagmi` reads the connected wallet from wagmi context automatically. Your app just needs `WagmiProvider` and `ProvexProvider` above it.
|
|
66
|
+
|
|
67
|
+
**With any wallet:**
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { ProvexBuy } from '@provex/react'
|
|
71
|
+
import '@provex/react/styles'
|
|
72
|
+
|
|
73
|
+
function BuyPage() {
|
|
74
|
+
const wallet = {
|
|
75
|
+
address: connectedAddress,
|
|
76
|
+
sendTransaction: async (tx) => {
|
|
77
|
+
// Your wallet's sendTransaction implementation
|
|
78
|
+
return txHash
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<ProvexBuy
|
|
84
|
+
wallet={wallet}
|
|
85
|
+
onComplete={(hash, chainId) => console.log('Done!', hash)}
|
|
86
|
+
/>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Three Layers
|
|
92
|
+
|
|
93
|
+
Use whichever layer matches your needs:
|
|
94
|
+
|
|
95
|
+
| Layer | Export | Use case |
|
|
96
|
+
|-------|--------|----------|
|
|
97
|
+
| 3 | `<ProvexBuy>` / `<ProvexBuyWagmi>` | Drop-in widget, zero UI code |
|
|
98
|
+
| 2 | `<ProvexBuyProvider>` + phase components | Custom layout, same state machine |
|
|
99
|
+
| 1 | `useProvexBuy()` | Fully custom UI, just the state machine |
|
|
100
|
+
|
|
101
|
+
### Layer 2 — Custom layout
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import {
|
|
105
|
+
ProvexBuyProvider,
|
|
106
|
+
BrowsePhase,
|
|
107
|
+
CommittedPhase,
|
|
108
|
+
ProvingPhase,
|
|
109
|
+
CompletePhase,
|
|
110
|
+
} from '@provex/react'
|
|
111
|
+
|
|
112
|
+
function CustomBuy({ wallet }) {
|
|
113
|
+
return (
|
|
114
|
+
<ProvexBuyProvider wallet={wallet} onComplete={handleDone}>
|
|
115
|
+
<div className="my-layout">
|
|
116
|
+
<BrowsePhase />
|
|
117
|
+
<CommittedPhase />
|
|
118
|
+
<ProvingPhase />
|
|
119
|
+
<CompletePhase />
|
|
120
|
+
</div>
|
|
121
|
+
</ProvexBuyProvider>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Layer 1 — Headless hook
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { useProvexBuy } from '@provex/react'
|
|
130
|
+
|
|
131
|
+
function CustomBuy({ wallet }) {
|
|
132
|
+
const {
|
|
133
|
+
phase,
|
|
134
|
+
amount, setAmount,
|
|
135
|
+
deposits, selectedDeposit,
|
|
136
|
+
rate, rateDisplay,
|
|
137
|
+
canSubmit, validationMessage,
|
|
138
|
+
submitOrder, confirmPayment, reset,
|
|
139
|
+
} = useProvexBuy({ wallet })
|
|
140
|
+
|
|
141
|
+
// Render your own UI using the state machine
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## ProveXClient (Framework-Agnostic)
|
|
146
|
+
|
|
147
|
+
For Node.js, serverless, or non-React apps, use the core client directly:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { createProveXClient } from '@provex/react'
|
|
151
|
+
import { pulsechain } from 'viem/chains'
|
|
152
|
+
|
|
153
|
+
const client = createProveXClient({
|
|
154
|
+
chain: pulsechain,
|
|
155
|
+
wallet: myWalletAdapter,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Create a deposit
|
|
159
|
+
const { hash } = await client.createDeposit({
|
|
160
|
+
token: USDC_ADDRESS,
|
|
161
|
+
amount: 1000_000000n,
|
|
162
|
+
paymentMethods: [
|
|
163
|
+
{ provider: 'venmo', payeeId: '@myvenmo', currencies: [{ code: 'USD', minRate: 0n }] },
|
|
164
|
+
],
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Signal intent (buy side)
|
|
168
|
+
const { intentHash } = await client.signalIntent({
|
|
169
|
+
deposit: { escrow: '0x...', localId: 1n },
|
|
170
|
+
paymentMethod: paymentMethodHash,
|
|
171
|
+
tokenAmount: 100_000000n,
|
|
172
|
+
toAddress: buyerAddress,
|
|
173
|
+
fiatCurrencyCode: currencyHash,
|
|
174
|
+
conversionRate: rate,
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
// Prepare-only mode (for smart accounts, relayers, multisigs)
|
|
178
|
+
const prepared = await client.addFunds.prepare({ depositId: 1n, amount: 500_000000n })
|
|
179
|
+
// → { to, data, value, chainId } — hand to Safe SDK, Privy, etc.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Hooks API
|
|
183
|
+
|
|
184
|
+
### useDeposits
|
|
185
|
+
|
|
186
|
+
Fetch available deposits matching a payment method and token.
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
import { useDeposits, getRate } from '@provex/react'
|
|
190
|
+
|
|
191
|
+
const { deposits, isLoading, getMatchableDeposits } = useDeposits({
|
|
192
|
+
token: usdcToken,
|
|
193
|
+
paymentMethod: 'venmo',
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const matches = getMatchableDeposits('100') // $100
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### useSignalIntent
|
|
200
|
+
|
|
201
|
+
Signal intent to buy tokens (lock USDC in escrow).
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { useSignalIntent } from '@provex/react'
|
|
205
|
+
|
|
206
|
+
const { startOrder, status, message, isLoading } = useSignalIntent({
|
|
207
|
+
wallet,
|
|
208
|
+
chainId: 369,
|
|
209
|
+
deposit: selectedDeposit,
|
|
210
|
+
onSuccess: (intentHash) => navigate(`/verify/${intentHash}`),
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### useReputation
|
|
215
|
+
|
|
216
|
+
Fetch the connected user's reputation tier and cooldown status.
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { useReputation, getTierDisplayInfo } from '@provex/react'
|
|
220
|
+
|
|
221
|
+
const { reputation, isLoading } = useReputation({
|
|
222
|
+
address: walletAddress,
|
|
223
|
+
chainId: 369,
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
const tierInfo = getTierDisplayInfo(reputation.tier)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### useReputationLimits
|
|
230
|
+
|
|
231
|
+
Calculate trading limits based on reputation and payment method.
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
import { useReputationLimits } from '@provex/react'
|
|
235
|
+
|
|
236
|
+
const { effectiveCap, isOnCooldown, cooldownRemaining } = useReputationLimits({
|
|
237
|
+
chainId: 369,
|
|
238
|
+
selectedPaymentMethod: 'venmo',
|
|
239
|
+
tier: reputation.tier,
|
|
240
|
+
amountInInt: parseUnits('100', { decimals: 2 }),
|
|
241
|
+
})
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### useProtocolFees
|
|
245
|
+
|
|
246
|
+
Read protocol fees from the on-chain Orchestrator contract.
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { useProtocolFees } from '@provex/react'
|
|
250
|
+
|
|
251
|
+
const { feeInfo, isLoading } = useProtocolFees({
|
|
252
|
+
chainId: 8453,
|
|
253
|
+
escrowAddress: '0x...',
|
|
254
|
+
})
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### usePayeeDetails
|
|
258
|
+
|
|
259
|
+
Fetch intent details and payee information for the verification flow.
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
import { usePayeeDetails } from '@provex/react'
|
|
263
|
+
|
|
264
|
+
const { intent, intentStatus, payeeDetails, isFetching } = usePayeeDetails({
|
|
265
|
+
intentHash: '0xabc...',
|
|
266
|
+
chainId: 369,
|
|
267
|
+
})
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### useWagmiWallet
|
|
271
|
+
|
|
272
|
+
Bridge wagmi's wallet to the `WalletAdapter` interface.
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
import { useWagmiWallet } from '@provex/react'
|
|
276
|
+
|
|
277
|
+
const wallet = useWagmiWallet()
|
|
278
|
+
// Returns WalletAdapter | null (null when disconnected)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## WalletAdapter Interface
|
|
282
|
+
|
|
283
|
+
The `WalletAdapter` decouples @provex/react from any specific wallet SDK.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
interface WalletAdapter {
|
|
287
|
+
address?: `0x${string}`
|
|
288
|
+
sendTransaction(tx: {
|
|
289
|
+
to: `0x${string}`
|
|
290
|
+
data: `0x${string}`
|
|
291
|
+
value?: bigint
|
|
292
|
+
chainId: number
|
|
293
|
+
maxFeePerGas?: bigint
|
|
294
|
+
maxPriorityFeePerGas?: bigint
|
|
295
|
+
}): Promise<`0x${string}`>
|
|
296
|
+
readContract?(params: {
|
|
297
|
+
address: `0x${string}`
|
|
298
|
+
abi: readonly unknown[]
|
|
299
|
+
functionName: string
|
|
300
|
+
args?: readonly unknown[]
|
|
301
|
+
chainId?: number
|
|
302
|
+
}): Promise<unknown>
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Only `sendTransaction` is required. `readContract` is optional — the client falls back to public RPC.
|
|
307
|
+
|
|
308
|
+
## IndexerAdapter
|
|
309
|
+
|
|
310
|
+
The `IndexerAdapter` decouples data fetching from any specific indexer backend. Use `createPonderAdapter()` from `@provex/indexer-client` for the standard Provex setup, or implement your own against The Graph, a REST API, or direct RPC.
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { createPonderAdapter } from '@provex/indexer-client'
|
|
314
|
+
|
|
315
|
+
const indexer = createPonderAdapter()
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Styling
|
|
319
|
+
|
|
320
|
+
### Default Stylesheet
|
|
321
|
+
|
|
322
|
+
Import the built-in styles for a functional baseline:
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
import '@provex/react/styles'
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### CSS Custom Properties
|
|
329
|
+
|
|
330
|
+
Override any CSS variable on the `[data-provex-root]` selector:
|
|
331
|
+
|
|
332
|
+
```css
|
|
333
|
+
[data-provex-root] {
|
|
334
|
+
--provex-color-bg: #0f0f23;
|
|
335
|
+
--provex-color-primary: #00d4aa;
|
|
336
|
+
--provex-color-text: #ffffff;
|
|
337
|
+
--provex-border-radius: 12px;
|
|
338
|
+
--provex-max-width: 480px;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Available variables:
|
|
343
|
+
|
|
344
|
+
| Variable | Default (light) | Description |
|
|
345
|
+
|----------|----------------|-------------|
|
|
346
|
+
| `--provex-color-bg` | `#ffffff` | Background color |
|
|
347
|
+
| `--provex-color-surface` | `#f8f9fa` | Surface/card color |
|
|
348
|
+
| `--provex-color-border` | `#e2e8f0` | Border color |
|
|
349
|
+
| `--provex-color-text` | `#1a202c` | Primary text color |
|
|
350
|
+
| `--provex-color-text-secondary` | `#718096` | Secondary text |
|
|
351
|
+
| `--provex-color-primary` | `#3b82f6` | Primary accent |
|
|
352
|
+
| `--provex-color-primary-hover` | `#2563eb` | Hover state |
|
|
353
|
+
| `--provex-color-success` | `#10b981` | Success color |
|
|
354
|
+
| `--provex-color-error` | `#ef4444` | Error color |
|
|
355
|
+
| `--provex-space-*` | various | Spacing (xs, sm, md, lg, xl) |
|
|
356
|
+
| `--provex-font-family` | system stack | Font family |
|
|
357
|
+
| `--provex-font-size-*` | various | Font sizes (sm, md, lg, xl) |
|
|
358
|
+
| `--provex-border-radius` | `0.5rem` | Border radius |
|
|
359
|
+
| `--provex-max-width` | `420px` | Max component width |
|
|
360
|
+
|
|
361
|
+
### Theme Prop
|
|
362
|
+
|
|
363
|
+
Pass theme overrides directly to the widget:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
<ProvexBuy
|
|
367
|
+
wallet={wallet}
|
|
368
|
+
theme={{
|
|
369
|
+
accent: '#00d4aa',
|
|
370
|
+
background: '#0f0f23',
|
|
371
|
+
text: '#ffffff',
|
|
372
|
+
radius: '12px',
|
|
373
|
+
}}
|
|
374
|
+
/>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### className Prop
|
|
378
|
+
|
|
379
|
+
Pass a `className` to the root element for framework-specific styling:
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
<ProvexBuy wallet={wallet} className="my-custom-buy-widget" />
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Data Attributes
|
|
386
|
+
|
|
387
|
+
All elements use `data-provex-*` attributes for CSS targeting:
|
|
388
|
+
|
|
389
|
+
```css
|
|
390
|
+
[data-provex-button="buy"] { ... }
|
|
391
|
+
[data-provex-input="amount"] { ... }
|
|
392
|
+
[data-provex-phase="browse"] { ... }
|
|
393
|
+
[data-provex-phase="committed"] { ... }
|
|
394
|
+
[data-provex-phase="complete"] { ... }
|
|
395
|
+
[data-provex-message="error"] { ... }
|
|
396
|
+
[data-provex-message="validation"] { ... }
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Dark Mode
|
|
400
|
+
|
|
401
|
+
The default stylesheet responds to `prefers-color-scheme: dark` automatically. To force a theme, override the CSS variables.
|
|
402
|
+
|
|
403
|
+
## Configuration
|
|
404
|
+
|
|
405
|
+
### ProvexConfig
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
interface ProvexConfig {
|
|
409
|
+
apiUrl: string // Provex backend API URL
|
|
410
|
+
chain: Chain // viem Chain object (from viem/chains)
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### ProvexProviderProps
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
interface ProvexProviderProps {
|
|
418
|
+
config: ProvexConfig
|
|
419
|
+
indexer: IndexerAdapter // Data source (use createPonderAdapter())
|
|
420
|
+
queryClient?: QueryClient // Optional external React Query client
|
|
421
|
+
children: React.ReactNode
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### BuyProps
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
interface BuyProps {
|
|
429
|
+
wallet: WalletAdapter
|
|
430
|
+
onIntentSignaled?: (intentHash: string, chainId: number) => void
|
|
431
|
+
onComplete?: (intentHash: string, chainId: number) => void
|
|
432
|
+
paymentMethods?: ProviderKey[]
|
|
433
|
+
className?: string
|
|
434
|
+
style?: React.CSSProperties
|
|
435
|
+
theme?: ProvexTheme
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## License
|
|
440
|
+
|
|
441
|
+
Private — Provex Protocol
|