@volr/react-ui 0.1.49 → 0.1.54

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
@@ -62,25 +62,46 @@ function LoginButton() {
62
62
  }
63
63
  ```
64
64
 
65
- ## Styling & Tailwind
66
-
67
- - **No Tailwind dependency for the host app**: `@volr/react-ui` ships with its own compiled CSS.
68
- You do **not** need to install Tailwind or import any extra CSS files in your project.
69
- - **Automatic style injection**: when `VolrUIProvider` is mounted, the SDK injects a single
70
- `<style id="volr-sdk-styles">…</style>` tag into `document.head` using the embedded `VOLR_SDK_CSS`.
71
- - **Scoped and namespaced styles**:
72
- - All selectors are scoped under a root container marked with `data-volr-root="true"`.
73
- - All utility classes are prefixed with `volr:` (e.g. `volr:px-4`, `volr:border-slate-200`).
74
- - The compiled CSS is post-processed so that it only affects elements inside `[data-volr-root]`
75
- and does not leak into the host UI.
76
- - **Safe with any host styling system**:
77
- - Internally we use Tailwind v4, but the shipped CSS is fully self-contained.
78
- - The SDK works the same whether the host uses Tailwind v2/v3/v4, another CSS framework,
79
- or no global CSS system at all.
80
-
81
- If your app applies extremely aggressive global resets (for example `all: unset` on `button`/`input`
82
- at the top level), those rules can still affect the Volr UI. In such cases, consider scoping those
83
- resets so they do not apply under the `[data-volr-root]` subtree.
65
+ ### 3. Use Wallet
66
+
67
+ After login, use `useVolr` to interact with the blockchain.
68
+
69
+ ```tsx
70
+ import { useVolr } from '@volr/react-ui';
71
+
72
+ function Example() {
73
+ const { evm, isLoggedIn, logout } = useVolr();
74
+
75
+ if (!isLoggedIn) {
76
+ return <LoginButton />;
77
+ }
78
+
79
+ const handleTransfer = async () => {
80
+ await evm(8453).sendBatch([
81
+ {
82
+ target: tokenAddress,
83
+ abi: erc20Abi,
84
+ functionName: 'transfer',
85
+ args: [recipient, amount],
86
+ },
87
+ ]);
88
+ };
89
+
90
+ return (
91
+ <div className="flex flex-col gap-4">
92
+ <p className="text-sm text-gray-600">Wallet: {evm.address}</p>
93
+ <div className="flex gap-2">
94
+ <button onClick={handleTransfer} className="bg-blue-500 text-white rounded">
95
+ Transfer
96
+ </button>
97
+ <button onClick={logout} className="bg-gray-200 rounded">
98
+ Logout
99
+ </button>
100
+ </div>
101
+ </div>
102
+ );
103
+ }
104
+ ```
84
105
 
85
106
  ## Configuration
86
107
 
@@ -107,6 +128,74 @@ resets so they do not apply under the `[data-volr-root]` subtree.
107
128
  | `onClose` | `() => void` | **Required** | Close callback |
108
129
  | `onError` | `(error: Error) => void` | `undefined` | Error callback |
109
130
 
131
+ ## API Reference
132
+
133
+ ### useVolr
134
+
135
+ ```tsx
136
+ import { useVolr } from '@volr/react-ui';
137
+
138
+ const {
139
+ evm, // EvmNamespace - chain client factory + address
140
+ email, // string | undefined
141
+ isLoggedIn, // boolean
142
+ signerType, // 'passkey' | 'external_wallet' | 'mpc' | undefined
143
+ logout, // () => Promise<void>
144
+ isLoading, // boolean
145
+ error, // Error | null
146
+ } = useVolr();
147
+
148
+ // Get EVM address
149
+ const address = evm.address;
150
+
151
+ // Get chain client
152
+ const client = evm(8453);
153
+ ```
154
+
155
+ ### EvmClient
156
+
157
+ Returned by `evm(chainId)`.
158
+
159
+ ```tsx
160
+ const client = evm(8453);
161
+
162
+ // Read contract
163
+ const balance = await client.readContract({
164
+ address: tokenAddress,
165
+ abi: erc20Abi,
166
+ functionName: 'balanceOf',
167
+ args: [userAddress],
168
+ });
169
+
170
+ // Send single transaction
171
+ const result = await client.sendTransaction({
172
+ to: '0x...',
173
+ data: '0x...',
174
+ value: 0n,
175
+ });
176
+
177
+ // Send batch (with ABI)
178
+ const result = await client.sendBatch([
179
+ {
180
+ target: tokenAddress,
181
+ abi: erc20Abi,
182
+ functionName: 'transfer',
183
+ args: [recipient, amount],
184
+ gasLimit: 100000n,
185
+ },
186
+ ]);
187
+
188
+ // Send batch (raw calls)
189
+ const result = await client.sendBatch([
190
+ {
191
+ target: '0x...',
192
+ data: '0x...',
193
+ value: 0n,
194
+ gasLimit: 100000n,
195
+ },
196
+ ]);
197
+ ```
198
+
110
199
  ## Features
111
200
 
112
201
  - **Email Login**: Email verification with 6-digit code
@@ -197,15 +286,9 @@ function App() {
197
286
  const [error, setError] = useState<string | null>(null);
198
287
 
199
288
  return (
200
- <>
289
+ <div className="flex flex-col gap-4">
201
290
  {error && (
202
- <div style={{
203
- padding: '12px',
204
- backgroundColor: '#fef2f2',
205
- color: '#991b1b',
206
- borderRadius: '8px',
207
- marginBottom: '16px'
208
- }}>
291
+ <div className="bg-red-50 text-red-800 rounded-lg">
209
292
  {error}
210
293
  </div>
211
294
  )}
@@ -223,75 +306,11 @@ function App() {
223
306
  setTimeout(() => setError(null), 3000);
224
307
  }}
225
308
  />
226
- </>
309
+ </div>
227
310
  );
228
311
  }
229
312
  ```
