@capxul/sdk-react 0.1.0-alpha.3 → 0.1.0-alpha.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,81 @@
1
1
  # @capxul/sdk-react
2
2
 
3
+ ## 0.1.0-alpha.6
4
+
5
+ ### Minor Changes
6
+
7
+ - 3af04a9: Public `<CapxulProvider>` now wires authenticated Convex reads end-to-end (#487, closes #484).
8
+
9
+ The `build-time-urls` arm of `BrowserCapxulConfig` now causes the provider to internally instantiate a `ConvexReactClient`, wrap it as a `CapxulDataClient`, and feed it as `config.data` into `createCapxulClient`. The existing `auth.createDataClient` callback is wired to the same singleton so a `verifyOtp` call refreshes the data client's auth header without churning the WebSocket. The provider also wraps `client.auth.signOut` so the data client survives sign-out — post-signout reads return typed backend `NOT_AUTHENTICATED` instead of the SDK's `NOT_IMPLEMENTED` stub (closes the #474 friction as a side-effect).
10
+
11
+ New optional `sessionStore?: AuthSessionStore` prop lets browser apps opt into `localStorage`-backed persistence and Node consumers (CLIs, e2e harnesses) opt into file-backed persistence. Defaults to in-memory.
12
+
13
+ This closes the architectural gap that made the React hook surface (`useMe`, `useAccount`, `useSafe`, ...) impossible to exercise end-to-end through the public provider — previously `config.data` was never populated, so every authenticated read short-circuited to `NOT_IMPLEMENTED`. The Ink reference CLI (`apps/reference-cli/`) is rebuilt on top of the public provider as proof: 17/17 agent-driver assertions pass against live alpha-3 Convex, including a dev-OTP authenticated round-trip that mints a real session via `AUTH_DEV_OTP=00000` and exercises three distinct hook end-states (`NOT_AUTHENTICATED`, `PROFILE_NOT_FOUND`, post-signout `NOT_AUTHENTICATED`).
14
+
15
+ - 57203a4: Withdrawals v1 W2 (#465) — public surface tightening + org-scope create
16
+ - `WithdrawalsCreateInput.destination` no longer accepts `kind`. The
17
+ backend now resolves the `external_account` row by FK and infers
18
+ the kind + rail server-side. Anything that doesn't route to
19
+ `chain_wallet` (or is chain_wallet but non-EVM in slice 1) returns
20
+ `VERIFICATION_REQUIRED` with `details.rail` + `details.currentKind`.
21
+ - `organizations.withdrawals.create` is now a real mutation (no
22
+ longer a `NOT_IMPLEMENTED` stub). Returns the `processing` row
23
+ only — Safe + Zodiac submission orchestration ships in W3+.
24
+ - `Errors.verificationRequired({ rail, currentKind })` factory
25
+ added; the `VERIFICATION_REQUIRED` code now broadens to cover
26
+ both KYC tier gates and unsupported withdrawal rails.
27
+
28
+ **Migration:** Remove `destination.kind` from any
29
+ `capxul.withdrawals.create({ destination: { kind, externalAccountId } })`
30
+ call sites. Pass only `externalAccountId`.
31
+
32
+ ### Patch Changes
33
+
34
+ - Updated dependencies [57203a4]
35
+ - @capxul/sdk@0.1.0-alpha.6
36
+
37
+ ## 0.1.0-alpha.5
38
+
39
+ ### Patch Changes
40
+
41
+ - Widen the React peer dependency to `>=18.2.0 <20` so React 18-era Ink 5
42
+ CLI apps can install `@capxul/sdk-react` without forcing React 19 into
43
+ Ink's React reconciler. The provider and hooks only use React 18-compatible
44
+ APIs (`createContext`, `useContext`, `useMemo`, `useEffect`, `useState`, and
45
+ `useSyncExternalStore`), preserving React 19 compatibility while unblocking
46
+ React 18 hosts.
47
+
48
+ - Updated dependencies
49
+ - @capxul/sdk@0.1.0-alpha.5
50
+
51
+ ## 0.1.0-alpha.4
52
+
53
+ ### Minor Changes
54
+
55
+ - Post-alpha hardening — WAVE 1 + WAVE 2 cumulative
56
+
57
+ **WAVE 1 (merged 2026-05-03 12:44Z):**
58
+ - S2 story 1: wire onboarding readback hooks (#469) — `me.update`, `accounts.retrieve`, `accounts.update`, `useAccount`, `useSafe`
59
+ - S3 phase 1: Ink reference CLI scaffold + `auth+me` end-to-end against live alpha-3 Convex (#470). Stickiness gate (D3) fired.
60
+ - S5: split `CapxulProvider` into public single-input `BrowserCapxulConfig` + test-only `CapxulTestProvider` from `@capxul/sdk-react/proof` (#473). Q1 lock honored. 7 type-level provider-shape guards including `@ts-expect-error` against test-provider leaking to public barrel.
61
+
62
+ **WAVE 2 (merged 2026-05-03 12:54-13:16Z):**
63
+ - S3 phase 2: per-domain CLI commands closing #458 (#476) — `account retrieve/update`, `safe retrieve`, `payment retrieve`, `withdrawal retrieve/list`. 12/12 agent-driver tests pass.
64
+ - S2 story 2: `capxul.tokenTransfers.*` non-canonical SDK namespace (#479) — Option A per #477 (canon-aligned `transfers.*` shape deferred to alpha.5+ pending backend canon work). New `useTokenTransfers` + `useTokenTransfer` hooks; new `getByTxLogIndex` backend query. Hook proof matrix length unchanged at 41 (non-canonical hooks deliberately excluded).
65
+
66
+ **S1 (#456) closed no-op** — alpha publish infrastructure (tsup, lazy-DX, transport state machine, npm metadata, READMEs, CHANGELOG, changesets, OIDC release workflow) physically merged into `api-first` via PRs #449-#452 earlier the same day; the slice merge produced 0 file changes per clean-room probe.
67
+
68
+ **Friction issues filed for alpha.4+ polish:**
69
+ - #474 — `me.get` returns `NOT_IMPLEMENTED` when `config.data` is undefined; should be `NOT_AUTHENTICATED`.
70
+ - #475 — `@capxul/sdk/headless` slim entry point excludes xstate flow machines + brand constructors (1.6 MB → much smaller).
71
+ - #477 / #478 — `transfers.*` / `balanceLedger.*` / `treasury` canon-shape alignment with indexer feed.
72
+ - #471 — Vercel-capxul-web preview-deploy systemic failure on api-first base (separate from epic).
73
+
74
+ ### Patch Changes
75
+
76
+ - Updated dependencies
77
+ - @capxul/sdk@0.1.0-alpha.4
78
+
3
79
  ## 0.1.0-alpha.3
4
80
 
5
81
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -5,12 +5,52 @@ var react = require('react');
5
5
  var sdk = require('@capxul/sdk');
6
6
  var reactQuery = require('@tanstack/react-query');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
+ var react$2 = require('convex/react');
8
9
  var errors = require('@capxul/sdk/errors');
9
10
  var react$1 = require('@xstate/react');
10
11
  var viem = require('viem');
11
12
  var accounts = require('viem/accounts');
12
13
 
13
14
  // src/provider.tsx
15
+ var CapxulClientContext = react.createContext(null);
16
+ function CapxulClientProvider({
17
+ client,
18
+ children
19
+ }) {
20
+ return /* @__PURE__ */ jsxRuntime.jsx(CapxulClientContext.Provider, { value: client, children });
21
+ }
22
+ function useCapxul() {
23
+ const client = react.useContext(CapxulClientContext);
24
+ if (!client) {
25
+ throw new Error(
26
+ "useCapxul() was called outside a <CapxulProvider>. Wrap your app in <CapxulProvider config={...}> before rendering hooks from @capxul/sdk-react."
27
+ );
28
+ }
29
+ return client;
30
+ }
31
+ var CapxulTransportContext = react.createContext(null);
32
+ function CapxulTransportProvider({
33
+ transport,
34
+ children
35
+ }) {
36
+ return /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportContext.Provider, { value: transport, children });
37
+ }
38
+ function useCapxulStatus() {
39
+ const transport = react.useContext(CapxulTransportContext);
40
+ return react.useSyncExternalStore(
41
+ (listener) => {
42
+ if (!transport) return () => {
43
+ };
44
+ return transport.subscribe(listener);
45
+ },
46
+ () => transport?.getState() ?? FALLBACK_READY,
47
+ () => transport?.getState() ?? FALLBACK_READY
48
+ );
49
+ }
50
+ var FALLBACK_READY = Object.freeze({
51
+ status: "ready",
52
+ runtime: { authBaseUrl: "", convexUrl: "" }
53
+ });
14
54
 
15
55
  // ../config/src/errors.ts
16
56
  var CapxulError = class extends Error {
@@ -71,7 +111,29 @@ var Errors = {
71
111
  { details }
72
112
  ),
73
113
  emailDeliveryFailed: (detail) => new CapxulError("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`),
74
- internalError: (reason) => new CapxulError("INTERNAL_ERROR", `Internal error: ${reason}`)
114
+ internalError: (reason) => new CapxulError("INTERNAL_ERROR", `Internal error: ${reason}`),
115
+ /**
116
+ * Verification gate. Surfaced when a request hits a verification
117
+ * boundary the actor cannot cross under their current state. Two
118
+ * variants share this code:
119
+ *
120
+ * - Rail gate (Withdrawals v1 W2, #465): the resolved
121
+ * `external_account.kind` routes to a withdrawal rail (e.g.
122
+ * `fiat_offramp`, `card_payout`) that is not yet supported. Carries
123
+ * `details.rail` + `details.currentKind`.
124
+ * - KYC tier gate (legacy / future): the actor's KYC tier is below
125
+ * the required tier. Carries `details.requiredTier`.
126
+ *
127
+ * Code is shared because both expose the same UX shape ("you cannot
128
+ * proceed until verification advances"); the `details.*` keys
129
+ * differentiate the route.
130
+ */
131
+ verificationRequired: (details) => {
132
+ const message = "rail" in details ? `Withdrawal rail "${details.rail}" (kind=${details.currentKind}) is not yet supported.` : `Verification tier ${details.requiredTier} is required.`;
133
+ return new CapxulError("VERIFICATION_REQUIRED", message, {
134
+ details: { ...details }
135
+ });
136
+ }
75
137
  };
76
138
 
77
139
  // ../config/src/org-roles.ts
@@ -83,56 +145,95 @@ function roleKeyFromLabel(label) {
83
145
  roleKeyFromLabel("OWNER");
84
146
  roleKeyFromLabel("FINANCE_MANAGER");
85
147
  roleKeyFromLabel("TEAM_LEAD");
86
- var CapxulClientContext = react.createContext(null);
87
- function CapxulClientProvider({
88
- client,
89
- children
90
- }) {
91
- return /* @__PURE__ */ jsxRuntime.jsx(CapxulClientContext.Provider, { value: client, children });
148
+
149
+ // src/config.ts
150
+ function createCapxulConfig(input) {
151
+ assertOnlyKnownKeys(input);
152
+ assertModeRequiredFields(input);
153
+ return Object.freeze({ ...input });
92
154
  }
93
- function useCapxul() {
94
- const client = react.useContext(CapxulClientContext);
95
- if (!client) {
96
- throw new Error(
97
- "useCapxul() was called outside a <CapxulProvider>. Wrap your app in <CapxulProvider config={...}> before rendering hooks from @capxul/sdk-react."
98
- );
99
- }
100
- return client;
155
+ var ALLOWED_BROWSER_CONFIG_KEYS = [
156
+ "mode",
157
+ "authBaseUrl",
158
+ "convexUrl",
159
+ "publishableKey",
160
+ "bootstrapUrl",
161
+ "fetchImpl"
162
+ ];
163
+ function assertOnlyKnownKeys(input) {
164
+ const candidate = input;
165
+ const allowed = new Set(ALLOWED_BROWSER_CONFIG_KEYS);
166
+ const unknown = Object.keys(candidate).filter((key) => !allowed.has(key));
167
+ if (unknown.length === 0) return;
168
+ throw Errors.invalidInput(
169
+ "config",
170
+ `Browser Capxul config contains unknown or secret/server-only fields: ${unknown.join(", ")}. Allowed keys: ${ALLOWED_BROWSER_CONFIG_KEYS.join(", ")}.`
171
+ );
101
172
  }
102
- var CapxulTransportContext = react.createContext(null);
103
- function CapxulTransportProvider({
104
- transport,
105
- children
106
- }) {
107
- return /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportContext.Provider, { value: transport, children });
173
+ function assertModeRequiredFields(input) {
174
+ switch (input.mode) {
175
+ case "build-time-urls": {
176
+ if (!input.authBaseUrl || input.authBaseUrl.trim().length === 0) {
177
+ throw Errors.invalidInput("authBaseUrl", "non-empty string required.");
178
+ }
179
+ if (!input.convexUrl || input.convexUrl.trim().length === 0) {
180
+ throw Errors.invalidInput("convexUrl", "non-empty string required.");
181
+ }
182
+ return;
183
+ }
184
+ case "publishable-key": {
185
+ if (!input.publishableKey || input.publishableKey.trim().length === 0) {
186
+ throw Errors.invalidInput("publishableKey", "non-empty string required.");
187
+ }
188
+ return;
189
+ }
190
+ default: {
191
+ const value = input;
192
+ throw Errors.internalError(
193
+ `Unhandled BrowserCapxulConfig.mode: ${String(value.mode)}.`
194
+ );
195
+ }
196
+ }
108
197
  }
109
- function useCapxulStatus() {
110
- const transport = react.useContext(CapxulTransportContext);
111
- return react.useSyncExternalStore(
112
- (listener) => {
113
- if (!transport) return () => {
114
- };
115
- return transport.subscribe(listener);
116
- },
117
- () => transport?.getState() ?? FALLBACK_READY,
118
- () => transport?.getState() ?? FALLBACK_READY
119
- );
198
+ function createReactDataClient(convexUrl, sessionStore) {
199
+ const client = new react$2.ConvexReactClient(convexUrl);
200
+ const refreshAuth = () => {
201
+ const session = sessionStore.get();
202
+ const jwt = session?.convexJwt;
203
+ if (jwt) {
204
+ client.setAuth(() => Promise.resolve(jwt));
205
+ } else {
206
+ client.clearAuth();
207
+ }
208
+ };
209
+ refreshAuth();
210
+ return {
211
+ query: (name, args) => client.query(name, args),
212
+ mutation: (name, args) => client.mutation(name, args),
213
+ action: (name, args) => client.action(name, args),
214
+ refreshAuth,
215
+ close: () => {
216
+ void client.close();
217
+ }
218
+ };
120
219
  }
121
- var FALLBACK_READY = Object.freeze({
122
- status: "ready",
123
- runtime: { authBaseUrl: "", convexUrl: "" }
124
- });
125
220
  function CapxulProvider({
126
221
  config,
127
- publishableKey,
128
- browserConfig,
222
+ sessionStore,
129
223
  queryClient,
130
224
  children
131
225
  }) {
226
+ const defaultSessionStore = react.useMemo(() => createMemorySessionStore(), []);
227
+ const effectiveSessionStore = sessionStore ?? defaultSessionStore;
132
228
  const wiring = react.useMemo(
133
- () => buildWiring({ config, publishableKey, browserConfig }),
134
- [config, publishableKey, browserConfig]
229
+ () => buildWiring(config, effectiveSessionStore),
230
+ [config, effectiveSessionStore]
135
231
  );
232
+ react.useEffect(() => {
233
+ return () => {
234
+ wiring.dataClient?.close();
235
+ };
236
+ }, [wiring]);
136
237
  const defaultClient = react.useMemo(
137
238
  () => new reactQuery.QueryClient({
138
239
  defaultOptions: { queries: { staleTime: 3e4 } }
@@ -140,51 +241,60 @@ function CapxulProvider({
140
241
  []
141
242
  );
142
243
  const effectiveClient = queryClient ?? defaultClient;
143
- const inner = /* @__PURE__ */ jsxRuntime.jsx(CapxulClientProvider, { client: wiring.client, children });
144
- return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: effectiveClient, children: wiring.transport ? /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportProvider, { transport: wiring.transport, children: inner }) : inner });
244
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: effectiveClient, children: /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportProvider, { transport: wiring.transport, children: /* @__PURE__ */ jsxRuntime.jsx(CapxulClientProvider, { client: wiring.client, children }) }) });
145
245
  }
146
- function buildWiring({
147
- config,
148
- publishableKey,
149
- browserConfig
150
- }) {
151
- const sources = [
152
- config !== void 0,
153
- publishableKey !== void 0,
154
- browserConfig !== void 0
155
- ].filter(Boolean).length;
156
- if (sources === 0) {
157
- throw Errors.invalidInput(
158
- "CapxulProvider",
159
- "Pass exactly one of `config`, `publishableKey`, or `browserConfig`."
160
- );
161
- }
162
- if (sources > 1) {
163
- throw Errors.invalidInput(
164
- "CapxulProvider",
165
- "`config`, `publishableKey`, and `browserConfig` are mutually exclusive \u2014 pass exactly one."
166
- );
167
- }
168
- if (config !== void 0) {
169
- return {
170
- client: sdk.createCapxulClient(config),
171
- transport: null
172
- };
173
- }
174
- const browserCfg = browserConfig ?? {
175
- mode: "publishable-key",
176
- // The narrowing above (`sources === 0` rejected; `config` not
177
- // present) guarantees `publishableKey` is set on this branch.
178
- publishableKey
179
- };
180
- const transport = sdk.makeHttpTransport(browserCfg);
246
+ function buildWiring(config, sessionStore) {
247
+ const validated = createCapxulConfig(config);
248
+ const transport = sdk.makeHttpTransport(validated);
249
+ const dataClient = validated.mode === "build-time-urls" ? createReactDataClient(validated.convexUrl, sessionStore) : null;
181
250
  const sdkConfig = {
182
251
  _transport: transport,
183
- publishableKey: browserCfg.mode === "publishable-key" ? browserCfg.publishableKey : void 0
252
+ publishableKey: validated.mode === "publishable-key" ? validated.publishableKey : void 0,
253
+ data: dataClient ?? void 0,
254
+ auth: dataClient ? {
255
+ // The auth client builds the BetterAuth root URL from this
256
+ // value. Convex's `.cloud` URL is the wrong host (BetterAuth
257
+ // is mounted on the `.site` URL), but the build-time-urls
258
+ // transport already encodes the correct `authBaseUrl` via
259
+ // its discriminated union. We pass `convexUrl` here only so
260
+ // `core/auth.ts`'s `createTransportProvider` short-circuits
261
+ // to the externally-injected `_transport` cache slot.
262
+ baseUrl: transport.authBaseUrl,
263
+ sessionStore,
264
+ createDataClient: async (_session) => {
265
+ dataClient.refreshAuth();
266
+ return dataClient;
267
+ }
268
+ } : void 0
269
+ };
270
+ const client = sdk.createCapxulClient(sdkConfig);
271
+ if (dataClient) {
272
+ const originalSignOut = client.auth.signOut;
273
+ Object.assign(client.auth, {
274
+ signOut: async () => {
275
+ const result = await originalSignOut();
276
+ dataClient.refreshAuth();
277
+ sdkConfig.data = dataClient;
278
+ return result;
279
+ }
280
+ });
281
+ }
282
+ return {
283
+ client,
284
+ transport,
285
+ dataClient
184
286
  };
287
+ }
288
+ function createMemorySessionStore() {
289
+ let current = null;
185
290
  return {
186
- client: sdk.createCapxulClient(sdkConfig),
187
- transport
291
+ get: () => current,
292
+ set: (session) => {
293
+ current = session;
294
+ },
295
+ clear: () => {
296
+ current = null;
297
+ }
188
298
  };
189
299
  }
190
300
  function notImplementedQuery(hookName) {
@@ -274,8 +384,12 @@ function useMe() {
274
384
  staleTime: 3e4
275
385
  });
276
386
  }
277
- function useAccount(_accountId) {
278
- return notImplementedQuery("useAccount");
387
+ function useAccount(accountId) {
388
+ const capxul = useCapxul();
389
+ return useSdkQuery(
390
+ () => accountId !== void 0 ? capxul.accounts.retrieve(accountId) : capxul.me.get(),
391
+ [capxul, accountId]
392
+ );
279
393
  }
280
394
  function useOrganization(_organizationId) {
281
395
  return notImplementedQuery("useOrganization");
@@ -283,8 +397,12 @@ function useOrganization(_organizationId) {
283
397
  function useMember(_args) {
284
398
  return notImplementedQuery("useMember");
285
399
  }
286
- function useSafe(_safeId) {
287
- return notImplementedQuery("useSafe");
400
+ function useSafe(safeId) {
401
+ const capxul = useCapxul();
402
+ return useSdkQuery(
403
+ () => capxul.accounts.safes.retrieve(safeId),
404
+ [capxul, safeId]
405
+ );
288
406
  }
289
407
  function useTreasury(_organizationId) {
290
408
  return notImplementedQuery("useTreasury");
@@ -298,8 +416,15 @@ function useKycProfile(_accountId) {
298
416
  function useKybProfile(_organizationId) {
299
417
  return notImplementedQuery("useKybProfile");
300
418
  }
301
- function useExternalAccount(_args) {
302
- return notImplementedQuery("useExternalAccount");
419
+ function useExternalAccount(args) {
420
+ const capxul = useCapxul();
421
+ return useSdkQuery(
422
+ () => args.ownerKind === "account" ? capxul.externalAccounts.retrieve(args.externalAccountId) : capxul.organizations.externalAccounts.retrieve({
423
+ organizationId: args.ownerId,
424
+ externalAccountId: args.externalAccountId
425
+ }),
426
+ [capxul, args.ownerKind, args.ownerId, args.externalAccountId]
427
+ );
303
428
  }
304
429
  function useSubAccount(_subAccountId) {
305
430
  return notImplementedQuery("useSubAccount");
@@ -316,14 +441,25 @@ function usePayment(_paymentId) {
316
441
  function useTransfer(_transferId) {
317
442
  return notImplementedQuery("useTransfer");
318
443
  }
444
+ function useTokenTransfer(args) {
445
+ const capxul = useCapxul();
446
+ return useSdkQuery(
447
+ () => capxul.tokenTransfers.retrieve(args),
448
+ [capxul, args.txHash, args.logIndex, args.chainId]
449
+ );
450
+ }
319
451
  function useBalanceLedgerEntry(_args) {
320
452
  return notImplementedQuery("useBalanceLedgerEntry");
321
453
  }
322
454
  function useDocument(_documentId) {
323
455
  return notImplementedQuery("useDocument");
324
456
  }
325
- function useWithdrawal(_withdrawalId) {
326
- return notImplementedQuery("useWithdrawal");
457
+ function useWithdrawal(withdrawalId) {
458
+ const capxul = useCapxul();
459
+ return useSdkQuery(() => capxul.withdrawals.retrieve(withdrawalId), [
460
+ capxul,
461
+ withdrawalId
462
+ ]);
327
463
  }
328
464
  function useOperation(operationId) {
329
465
  const capxul = useCapxul();
@@ -346,8 +482,14 @@ function useOrganizations() {
346
482
  function useMembers(_organizationId) {
347
483
  return notImplementedQuery("useMembers");
348
484
  }
349
- function useExternalAccounts(_args) {
350
- return notImplementedQuery("useExternalAccounts");
485
+ function useExternalAccounts(args) {
486
+ const capxul = useCapxul();
487
+ return useSdkQuery(
488
+ () => args.ownerKind === "account" ? capxul.accounts.externalAccounts.list({ accountId: args.ownerId }) : capxul.organizations.externalAccounts.list({
489
+ organizationId: args.ownerId
490
+ }),
491
+ [capxul, args.ownerKind, args.ownerId]
492
+ );
351
493
  }
352
494
  function useSubAccounts(_args) {
353
495
  return notImplementedQuery("useSubAccounts");
@@ -370,6 +512,13 @@ function useTransfers(_filters) {
370
512
  function useOrgTransfers(_args) {
371
513
  return notImplementedQuery("useOrgTransfers");
372
514
  }
515
+ function useTokenTransfers(filters) {
516
+ const capxul = useCapxul();
517
+ return useSdkQuery(
518
+ () => capxul.tokenTransfers.list(filters),
519
+ [capxul, filters?.limit, filters?.cursor, filters?.direction]
520
+ );
521
+ }
373
522
  function useBalanceLedger(_args) {
374
523
  return notImplementedQuery("useBalanceLedger");
375
524
  }
@@ -379,11 +528,19 @@ function useDocuments(_filters) {
379
528
  function useOrgDocuments(_args) {
380
529
  return notImplementedQuery("useOrgDocuments");
381
530
  }
382
- function useWithdrawals(_filters) {
383
- return notImplementedQuery("useWithdrawals");
531
+ function useWithdrawals(filters) {
532
+ const capxul = useCapxul();
533
+ return useSdkQuery(
534
+ () => capxul.withdrawals.list(filters),
535
+ [capxul, filters?.limit, filters?.cursor]
536
+ );
384
537
  }
385
- function useOrgWithdrawals(_args) {
386
- return notImplementedQuery("useOrgWithdrawals");
538
+ function useOrgWithdrawals(args) {
539
+ const capxul = useCapxul();
540
+ return useSdkQuery(
541
+ () => capxul.organizations.withdrawals.list(args),
542
+ [capxul, args.organizationId, args.limit, args.cursor]
543
+ );
387
544
  }
388
545
  function useApiKeys(_organizationId) {
389
546
  return notImplementedQuery("useApiKeys");
@@ -409,56 +566,6 @@ function useProvisioningFlow() {
409
566
  const [snapshot, send] = react$1.useActor(machine);
410
567
  return { snapshot, send };
411
568
  }
412
-
413
- // src/config.ts
414
- function createCapxulConfig(input) {
415
- assertOnlyKnownKeys(input);
416
- assertModeRequiredFields(input);
417
- return Object.freeze({ ...input });
418
- }
419
- var ALLOWED_BROWSER_CONFIG_KEYS = [
420
- "mode",
421
- "authBaseUrl",
422
- "convexUrl",
423
- "publishableKey",
424
- "bootstrapUrl",
425
- "fetchImpl"
426
- ];
427
- function assertOnlyKnownKeys(input) {
428
- const candidate = input;
429
- const allowed = new Set(ALLOWED_BROWSER_CONFIG_KEYS);
430
- const unknown = Object.keys(candidate).filter((key) => !allowed.has(key));
431
- if (unknown.length === 0) return;
432
- throw Errors.invalidInput(
433
- "config",
434
- `Browser Capxul config contains unknown or secret/server-only fields: ${unknown.join(", ")}. Allowed keys: ${ALLOWED_BROWSER_CONFIG_KEYS.join(", ")}.`
435
- );
436
- }
437
- function assertModeRequiredFields(input) {
438
- switch (input.mode) {
439
- case "build-time-urls": {
440
- if (!input.authBaseUrl || input.authBaseUrl.trim().length === 0) {
441
- throw Errors.invalidInput("authBaseUrl", "non-empty string required.");
442
- }
443
- if (!input.convexUrl || input.convexUrl.trim().length === 0) {
444
- throw Errors.invalidInput("convexUrl", "non-empty string required.");
445
- }
446
- return;
447
- }
448
- case "publishable-key": {
449
- if (!input.publishableKey || input.publishableKey.trim().length === 0) {
450
- throw Errors.invalidInput("publishableKey", "non-empty string required.");
451
- }
452
- return;
453
- }
454
- default: {
455
- const value = input;
456
- throw Errors.internalError(
457
- `Unhandled BrowserCapxulConfig.mode: ${String(value.mode)}.`
458
- );
459
- }
460
- }
461
- }
462
569
  var PRIVATE_KEY_PATTERN = /^0x[0-9a-fA-F]{64}$/;
463
570
  var EVM_ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
464
571
  function injectedConnector(options = {}) {
@@ -592,6 +699,8 @@ exports.useProvisioningFlow = useProvisioningFlow;
592
699
  exports.useSafe = useSafe;
593
700
  exports.useSubAccount = useSubAccount;
594
701
  exports.useSubAccounts = useSubAccounts;
702
+ exports.useTokenTransfer = useTokenTransfer;
703
+ exports.useTokenTransfers = useTokenTransfers;
595
704
  exports.useTransfer = useTransfer;
596
705
  exports.useTransfers = useTransfers;
597
706
  exports.useTreasury = useTreasury;