@capxul/sdk-react 0.2.0-alpha.4 → 0.2.0-alpha.5

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/dist/index.cjs DELETED
@@ -1,1289 +0,0 @@
1
- "use client";
2
- 'use strict';
3
-
4
- var react = require('react');
5
- var sdk = require('@capxul/sdk');
6
- var reactQuery = require('@tanstack/react-query');
7
- var jsxRuntime = require('react/jsx-runtime');
8
- var react$2 = require('convex/react');
9
- var errors = require('@capxul/sdk/errors');
10
- var react$1 = require('@xstate/react');
11
- var viem = require('viem');
12
- var accounts = require('viem/accounts');
13
-
14
- // src/provider.tsx
15
- var AuthServiceContext = react.createContext(null);
16
- function AuthServiceProvider({
17
- authService,
18
- children
19
- }) {
20
- return /* @__PURE__ */ jsxRuntime.jsx(AuthServiceContext.Provider, { value: authService, children });
21
- }
22
- function useAuthService() {
23
- const authService = react.useContext(AuthServiceContext);
24
- if (!authService) {
25
- throw new Error(
26
- "useAuthService() was called outside a <CapxulProvider>. Wrap your app in <CapxulProvider config={...}> before rendering hooks from @capxul/sdk-react."
27
- );
28
- }
29
- return authService;
30
- }
31
- var CapxulClientContext = react.createContext(null);
32
- function CapxulClientProvider({
33
- client,
34
- children
35
- }) {
36
- return /* @__PURE__ */ jsxRuntime.jsx(CapxulClientContext.Provider, { value: client, children });
37
- }
38
- function useCapxul() {
39
- const client = react.useContext(CapxulClientContext);
40
- if (!client) {
41
- throw new Error(
42
- "useCapxul() was called outside a <CapxulProvider>. Wrap your app in <CapxulProvider config={...}> before rendering hooks from @capxul/sdk-react."
43
- );
44
- }
45
- return client;
46
- }
47
- var CapxulTransportContext = react.createContext(null);
48
- function CapxulTransportProvider({
49
- transport,
50
- children
51
- }) {
52
- return /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportContext.Provider, { value: transport, children });
53
- }
54
- function useCapxulStatus() {
55
- const transport = react.useContext(CapxulTransportContext);
56
- return react.useSyncExternalStore(
57
- (listener) => {
58
- if (!transport) return () => {
59
- };
60
- return transport.subscribe(listener);
61
- },
62
- () => transport?.getState() ?? FALLBACK_READY,
63
- () => transport?.getState() ?? FALLBACK_READY
64
- );
65
- }
66
- var FALLBACK_READY = Object.freeze({
67
- status: "ready",
68
- runtime: { authBaseUrl: "", convexUrl: "" }
69
- });
70
-
71
- // ../config/src/errors.ts
72
- var CapxulError = class extends Error {
73
- code;
74
- details;
75
- correlationId;
76
- layer;
77
- constructor(code, message, options) {
78
- super(message, options?.cause ? { cause: options.cause } : void 0);
79
- this.code = code;
80
- this.details = options?.details;
81
- this.correlationId = options?.correlationId;
82
- this.layer = options?.layer;
83
- }
84
- };
85
- var Errors = {
86
- notAuthenticated: () => new CapxulError("NOT_AUTHENTICATED", "Not authenticated"),
87
- profileNotFound: (authUserId) => new CapxulError("PROFILE_NOT_FOUND", `Profile not found for user ${authUserId}`),
88
- smartAccountMissing: (authUserId) => new CapxulError("SMART_ACCOUNT_MISSING", `Smart account not provisioned for user ${authUserId}`),
89
- envMissing: (name) => new CapxulError("ENV_MISSING", `Environment variable ${name} not configured`),
90
- openfortApi: (operation, cause) => new CapxulError(
91
- "PROVIDER_ERROR",
92
- `Openfort ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
93
- { cause, details: { provider: "openfort", operation } }
94
- ),
95
- shieldApi: (status, detail) => new CapxulError(
96
- "PROVIDER_ERROR",
97
- `Shield API error (${status}): ${detail}`,
98
- { details: { provider: "shield", status } }
99
- ),
100
- providerError: (provider, operation, cause) => (
101
- // Public `message` is redacted to a fixed shape so provider-side
102
- // exception text never leaks to the client. The original `cause`
103
- // is preserved on `Error.cause` for server-side debugging via
104
- // observability sinks (Sentry, console traces).
105
- new CapxulError(
106
- "PROVIDER_ERROR",
107
- `Provider error: ${provider} ${operation}`,
108
- { cause, details: { provider, operation } }
109
- )
110
- ),
111
- invalidInput: (field, reason) => new CapxulError(
112
- "INVALID_INPUT",
113
- `Invalid ${field}: ${reason}`,
114
- { details: { field, reason } }
115
- ),
116
- playerNotFound: (playerId) => new CapxulError(
117
- "PLAYER_NOT_FOUND",
118
- playerId ? `Openfort player ${playerId} not found` : "Openfort player not found"
119
- ),
120
- accountNotFound: (accountId) => new CapxulError(
121
- "ACCOUNT_NOT_FOUND",
122
- accountId ? `Openfort account ${accountId} not found` : "Openfort smart account not found"
123
- ),
124
- invalidRecipient: (reason) => new CapxulError("INVALID_RECIPIENT", reason),
125
- permissionDenied: (reason = "Permission denied") => new CapxulError("PERMISSION_DENIED", reason),
126
- notFound: (resource, id) => new CapxulError(
127
- "NOT_FOUND",
128
- id ? `${resource} ${id} not found` : `${resource} not found`
129
- ),
130
- idempotencyConflict: (details) => new CapxulError(
131
- "IDEMPOTENCY_CONFLICT",
132
- "Idempotency key was already used for a different request",
133
- { details }
134
- ),
135
- emailDeliveryFailed: (detail, details) => new CapxulError("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`, {
136
- details
137
- }),
138
- rateLimited: (details) => new CapxulError("RATE_LIMITED", "Request was rate limited", {
139
- details: { ...details }
140
- }),
141
- internalError: (reason) => new CapxulError("INTERNAL_ERROR", `Internal error: ${reason}`),
142
- /**
143
- * Verification gate. Surfaced when a request hits a verification
144
- * boundary the actor cannot cross under their current state. Two
145
- * variants share this code:
146
- *
147
- * - Rail gate (Withdrawals v1 W2, #465): the resolved
148
- * `external_account.kind` routes to a withdrawal rail (e.g.
149
- * `fiat_offramp`, `card_payout`) that is not yet supported. Carries
150
- * `details.rail` + `details.currentKind`.
151
- * - KYC tier gate (legacy / future): the actor's KYC tier is below
152
- * the required tier. Carries `details.requiredTier`.
153
- *
154
- * Code is shared because both expose the same UX shape ("you cannot
155
- * proceed until verification advances"); the `details.*` keys
156
- * differentiate the route.
157
- */
158
- verificationRequired: (details) => {
159
- const message = "rail" in details ? `Withdrawal rail "${details.rail}" (kind=${details.currentKind}) is not yet supported.` : `Verification tier ${details.requiredTier} is required.`;
160
- return new CapxulError("VERIFICATION_REQUIRED", message, {
161
- details: { ...details }
162
- });
163
- }
164
- };
165
-
166
- // ../config/src/org-roles.ts
167
- function roleKeyFromLabel(label) {
168
- const bytes = new TextEncoder().encode(label);
169
- const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
170
- return "0x" + hex.padEnd(64, "0");
171
- }
172
- roleKeyFromLabel("OWNER");
173
- roleKeyFromLabel("FINANCE_MANAGER");
174
- roleKeyFromLabel("PAYMENTS_OPERATOR");
175
-
176
- // src/config.ts
177
- function createCapxulConfig(input) {
178
- assertOnlyKnownKeys(input);
179
- assertModeRequiredFields(input);
180
- return Object.freeze({ ...input });
181
- }
182
- var ALLOWED_BROWSER_CONFIG_KEYS = [
183
- "mode",
184
- "authBaseUrl",
185
- "convexUrl",
186
- "publishableKey",
187
- "bootstrapUrl",
188
- "fetchImpl"
189
- ];
190
- function assertOnlyKnownKeys(input) {
191
- const candidate = input;
192
- const allowed = new Set(ALLOWED_BROWSER_CONFIG_KEYS);
193
- const unknown = Object.keys(candidate).filter((key) => !allowed.has(key));
194
- if (unknown.length === 0) return;
195
- throw Errors.invalidInput(
196
- "config",
197
- `Browser Capxul config contains unknown or secret/server-only fields: ${unknown.join(", ")}. Allowed keys: ${ALLOWED_BROWSER_CONFIG_KEYS.join(", ")}.`
198
- );
199
- }
200
- function assertModeRequiredFields(input) {
201
- switch (input.mode) {
202
- case "build-time-urls": {
203
- if (!input.authBaseUrl || input.authBaseUrl.trim().length === 0) {
204
- throw Errors.invalidInput("authBaseUrl", "non-empty string required.");
205
- }
206
- if (!input.convexUrl || input.convexUrl.trim().length === 0) {
207
- throw Errors.invalidInput("convexUrl", "non-empty string required.");
208
- }
209
- return;
210
- }
211
- case "publishable-key": {
212
- if (!input.publishableKey || input.publishableKey.trim().length === 0) {
213
- throw Errors.invalidInput("publishableKey", "non-empty string required.");
214
- }
215
- return;
216
- }
217
- default: {
218
- const value = input;
219
- throw Errors.internalError(
220
- `Unhandled BrowserCapxulConfig.mode: ${String(value.mode)}.`
221
- );
222
- }
223
- }
224
- }
225
- function createReactDataClient(convexUrl, sessionStore) {
226
- const client = new react$2.ConvexReactClient(convexUrl);
227
- const refreshAuth = () => {
228
- const session = sessionStore.get();
229
- const jwt = session?.convexJwt;
230
- if (jwt) {
231
- client.setAuth(() => Promise.resolve(jwt));
232
- } else {
233
- client.clearAuth();
234
- }
235
- };
236
- refreshAuth();
237
- return {
238
- query: (name, args) => client.query(name, args),
239
- mutation: (name, args) => client.mutation(name, args),
240
- action: (name, args) => client.action(name, args),
241
- refreshAuth,
242
- close: () => {
243
- void client.close();
244
- }
245
- };
246
- }
247
- function createLazyReactDataClient(transport, sessionStore, createClient = createReactDataClient) {
248
- let client = null;
249
- let initializeClient = null;
250
- let closed = false;
251
- function closedError() {
252
- return new Error("Capxul React data client is closed");
253
- }
254
- async function getClient() {
255
- if (closed) throw closedError();
256
- if (client) return client;
257
- initializeClient ??= (async () => {
258
- const runtime = await transport.ensureRuntime();
259
- if (closed) throw closedError();
260
- const nextClient = createClient(runtime.convexUrl, sessionStore);
261
- if (closed) {
262
- nextClient.close();
263
- throw closedError();
264
- }
265
- client = nextClient;
266
- return nextClient;
267
- })().catch((error) => {
268
- if (!closed) {
269
- initializeClient = null;
270
- }
271
- throw error;
272
- });
273
- return initializeClient;
274
- }
275
- return {
276
- query: async (name, args) => (await getClient()).query(name, args),
277
- mutation: async (name, args) => (await getClient()).mutation(name, args),
278
- action: async (name, args) => (await getClient()).action?.(name, args),
279
- refreshAuth: () => {
280
- client?.refreshAuth();
281
- },
282
- close: () => {
283
- closed = true;
284
- client?.close();
285
- client = null;
286
- }
287
- };
288
- }
289
- function CapxulProvider({
290
- config,
291
- sessionStore,
292
- queryClient,
293
- children
294
- }) {
295
- const defaultSessionStore = react.useMemo(() => createMemorySessionStore(), []);
296
- const effectiveSessionStore = sessionStore ?? defaultSessionStore;
297
- const wiring = react.useMemo(
298
- () => buildWiring(config, effectiveSessionStore),
299
- [config, effectiveSessionStore]
300
- );
301
- react.useEffect(() => {
302
- return () => {
303
- wiring.dataClient?.close();
304
- };
305
- }, [wiring]);
306
- const defaultClient = react.useMemo(
307
- () => new reactQuery.QueryClient({
308
- defaultOptions: { queries: { staleTime: 3e4 } }
309
- }),
310
- []
311
- );
312
- const effectiveClient = queryClient ?? defaultClient;
313
- 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: /* @__PURE__ */ jsxRuntime.jsx(AuthServiceProvider, { authService: wiring.authService, children }) }) }) });
314
- }
315
- function buildWiring(config, sessionStore) {
316
- const validated = createCapxulConfig(config);
317
- const transport = sdk.makeHttpTransport(validated);
318
- const dataClient = validated.mode === "build-time-urls" ? createReactDataClient(validated.convexUrl, sessionStore) : createLazyReactDataClient(transport, sessionStore);
319
- const sdkConfig = {
320
- _transport: transport,
321
- publishableKey: validated.mode === "publishable-key" ? validated.publishableKey : void 0,
322
- _data: dataClient ?? void 0,
323
- auth: validated.mode === "build-time-urls" || validated.mode === "publishable-key" ? {
324
- // The auth client builds the BetterAuth root URL from this
325
- // value. Convex's `.cloud` URL is the wrong host (BetterAuth
326
- // is mounted on the `.site` URL), but the build-time-urls
327
- // transport already encodes the correct `authBaseUrl` via
328
- // its discriminated union. We pass `convexUrl` here only so
329
- // `core/auth.ts`'s `createTransportProvider` short-circuits
330
- // to the externally-injected `_transport` cache slot.
331
- baseUrl: transport.authBaseUrl,
332
- sessionStore
333
- } : void 0
334
- };
335
- const client = sdk.createCapxulClient(sdkConfig);
336
- const authService = new sdk.AuthService(sdkConfig);
337
- return {
338
- client,
339
- transport,
340
- dataClient,
341
- authService
342
- };
343
- }
344
- function createMemorySessionStore() {
345
- let current = null;
346
- return {
347
- get: () => current,
348
- set: (session) => {
349
- current = session;
350
- },
351
- clear: () => {
352
- current = null;
353
- }
354
- };
355
- }
356
- function notImplementedQuery(hookName) {
357
- return {
358
- status: "error",
359
- error: new errors.CapxulError({
360
- code: "NOT_IMPLEMENTED",
361
- message: `${hookName} is not yet implemented in @capxul/sdk-react. The hook remains a reset placeholder until its vertical lands per sdk-surface.md \xA73b.`
362
- })
363
- };
364
- }
365
- function useSdkQuery(read, dependencies) {
366
- const [state, setState] = react.useState({
367
- dependencies,
368
- result: { status: "loading" }
369
- });
370
- const dependenciesChanged = didDependenciesChange(
371
- state.dependencies,
372
- dependencies
373
- );
374
- react.useEffect(() => {
375
- let active = true;
376
- setState({ dependencies, result: { status: "loading" } });
377
- void read().then(([error, data]) => {
378
- if (!active) {
379
- return;
380
- }
381
- if (error) {
382
- setState({ dependencies, result: { status: "error", error } });
383
- return;
384
- }
385
- setState({ dependencies, result: { status: "data", data } });
386
- }).catch((cause) => {
387
- if (!active) {
388
- return;
389
- }
390
- setState({
391
- dependencies,
392
- result: {
393
- status: "error",
394
- error: cause instanceof errors.CapxulError ? cause : new errors.CapxulError({
395
- code: "UNKNOWN",
396
- message: "SDK read failed before returning a CapxulResult.",
397
- cause
398
- })
399
- }
400
- });
401
- });
402
- return () => {
403
- active = false;
404
- };
405
- }, dependencies);
406
- if (dependenciesChanged) {
407
- return { status: "loading" };
408
- }
409
- return state.result;
410
- }
411
- function didDependenciesChange(previous, next) {
412
- if (previous.length !== next.length) {
413
- return true;
414
- }
415
- return previous.some((previousDependency, index) => {
416
- return !Object.is(previousDependency, next[index]);
417
- });
418
- }
419
-
420
- // src/hooks/singular.ts
421
- function useMe() {
422
- const capxul = useCapxul();
423
- return reactQuery.useQuery({
424
- queryKey: [capxul.id, "capxul", "me"],
425
- queryFn: () => capxul.me.get().then(([error, data]) => {
426
- if (error) {
427
- throw error;
428
- }
429
- return data;
430
- }).catch((cause) => {
431
- if (cause instanceof sdk.CapxulError) {
432
- throw cause;
433
- }
434
- throw new sdk.CapxulError({
435
- code: "UNKNOWN",
436
- message: "SDK read failed before returning a CapxulResult.",
437
- cause
438
- });
439
- }),
440
- staleTime: 3e4
441
- });
442
- }
443
- function useAccount(accountId) {
444
- const capxul = useCapxul();
445
- return useSdkQuery(
446
- () => accountId !== void 0 ? capxul.accounts.retrieve(accountId) : capxul.me.get(),
447
- [capxul, accountId]
448
- );
449
- }
450
- function useOrganization(organizationId) {
451
- const capxul = useCapxul();
452
- return reactQuery.useQuery({
453
- queryKey: [capxul.id, "capxul", "organizations", organizationId],
454
- queryFn: () => capxul.organizations.retrieve(organizationId).then(([error, data]) => {
455
- if (error) {
456
- throw error;
457
- }
458
- return data;
459
- }).catch((cause) => {
460
- if (cause instanceof sdk.CapxulError) {
461
- throw cause;
462
- }
463
- throw new sdk.CapxulError({
464
- code: "UNKNOWN",
465
- message: "SDK read failed before returning a CapxulResult.",
466
- cause
467
- });
468
- }),
469
- staleTime: 3e4
470
- });
471
- }
472
- function useMember(args) {
473
- const capxul = useCapxul();
474
- return reactQuery.useQuery({
475
- queryKey: [
476
- capxul.id,
477
- "capxul",
478
- "organizations",
479
- args.organizationId,
480
- "members",
481
- args.memberId
482
- ],
483
- queryFn: () => capxul.organizations.members.retrieve({
484
- organizationId: args.organizationId,
485
- memberId: args.memberId
486
- }).then(([error, data]) => {
487
- if (error) {
488
- throw error;
489
- }
490
- return data;
491
- }).catch((cause) => {
492
- if (cause instanceof sdk.CapxulError) {
493
- throw cause;
494
- }
495
- throw new sdk.CapxulError({
496
- code: "UNKNOWN",
497
- message: "SDK read failed before returning a CapxulResult.",
498
- cause
499
- });
500
- }),
501
- staleTime: 3e4
502
- });
503
- }
504
- function useSafe(safeId) {
505
- const capxul = useCapxul();
506
- return useSdkQuery(
507
- () => capxul.accounts.safes.retrieve(safeId),
508
- [capxul, safeId]
509
- );
510
- }
511
- function useTreasury(organizationId) {
512
- const capxul = useCapxul();
513
- return reactQuery.useQuery({
514
- queryKey: [
515
- capxul.id,
516
- "capxul",
517
- "organizations",
518
- organizationId,
519
- "treasury"
520
- ],
521
- queryFn: () => capxul.organizations.treasury.retrieve(organizationId).then(([error, data]) => {
522
- if (error) {
523
- throw error;
524
- }
525
- return data;
526
- }).catch((cause) => {
527
- if (cause instanceof sdk.CapxulError) {
528
- throw cause;
529
- }
530
- throw new sdk.CapxulError({
531
- code: "UNKNOWN",
532
- message: "SDK read failed before returning a CapxulResult.",
533
- cause
534
- });
535
- }),
536
- staleTime: 3e4
537
- });
538
- }
539
- function useApiKey(_args) {
540
- return notImplementedQuery("useApiKey");
541
- }
542
- function useKycProfile(_accountId) {
543
- return notImplementedQuery("useKycProfile");
544
- }
545
- function useExternalAccount(args) {
546
- const capxul = useCapxul();
547
- return useSdkQuery(
548
- () => args.ownerKind === "account" ? capxul.externalAccounts.retrieve(args.externalAccountId) : capxul.organizations.externalAccounts.retrieve({
549
- organizationId: args.ownerId,
550
- externalAccountId: args.externalAccountId
551
- }),
552
- [capxul, args.ownerKind, args.ownerId, args.externalAccountId]
553
- );
554
- }
555
- function useSubAccount(subAccountId) {
556
- const capxul = useCapxul();
557
- return useSdkQuery(
558
- () => capxul.subAccounts.retrieve(subAccountId),
559
- [capxul, subAccountId]
560
- );
561
- }
562
- function useVirtualAccount(_virtualAccountId) {
563
- return notImplementedQuery("useVirtualAccount");
564
- }
565
- function useVirtualCard(_virtualCardId) {
566
- return notImplementedQuery("useVirtualCard");
567
- }
568
- function usePayment(paymentId) {
569
- const capxul = useCapxul();
570
- return reactQuery.useQuery({
571
- queryKey: [capxul.id, "capxul", "payments", paymentId],
572
- queryFn: () => capxul.payments.retrieve(paymentId).then(([error, data]) => {
573
- if (error) {
574
- throw error;
575
- }
576
- return data;
577
- }).catch((cause) => {
578
- if (cause instanceof sdk.CapxulError) {
579
- throw cause;
580
- }
581
- throw new sdk.CapxulError({
582
- code: "UNKNOWN",
583
- message: "SDK read failed before returning a CapxulResult.",
584
- cause
585
- });
586
- }),
587
- staleTime: 3e4
588
- });
589
- }
590
- function useTransfer(_transferId) {
591
- return notImplementedQuery("useTransfer");
592
- }
593
- function useTokenTransfer(args) {
594
- const capxul = useCapxul();
595
- return useSdkQuery(
596
- () => capxul.tokenTransfers.retrieve(args),
597
- [capxul, args.txHash, args.logIndex, args.chainId]
598
- );
599
- }
600
- function useBalanceLedgerEntry(args) {
601
- const capxul = useCapxul();
602
- return useSdkQuery(
603
- () => args.ownerKind === "account" ? capxul.accounts.balanceLedger.retrieve(args.entryId) : capxul.organizations.balanceLedger.retrieve({
604
- organizationId: args.ownerId,
605
- entryId: args.entryId
606
- }),
607
- [capxul, args.ownerKind, args.ownerId, args.entryId]
608
- );
609
- }
610
- function useDocument(_documentId) {
611
- return notImplementedQuery("useDocument");
612
- }
613
- function useWithdrawal(withdrawalId) {
614
- const capxul = useCapxul();
615
- return useSdkQuery(
616
- () => capxul.withdrawals.retrieve(withdrawalId),
617
- [capxul, withdrawalId]
618
- );
619
- }
620
- function useOperation(operationId) {
621
- const capxul = useCapxul();
622
- return useSdkQuery(
623
- () => capxul.operations.retrieve(operationId),
624
- [capxul, operationId]
625
- );
626
- }
627
- function useWebhookEndpoint(_endpointId) {
628
- return notImplementedQuery("useWebhookEndpoint");
629
- }
630
- function useWebhookEvent(_eventId) {
631
- return notImplementedQuery("useWebhookEvent");
632
- }
633
- function useOrganizations(filters) {
634
- const capxul = useCapxul();
635
- return reactQuery.useQuery({
636
- queryKey: [capxul.id, "capxul", "organizations", "list", filters],
637
- queryFn: () => capxul.organizations.list(filters).then(([error, data]) => {
638
- if (error) {
639
- throw error;
640
- }
641
- return data;
642
- }).catch((cause) => {
643
- if (cause instanceof sdk.CapxulError) {
644
- throw cause;
645
- }
646
- throw new sdk.CapxulError({
647
- code: "UNKNOWN",
648
- message: "SDK read failed before returning a CapxulResult.",
649
- cause
650
- });
651
- }),
652
- staleTime: 3e4
653
- });
654
- }
655
- function useMembers(organizationId, filters) {
656
- const capxul = useCapxul();
657
- return reactQuery.useQuery({
658
- queryKey: [
659
- capxul.id,
660
- "capxul",
661
- "organizations",
662
- organizationId,
663
- "members",
664
- "list",
665
- filters?.status
666
- ],
667
- queryFn: () => capxul.organizations.members.list({ organizationId, status: filters?.status }).then(([error, data]) => {
668
- if (error) {
669
- throw error;
670
- }
671
- return data;
672
- }).catch((cause) => {
673
- if (cause instanceof sdk.CapxulError) {
674
- throw cause;
675
- }
676
- throw new sdk.CapxulError({
677
- code: "UNKNOWN",
678
- message: "SDK read failed before returning a CapxulResult.",
679
- cause
680
- });
681
- }),
682
- staleTime: 3e4
683
- });
684
- }
685
- function useExternalAccounts(args) {
686
- const capxul = useCapxul();
687
- return useSdkQuery(
688
- () => args.ownerKind === "account" ? capxul.accounts.externalAccounts.list({ accountId: args.ownerId }) : capxul.organizations.externalAccounts.list({
689
- organizationId: args.ownerId
690
- }),
691
- [capxul, args.ownerKind, args.ownerId]
692
- );
693
- }
694
- function useSubAccounts(args) {
695
- const capxul = useCapxul();
696
- return useSdkQuery(
697
- () => args.ownerKind === "account" ? capxul.accounts.subAccounts.list({ accountId: args.ownerId }) : capxul.organizations.subAccounts.list({
698
- organizationId: args.ownerId
699
- }),
700
- [capxul, args.ownerKind, args.ownerId]
701
- );
702
- }
703
- function useVirtualAccounts(_filters) {
704
- return notImplementedQuery("useVirtualAccounts");
705
- }
706
- function useVirtualCards(_filters) {
707
- return notImplementedQuery("useVirtualCards");
708
- }
709
- function usePayments(filters) {
710
- const capxul = useCapxul();
711
- return reactQuery.useQuery({
712
- queryKey: [capxul.id, "capxul", "payments", "list", filters],
713
- queryFn: () => capxul.payments.list(filters).then(([error, data]) => {
714
- if (error) {
715
- throw error;
716
- }
717
- return data;
718
- }).catch((cause) => {
719
- if (cause instanceof sdk.CapxulError) {
720
- throw cause;
721
- }
722
- throw new sdk.CapxulError({
723
- code: "UNKNOWN",
724
- message: "SDK read failed before returning a CapxulResult.",
725
- cause
726
- });
727
- }),
728
- staleTime: 3e4
729
- });
730
- }
731
- function useOrgPayments(_args) {
732
- return notImplementedQuery("useOrgPayments");
733
- }
734
- function useTransfers(_filters) {
735
- return notImplementedQuery("useTransfers");
736
- }
737
- function useOrgTransfers(_args) {
738
- return notImplementedQuery("useOrgTransfers");
739
- }
740
- function useTokenTransfers(filters) {
741
- const capxul = useCapxul();
742
- return useSdkQuery(
743
- () => capxul.tokenTransfers.list(filters),
744
- [capxul, filters?.limit, filters?.cursor, filters?.direction]
745
- );
746
- }
747
- function useBalanceLedger(args) {
748
- const capxul = useCapxul();
749
- return useSdkQuery(
750
- () => args.ownerKind === "account" ? capxul.accounts.balanceLedger.list({
751
- accountId: args.ownerId,
752
- limit: args.limit,
753
- cursor: args.cursor
754
- }) : capxul.organizations.balanceLedger.list({
755
- organizationId: args.ownerId,
756
- limit: args.limit,
757
- cursor: args.cursor
758
- }),
759
- [capxul, args.ownerKind, args.ownerId, args.limit, args.cursor]
760
- );
761
- }
762
- function useAccountBalanceLedger(accountId, filters) {
763
- const capxul = useCapxul();
764
- return useSdkQuery(
765
- () => capxul.accounts.balanceLedger.list({ accountId, ...filters }),
766
- [capxul, accountId, filters?.limit, filters?.cursor]
767
- );
768
- }
769
- function useOrgBalanceLedger(args) {
770
- const capxul = useCapxul();
771
- return useSdkQuery(
772
- () => capxul.organizations.balanceLedger.list(args),
773
- [capxul, args.organizationId, args.limit, args.cursor]
774
- );
775
- }
776
- function useDocuments(_filters) {
777
- return notImplementedQuery("useDocuments");
778
- }
779
- function useOrgDocuments(_args) {
780
- return notImplementedQuery("useOrgDocuments");
781
- }
782
- function useWithdrawals(filters) {
783
- const capxul = useCapxul();
784
- return useSdkQuery(
785
- () => capxul.withdrawals.list(filters),
786
- [capxul, filters?.limit, filters?.cursor]
787
- );
788
- }
789
- function useOrgWithdrawals(args) {
790
- const capxul = useCapxul();
791
- return useSdkQuery(
792
- () => capxul.organizations.withdrawals.list(args),
793
- [capxul, args.organizationId, args.limit, args.cursor]
794
- );
795
- }
796
- function useApiKeys(_organizationId) {
797
- return notImplementedQuery("useApiKeys");
798
- }
799
- function useWebhookEndpoints() {
800
- return notImplementedQuery("useWebhookEndpoints");
801
- }
802
- function useInviteMember() {
803
- const capxul = useCapxul();
804
- return reactQuery.useMutation({
805
- mutationFn: async (args) => {
806
- const [error, data] = await capxul.organizations.members.invite(args);
807
- if (error) throw error;
808
- return data;
809
- }
810
- });
811
- }
812
- function useAcceptInvitation() {
813
- const capxul = useCapxul();
814
- return reactQuery.useMutation({
815
- mutationFn: async (args) => {
816
- const [error, data] = await capxul.organizations.members.accept(args);
817
- if (error) throw error;
818
- return data;
819
- }
820
- });
821
- }
822
- function useUpdateMemberRole() {
823
- const capxul = useCapxul();
824
- return reactQuery.useMutation({
825
- mutationFn: async (args) => {
826
- const [error, data] = await capxul.organizations.members.updateRole(args);
827
- if (error) throw error;
828
- return data;
829
- }
830
- });
831
- }
832
- function useRevokeMember() {
833
- const capxul = useCapxul();
834
- return reactQuery.useMutation({
835
- mutationFn: async (args) => {
836
- const [error, data] = await capxul.organizations.members.revoke(args);
837
- if (error) throw error;
838
- return data;
839
- }
840
- });
841
- }
842
- function useRemoveMember() {
843
- const capxul = useCapxul();
844
- return reactQuery.useMutation({
845
- mutationFn: async (args) => {
846
- const [error, data] = await capxul.organizations.members.remove(args);
847
- if (error) throw error;
848
- return data;
849
- }
850
- });
851
- }
852
- function useResendInvitation() {
853
- const capxul = useCapxul();
854
- return reactQuery.useMutation({
855
- mutationFn: async (args) => {
856
- const [error, data] = await capxul.organizations.members.resend(args);
857
- if (error) throw error;
858
- return data;
859
- }
860
- });
861
- }
862
-
863
- // ../observability/src/debug-log.ts
864
- function isDevelopmentBuild() {
865
- if (typeof process === "undefined") {
866
- return false;
867
- }
868
- return process.env?.NODE_ENV === "development" || process.env?.NODE_ENV === "test";
869
- }
870
- function debugLog(line) {
871
- if (!isDevelopmentBuild()) return;
872
- if (typeof globalThis !== "undefined" && "window" in globalThis && typeof console?.info === "function") {
873
- console.info(line);
874
- return;
875
- }
876
- if (typeof process !== "undefined" && typeof process.stderr?.write === "function") {
877
- process.stderr.write(`${line}
878
- `);
879
- }
880
- }
881
- function formatDebugValue(value) {
882
- if (value === void 0 || value === "") return "";
883
- if (typeof value === "string") return value;
884
- try {
885
- return JSON.stringify(value);
886
- } catch {
887
- return String(value);
888
- }
889
- }
890
- function track(...args) {
891
- const [name, props] = args;
892
- debugLog(`[TRACK] ${name} ${formatDebugValue(props ?? "")}`);
893
- }
894
- function formatDebugValue2(value) {
895
- if (value === void 0 || value === "") return "";
896
- if (typeof value === "string") return value;
897
- try {
898
- return JSON.stringify(value);
899
- } catch {
900
- return String(value);
901
- }
902
- }
903
- function identify(userId, traits) {
904
- debugLog(`[IDENTIFY] ${userId} ${formatDebugValue2(traits ?? "")}`);
905
- }
906
- function resetIdentity() {
907
- }
908
- function useAuth(options) {
909
- const authService = useAuthService();
910
- const signerProvisioner = useMemoizedSignerProvisioner();
911
- const injectedSigner = options?.signer;
912
- const [state, setState] = react.useState("idle");
913
- const [user, setUser] = react.useState(null);
914
- const [bootstrap, setBootstrap] = react.useState(
915
- null
916
- );
917
- const bootstrapRef = react.useRef(null);
918
- const [error, setError] = react.useState(null);
919
- const signIn = react.useCallback(
920
- async (email) => {
921
- setState("sendingOtp");
922
- setError(null);
923
- try {
924
- await authService.sendOtp(email);
925
- track("auth_otp_requested", {
926
- email_domain: emailDomain(email)
927
- });
928
- setState("awaitingOtp");
929
- } catch (err) {
930
- const wrapped = err instanceof Error ? err : new Error(String(err));
931
- trackAuthFailure("otp_request", wrapped);
932
- setError(wrapped);
933
- setState("error");
934
- throw wrapped;
935
- }
936
- },
937
- [authService]
938
- );
939
- const verifyOtp = react.useCallback(
940
- async (email, otp) => {
941
- setState("awaitingOtp");
942
- setError(null);
943
- try {
944
- const result = await authService.verifyOtp(email, otp);
945
- if (result.kind === "existing_member") {
946
- track("auth_otp_verified", {
947
- email_domain: emailDomain(result.session.email),
948
- branch: "existing_member"
949
- });
950
- const nextUser = {
951
- account: result.account,
952
- username: result.username,
953
- safe: result.safe,
954
- session: result.session
955
- };
956
- setUser(nextUser);
957
- setBootstrap(null);
958
- bootstrapRef.current = null;
959
- identify(result.session.authUserId, {
960
- auth_branch: "existing_member"
961
- });
962
- track("auth_session_ready", {
963
- branch: "existing_member",
964
- has_convex_jwt: typeof result.session.convexJwt === "string"
965
- });
966
- setState("authenticated");
967
- return {
968
- kind: "existing_member",
969
- session: result.session,
970
- user: nextUser
971
- };
972
- }
973
- const nextBootstrap = {
974
- bootstrapToken: result.bootstrapToken,
975
- email: result.email,
976
- reason: result.reason,
977
- username: result.username,
978
- session: result.session
979
- };
980
- setUser(null);
981
- setBootstrap(nextBootstrap);
982
- bootstrapRef.current = nextBootstrap;
983
- track("auth_otp_verified", {
984
- email_domain: emailDomain(result.session.email),
985
- branch: "bootstrap_required"
986
- });
987
- track("auth_bootstrap_required", {
988
- reason: result.reason,
989
- has_suggested_username: result.username !== void 0,
990
- has_convex_jwt: typeof result.session.convexJwt === "string"
991
- });
992
- setState("bootstrapRequired");
993
- return {
994
- kind: "bootstrap_required",
995
- session: result.session,
996
- bootstrap: nextBootstrap
997
- };
998
- } catch (err) {
999
- const wrapped = err instanceof Error ? err : new Error(String(err));
1000
- trackAuthFailure("otp_verify", wrapped);
1001
- setError(wrapped);
1002
- setState("error");
1003
- throw wrapped;
1004
- }
1005
- },
1006
- [authService]
1007
- );
1008
- const completeBootstrap = react.useCallback(
1009
- async (username, signer) => {
1010
- const pendingBootstrap = bootstrapRef.current;
1011
- if (!pendingBootstrap) {
1012
- const missing = new Error(
1013
- "completeBootstrap requires a prior bootstrap_required OTP result."
1014
- );
1015
- track("auth_session_lost", { step: "complete_bootstrap" });
1016
- setError(missing);
1017
- setState("error");
1018
- throw missing;
1019
- }
1020
- setError(null);
1021
- track("auth_username_submitted", {
1022
- has_suggested_username: pendingBootstrap.username !== void 0
1023
- });
1024
- setState("provisioningSigner");
1025
- try {
1026
- const signerKind = signer ? "provided" : injectedSigner ? "configured" : "generated";
1027
- const selectedSigner = signer ?? injectedSigner ?? signerProvisioner.provision().signer;
1028
- track("auth_signer_provisioned", { signer_kind: signerKind });
1029
- setState("bootstrapping");
1030
- const bootstrapResult = await authService.completeBootstrap(
1031
- {
1032
- bootstrapToken: pendingBootstrap.bootstrapToken,
1033
- username
1034
- },
1035
- selectedSigner
1036
- );
1037
- const nextUser = {
1038
- account: bootstrapResult.account,
1039
- username: bootstrapResult.username,
1040
- safe: bootstrapResult.safe,
1041
- session: bootstrapResult.session
1042
- };
1043
- track("auth_safe_provisioned", {
1044
- safe_status: bootstrapResult.safe.status
1045
- });
1046
- setUser(nextUser);
1047
- setBootstrap(null);
1048
- bootstrapRef.current = null;
1049
- identify(bootstrapResult.session.authUserId, {
1050
- auth_branch: "bootstrap_required"
1051
- });
1052
- track("auth_bootstrap_completed", {
1053
- reason: pendingBootstrap.reason
1054
- });
1055
- track("auth_session_ready", {
1056
- branch: "bootstrap_required",
1057
- has_convex_jwt: typeof bootstrapResult.session.convexJwt === "string"
1058
- });
1059
- setState("authenticated");
1060
- return nextUser;
1061
- } catch (err) {
1062
- const wrapped = err instanceof Error ? err : new Error(String(err));
1063
- trackAuthFailure("complete_bootstrap", wrapped);
1064
- setError(wrapped);
1065
- setState("error");
1066
- throw wrapped;
1067
- }
1068
- },
1069
- [authService, injectedSigner, signerProvisioner]
1070
- );
1071
- const signOut = react.useCallback(async () => {
1072
- setError(null);
1073
- try {
1074
- await authService.signOut();
1075
- track("auth_signed_out");
1076
- resetIdentity();
1077
- setUser(null);
1078
- setBootstrap(null);
1079
- bootstrapRef.current = null;
1080
- setState("idle");
1081
- } catch (err) {
1082
- const wrapped = err instanceof Error ? err : new Error(String(err));
1083
- trackAuthFailure("sign_out", wrapped);
1084
- setError(wrapped);
1085
- setState("error");
1086
- throw wrapped;
1087
- }
1088
- }, [authService]);
1089
- return react.useMemo(
1090
- () => ({
1091
- state,
1092
- user,
1093
- bootstrap,
1094
- error,
1095
- signIn,
1096
- verifyOtp,
1097
- completeBootstrap,
1098
- signOut
1099
- }),
1100
- [
1101
- state,
1102
- user,
1103
- bootstrap,
1104
- error,
1105
- signIn,
1106
- verifyOtp,
1107
- completeBootstrap,
1108
- signOut
1109
- ]
1110
- );
1111
- }
1112
- function useMemoizedSignerProvisioner() {
1113
- const [provisioner] = react.useState(() => new sdk.SignerProvisioner());
1114
- return provisioner;
1115
- }
1116
- function emailDomain(email) {
1117
- const domain = email.split("@")[1]?.trim().toLowerCase();
1118
- return domain && /^[a-z0-9.-]+$/.test(domain) ? domain : "unknown";
1119
- }
1120
- function trackAuthFailure(step, error) {
1121
- const reason = errorCode(error);
1122
- if (reason === "PERMISSION_DENIED" || reason === "AUTHZ_DENIED") {
1123
- track("authz_denied", { step, reason });
1124
- }
1125
- track("auth_failed", {
1126
- step,
1127
- reason
1128
- });
1129
- }
1130
- function errorCode(error) {
1131
- const code = error.code;
1132
- return typeof code === "string" && code.length > 0 ? code : error.name || "Error";
1133
- }
1134
- function useOnboardingFlow() {
1135
- const client = useCapxul();
1136
- const machine = react.useMemo(() => client.flows.onboarding(), [client]);
1137
- const [snapshot, send] = react$1.useActor(machine);
1138
- return { snapshot, send };
1139
- }
1140
- function useProvisioningFlow() {
1141
- const client = useCapxul();
1142
- const machine = react.useMemo(() => client.flows.provisioning(), [client]);
1143
- const [snapshot, send] = react$1.useActor(machine);
1144
- return { snapshot, send };
1145
- }
1146
- var PRIVATE_KEY_PATTERN = /^0x[0-9a-fA-F]{64}$/;
1147
- var EVM_ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
1148
- function injectedConnector(options = {}) {
1149
- const id = options.id ?? "injected";
1150
- return {
1151
- id,
1152
- name: options.name ?? "Injected wallet",
1153
- kind: "injected",
1154
- async connect() {
1155
- const provider = readInjectedProvider();
1156
- const result = await provider.request({
1157
- method: "eth_requestAccounts"
1158
- });
1159
- const accounts = Array.isArray(result) ? result : void 0;
1160
- const rawSignerAddress = accounts?.[0];
1161
- if (rawSignerAddress === void 0 || rawSignerAddress === null) {
1162
- throw Errors.providerError(
1163
- "connector",
1164
- "injected",
1165
- new Error("Injected wallet did not return an account.")
1166
- );
1167
- }
1168
- const signerAddress = validateAndNormalizeEvmAddress(
1169
- "signerAddress",
1170
- rawSignerAddress
1171
- );
1172
- return {
1173
- connectorId: id,
1174
- connectorKind: "injected",
1175
- signerAddress
1176
- };
1177
- }
1178
- };
1179
- }
1180
- function localPrivateKeyConnector(options) {
1181
- if (!options.privateKey || !PRIVATE_KEY_PATTERN.test(options.privateKey)) {
1182
- throw Errors.invalidInput(
1183
- "privateKey",
1184
- "must be a 0x-prefixed 32-byte (64 hex chars) string."
1185
- );
1186
- }
1187
- const id = options.id ?? "local-private-key";
1188
- return {
1189
- id,
1190
- name: options.name ?? "Local private key",
1191
- kind: "local-private-key",
1192
- autoConnect: true,
1193
- async connect() {
1194
- const account = accounts.privateKeyToAccount(options.privateKey);
1195
- return {
1196
- connectorId: id,
1197
- connectorKind: "local-private-key",
1198
- signerAddress: account.address
1199
- };
1200
- }
1201
- };
1202
- }
1203
- function readInjectedProvider() {
1204
- const provider = globalThis.ethereum;
1205
- if (!provider || typeof provider.request !== "function") {
1206
- throw Errors.providerError(
1207
- "connector",
1208
- "injected",
1209
- new Error("No injected EIP-1193 wallet was found.")
1210
- );
1211
- }
1212
- return provider;
1213
- }
1214
- function validateAndNormalizeEvmAddress(field, raw) {
1215
- if (typeof raw !== "string" || !EVM_ADDRESS_PATTERN.test(raw)) {
1216
- const display = typeof raw === "string" ? raw.slice(0, 64) : String(raw);
1217
- throw Errors.invalidInput(
1218
- field,
1219
- `must be a 0x-prefixed 40 hex char address, got ${display}.`
1220
- );
1221
- }
1222
- try {
1223
- return viem.getAddress(raw);
1224
- } catch (cause) {
1225
- throw Errors.invalidInput(
1226
- field,
1227
- `failed EIP-55 checksum: ${cause instanceof Error ? cause.message : String(cause)}.`
1228
- );
1229
- }
1230
- }
1231
-
1232
- exports.CapxulClientProvider = CapxulClientProvider;
1233
- exports.CapxulProvider = CapxulProvider;
1234
- exports.CapxulTransportProvider = CapxulTransportProvider;
1235
- exports.createCapxulConfig = createCapxulConfig;
1236
- exports.injectedConnector = injectedConnector;
1237
- exports.localPrivateKeyConnector = localPrivateKeyConnector;
1238
- exports.useAcceptInvitation = useAcceptInvitation;
1239
- exports.useAccount = useAccount;
1240
- exports.useAccountBalanceLedger = useAccountBalanceLedger;
1241
- exports.useApiKey = useApiKey;
1242
- exports.useApiKeys = useApiKeys;
1243
- exports.useAuth = useAuth;
1244
- exports.useBalanceLedger = useBalanceLedger;
1245
- exports.useBalanceLedgerEntry = useBalanceLedgerEntry;
1246
- exports.useCapxul = useCapxul;
1247
- exports.useCapxulStatus = useCapxulStatus;
1248
- exports.useDocument = useDocument;
1249
- exports.useDocuments = useDocuments;
1250
- exports.useExternalAccount = useExternalAccount;
1251
- exports.useExternalAccounts = useExternalAccounts;
1252
- exports.useInviteMember = useInviteMember;
1253
- exports.useKycProfile = useKycProfile;
1254
- exports.useMe = useMe;
1255
- exports.useMember = useMember;
1256
- exports.useMembers = useMembers;
1257
- exports.useOnboardingFlow = useOnboardingFlow;
1258
- exports.useOperation = useOperation;
1259
- exports.useOrgBalanceLedger = useOrgBalanceLedger;
1260
- exports.useOrgDocuments = useOrgDocuments;
1261
- exports.useOrgPayments = useOrgPayments;
1262
- exports.useOrgTransfers = useOrgTransfers;
1263
- exports.useOrgWithdrawals = useOrgWithdrawals;
1264
- exports.useOrganization = useOrganization;
1265
- exports.useOrganizations = useOrganizations;
1266
- exports.usePayment = usePayment;
1267
- exports.usePayments = usePayments;
1268
- exports.useProvisioningFlow = useProvisioningFlow;
1269
- exports.useRemoveMember = useRemoveMember;
1270
- exports.useResendInvitation = useResendInvitation;
1271
- exports.useRevokeMember = useRevokeMember;
1272
- exports.useSafe = useSafe;
1273
- exports.useSubAccount = useSubAccount;
1274
- exports.useSubAccounts = useSubAccounts;
1275
- exports.useTokenTransfer = useTokenTransfer;
1276
- exports.useTokenTransfers = useTokenTransfers;
1277
- exports.useTransfer = useTransfer;
1278
- exports.useTransfers = useTransfers;
1279
- exports.useTreasury = useTreasury;
1280
- exports.useUpdateMemberRole = useUpdateMemberRole;
1281
- exports.useVirtualAccount = useVirtualAccount;
1282
- exports.useVirtualAccounts = useVirtualAccounts;
1283
- exports.useVirtualCard = useVirtualCard;
1284
- exports.useVirtualCards = useVirtualCards;
1285
- exports.useWebhookEndpoint = useWebhookEndpoint;
1286
- exports.useWebhookEndpoints = useWebhookEndpoints;
1287
- exports.useWebhookEvent = useWebhookEvent;
1288
- exports.useWithdrawal = useWithdrawal;
1289
- exports.useWithdrawals = useWithdrawals;