230
313
 
231
- ## Backend Requirements
232
-
233
- ### Environment Variables
234
-
235
- ```bash
236
- # Google OAuth
237
- GOOGLE_CLIENT_ID=your_google_client_id
238
- GOOGLE_CLIENT_SECRET=your_google_client_secret
239
- GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback
240
-
241
- # Twitter OAuth
242
- TWITTER_CLIENT_ID=your_twitter_client_id
243
- TWITTER_CLIENT_SECRET=your_twitter_client_secret
244
- TWITTER_REDIRECT_URI=http://localhost:3000/auth/twitter/callback
245
-
246
- # Apple OAuth
247
- APPLE_CLIENT_ID=your_apple_client_id
248
- APPLE_REDIRECT_URI=http://localhost:3000/auth/apple/callback
249
-
250
- # Frontend URL (OAuth callback redirect)
251
- FRONTEND_URL=http://localhost:5173
252
-
253
- # API Base URL
254
- API_BASE_URL=http://localhost:3000
255
- ```
256
-
257
- ### Required Endpoints
258
-
259
- **Email Login**
260
- - `POST /auth/email/send` - Send verification code
261
- - `POST /auth/email/verify` - Verify code and login
262
-
263
- **Social Login**
264
- - `GET /auth/google` - Start Google OAuth
265
- - `GET /auth/google/callback` - Google OAuth callback
266
- - `GET /auth/twitter` - Start Twitter OAuth
267
- - `GET /auth/twitter/callback` - Twitter OAuth callback
268
- - `GET /auth/apple` - Start Apple OAuth
269
- - `POST /auth/apple/callback` - Apple OAuth callback
270
-
271
- **SIWE**
272
- - `POST /auth/siwe/nonce` - Generate nonce
273
- - `POST /auth/siwe/verify` - Verify SIWE signature
274
-
275
- **Passkey**
276
- - `POST /blob/presign` - Generate S3 upload URL
277
- - `POST /wallet/provider/register` - Register provider
278
-
279
- ## Troubleshooting
280
-
281
- ### OAuth Redirect Failure
282
- - Verify OAuth Client ID and Secret
283
- - Check Redirect URI matches OAuth app settings
284
- - Verify CORS configuration
285
-
286
- ### SIWE Signature Failure
287
- - Ensure MetaMask or wallet is installed
288
- - Check wallet is connected to correct network
289
-
290
- ### Passkey Creation Failure
291
- - HTTPS or localhost required (HTTP not supported)
292
- - Verify browser supports WebAuthn
293
- - Check biometric authentication is enabled on device
294
-
295
314
  ## License
296
315
 
297
- MIT
316
+ MIT
package/dist/index.cjs CHANGED
@@ -294,7 +294,7 @@ var VolrModalProvider = ({
294
294
  }) => {
295
295
  const [isOpen, setIsOpen] = React5.useState(false);
296
296
  const [mode, setMode] = React5.useState("auth");
297
- const { user } = react.useVolr();
297
+ const { user } = react.useVolrContext();
298
298
  const open = React5.useCallback(() => {
299
299
  setMode(user ? "deposit" : "auth");
300
300
  setIsOpen(true);
@@ -922,7 +922,7 @@ function PasskeyEnrollView({
922
922
  isOpen = true,
923
923
  wrapInModal = true
924
924
  }) {
925
- const { user, logout, setUser } = react.useVolr();
925
+ const { user, logout, setUser } = react.useVolrContext();
926
926
  const { client } = react.useInternalAuth();
927
927
  const { t } = useI18n();
928
928
  const { accentColor } = useVolrUI();
@@ -2364,7 +2364,7 @@ function LoginSuccessScreen({
2364
2364
  ] });
2365
2365
  }
2366
2366
  function SigninModal({ isOpen, onClose, onError }) {
2367
- const { logout, user } = react.useVolr();
2367
+ const { logout, user } = react.useVolrContext();
2368
2368
  const { appName, branding } = useVolrUI();
2369
2369
  const { requestEmailCode, verifyEmailCode, handleSocialLogin } = react.useVolrLogin();
2370
2370
  const [currentScreen, setCurrentScreen] = React5.useState("method-select");
@@ -2974,7 +2974,7 @@ var DepositCompletedToast = ({
2974
2974
  };
2975
2975
  function DepositQRView(props) {
2976
2976
  const { t } = useI18n();
2977
- const { config } = react.useVolr();
2977
+ const { config } = react.useVolrContext();
2978
2978
  const { client } = react.useInternalAuth();
2979
2979
  const [chainName, setChainName] = React5.useState(null);
2980
2980
  const [showOtherTokenModal, setShowOtherTokenModal] = React5.useState(false);
@@ -3107,7 +3107,7 @@ var DepositModal = ({
3107
3107
  open,
3108
3108
  onOpenChange
3109
3109
  }) => {
3110
- const { config, user } = react.useVolr();
3110
+ const { config, user } = react.useVolrContext();
3111
3111
  const supportedAssets = config.deposit?.supportedAssets ?? [];
3112
3112
  const hasAssets = supportedAssets.length > 0;
3113
3113
  const [selectedIdx, setSelectedIdx] = React5.useState(
@@ -3187,7 +3187,7 @@ function OnboardingFlow({
3187
3187
  keyStorageType,
3188
3188
  onComplete
3189
3189
  }) {
3190
- const { logout } = react.useVolr();
3190
+ const { logout } = react.useVolrContext();
3191
3191
  const handleEnrollComplete = () => {
3192
3192
  onComplete();
3193
3193
  };
@@ -3394,7 +3394,7 @@ function OnboardingChecker({
3394
3394
  onShowOnboarding,
3395
3395
  onHideOnboarding
3396
3396
  }) {
3397
- const { user, provider, isLoading } = react.useVolr();
3397
+ const { user, provider, isLoading } = react.useVolrContext();
3398
3398
  const { isOpen: isLoginModalOpen } = useVolrModal();
3399
3399
  React5.useEffect(() => {
3400
3400
  if (isLoading) {
@@ -3521,10 +3521,6 @@ Object.defineProperty(exports, "useVolrLogin", {
3521
3521
  enumerable: true,
3522
3522
  get: function () { return react.useVolrLogin; }
3523
3523
  });
3524
- Object.defineProperty(exports, "useVolrWallet", {
3525
- enumerable: true,
3526
- get: function () { return react.useVolrWallet; }
3527
- });
3528
3524
  exports.I18nContext = I18nContext;
3529
3525
  exports.I18nProvider = I18nProvider;
3530
3526
  exports.MpcConnectView = MpcConnectView;