@capxul/sdk-react 0.1.0-alpha.9 → 0.2.0-alpha.4

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 CHANGED
@@ -12,6 +12,22 @@ var viem = require('viem');
12
12
  var accounts = require('viem/accounts');
13
13
 
14
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
+ }
15
31
  var CapxulClientContext = react.createContext(null);
16
32
  function CapxulClientProvider({
17
33
  client,
@@ -81,10 +97,16 @@ var Errors = {
81
97
  `Shield API error (${status}): ${detail}`,
82
98
  { details: { provider: "shield", status } }
83
99
  ),
84
- providerError: (provider, operation, cause) => new CapxulError(
85
- "PROVIDER_ERROR",
86
- `${provider} ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
87
- { cause, details: { provider, operation } }
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
+ )
88
110
  ),
89
111
  invalidInput: (field, reason) => new CapxulError(
90
112
  "INVALID_INPUT",
@@ -149,7 +171,7 @@ function roleKeyFromLabel(label) {
149
171
  }
150
172
  roleKeyFromLabel("OWNER");
151
173
  roleKeyFromLabel("FINANCE_MANAGER");
152
- roleKeyFromLabel("TEAM_LEAD");
174
+ roleKeyFromLabel("PAYMENTS_OPERATOR");
153
175
 
154
176
  // src/config.ts
155
177
  function createCapxulConfig(input) {
@@ -288,7 +310,7 @@ function CapxulProvider({
288
310
  []
289
311
  );
290
312
  const effectiveClient = queryClient ?? defaultClient;
291
- 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 }) }) });
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 }) }) }) });
292
314
  }
293
315
  function buildWiring(config, sessionStore) {
294
316
  const validated = createCapxulConfig(config);
@@ -297,7 +319,7 @@ function buildWiring(config, sessionStore) {
297
319
  const sdkConfig = {
298
320
  _transport: transport,
299
321
  publishableKey: validated.mode === "publishable-key" ? validated.publishableKey : void 0,
300
- data: dataClient ?? void 0,
322
+ _data: dataClient ?? void 0,
301
323
  auth: validated.mode === "build-time-urls" || validated.mode === "publishable-key" ? {
302
324
  // The auth client builds the BetterAuth root URL from this
303
325
  // value. Convex's `.cloud` URL is the wrong host (BetterAuth
@@ -307,29 +329,16 @@ function buildWiring(config, sessionStore) {
307
329
  // `core/auth.ts`'s `createTransportProvider` short-circuits
308
330
  // to the externally-injected `_transport` cache slot.
309
331
  baseUrl: transport.authBaseUrl,
310
- sessionStore,
311
- createDataClient: async (_session) => {
312
- dataClient.refreshAuth();
313
- return dataClient;
314
- }
332
+ sessionStore
315
333
  } : void 0
316
334
  };
317
335
  const client = sdk.createCapxulClient(sdkConfig);
318
- if (dataClient) {
319
- const originalSignOut = client.auth.signOut;
320
- Object.assign(client.auth, {
321
- signOut: async () => {
322
- const result = await originalSignOut();
323
- dataClient.refreshAuth();
324
- sdkConfig.data = dataClient;
325
- return result;
326
- }
327
- });
328
- }
336
+ const authService = new sdk.AuthService(sdkConfig);
329
337
  return {
330
338
  client,
331
339
  transport,
332
- dataClient
340
+ dataClient,
341
+ authService
333
342
  };
334
343
  }
335
344
  function createMemorySessionStore() {
@@ -438,11 +447,59 @@ function useAccount(accountId) {
438
447
  [capxul, accountId]
439
448
  );
440
449
  }
441
- function useOrganization(_organizationId) {
442
- return notImplementedQuery("useOrganization");
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
+ });
443
471
  }
444
- function useMember(_args) {
445
- return notImplementedQuery("useMember");
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
+ });
446
503
  }
447
504
  function useSafe(safeId) {
448
505
  const capxul = useCapxul();
@@ -451,8 +508,33 @@ function useSafe(safeId) {
451
508
  [capxul, safeId]
452
509
  );
453
510
  }
454
- function useTreasury(_organizationId) {
455
- return notImplementedQuery("useTreasury");
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
+ });
456
538
  }
457
539
  function useApiKey(_args) {
458
540
  return notImplementedQuery("useApiKey");
@@ -460,9 +542,6 @@ function useApiKey(_args) {
460
542
  function useKycProfile(_accountId) {
461
543
  return notImplementedQuery("useKycProfile");
462
544
  }
463
- function useKybProfile(_organizationId) {
464
- return notImplementedQuery("useKybProfile");
465
- }
466
545
  function useExternalAccount(args) {
467
546
  const capxul = useCapxul();
468
547
  return useSdkQuery(
@@ -473,8 +552,12 @@ function useExternalAccount(args) {
473
552
  [capxul, args.ownerKind, args.ownerId, args.externalAccountId]
474
553
  );
475
554
  }
476
- function useSubAccount(_subAccountId) {
477
- return notImplementedQuery("useSubAccount");
555
+ function useSubAccount(subAccountId) {
556
+ const capxul = useCapxul();
557
+ return useSdkQuery(
558
+ () => capxul.subAccounts.retrieve(subAccountId),
559
+ [capxul, subAccountId]
560
+ );
478
561
  }
479
562
  function useVirtualAccount(_virtualAccountId) {
480
563
  return notImplementedQuery("useVirtualAccount");
@@ -482,8 +565,27 @@ function useVirtualAccount(_virtualAccountId) {
482
565
  function useVirtualCard(_virtualCardId) {
483
566
  return notImplementedQuery("useVirtualCard");
484
567
  }
485
- function usePayment(_paymentId) {
486
- return notImplementedQuery("usePayment");
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
+ });
487
589
  }
488
590
  function useTransfer(_transferId) {
489
591
  return notImplementedQuery("useTransfer");
@@ -495,25 +597,32 @@ function useTokenTransfer(args) {
495
597
  [capxul, args.txHash, args.logIndex, args.chainId]
496
598
  );
497
599
  }
498
- function useBalanceLedgerEntry(_args) {
499
- return notImplementedQuery("useBalanceLedgerEntry");
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
+ );
500
609
  }
501
610
  function useDocument(_documentId) {
502
611
  return notImplementedQuery("useDocument");
503
612
  }
504
613
  function useWithdrawal(withdrawalId) {
505
614
  const capxul = useCapxul();
506
- return useSdkQuery(() => capxul.withdrawals.retrieve(withdrawalId), [
507
- capxul,
508
- withdrawalId
509
- ]);
615
+ return useSdkQuery(
616
+ () => capxul.withdrawals.retrieve(withdrawalId),
617
+ [capxul, withdrawalId]
618
+ );
510
619
  }
511
620
  function useOperation(operationId) {
512
621
  const capxul = useCapxul();
513
- return useSdkQuery(() => capxul.operations.retrieve(operationId), [
514
- capxul,
515
- operationId
516
- ]);
622
+ return useSdkQuery(
623
+ () => capxul.operations.retrieve(operationId),
624
+ [capxul, operationId]
625
+ );
517
626
  }
518
627
  function useWebhookEndpoint(_endpointId) {
519
628
  return notImplementedQuery("useWebhookEndpoint");
@@ -521,13 +630,57 @@ function useWebhookEndpoint(_endpointId) {
521
630
  function useWebhookEvent(_eventId) {
522
631
  return notImplementedQuery("useWebhookEvent");
523
632
  }
524
-
525
- // src/hooks/list.ts
526
- function useOrganizations() {
527
- return notImplementedQuery("useOrganizations");
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
+ });
528
654
  }
529
- function useMembers(_organizationId) {
530
- return notImplementedQuery("useMembers");
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
+ });
531
684
  }
532
685
  function useExternalAccounts(args) {
533
686
  const capxul = useCapxul();
@@ -538,8 +691,14 @@ function useExternalAccounts(args) {
538
691
  [capxul, args.ownerKind, args.ownerId]
539
692
  );
540
693
  }
541
- function useSubAccounts(_args) {
542
- return notImplementedQuery("useSubAccounts");
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
+ );
543
702
  }
544
703
  function useVirtualAccounts(_filters) {
545
704
  return notImplementedQuery("useVirtualAccounts");
@@ -547,8 +706,27 @@ function useVirtualAccounts(_filters) {
547
706
  function useVirtualCards(_filters) {
548
707
  return notImplementedQuery("useVirtualCards");
549
708
  }
550
- function usePayments(_filters) {
551
- return notImplementedQuery("usePayments");
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
+ });
552
730
  }
553
731
  function useOrgPayments(_args) {
554
732
  return notImplementedQuery("useOrgPayments");
@@ -566,8 +744,34 @@ function useTokenTransfers(filters) {
566
744
  [capxul, filters?.limit, filters?.cursor, filters?.direction]
567
745
  );
568
746
  }
569
- function useBalanceLedger(_args) {
570
- return notImplementedQuery("useBalanceLedger");
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
+ );
571
775
  }
572
776
  function useDocuments(_filters) {
573
777
  return notImplementedQuery("useDocuments");
@@ -595,17 +799,337 @@ function useApiKeys(_organizationId) {
595
799
  function useWebhookEndpoints() {
596
800
  return notImplementedQuery("useWebhookEndpoints");
597
801
  }
598
- function useAuthFlow() {
599
- const client = useCapxul();
600
- const machine = react.useMemo(() => client.flows.auth(), [client]);
601
- const [snapshot, send] = react$1.useActor(machine);
602
- return { snapshot, send };
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
+ });
603
811
  }
604
- function useAuthBootstrapFlow() {
605
- const client = useCapxul();
606
- const machine = react.useMemo(() => client.flows.authBootstrap(), [client]);
607
- const [snapshot, send] = react$1.useActor(machine);
608
- return { snapshot, send };
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";
609
1133
  }
610
1134
  function useOnboardingFlow() {
611
1135
  const client = useCapxul();
@@ -660,10 +1184,6 @@ function localPrivateKeyConnector(options) {
660
1184
  "must be a 0x-prefixed 32-byte (64 hex chars) string."
661
1185
  );
662
1186
  }
663
- const safeAddress = validateAndNormalizeEvmAddress(
664
- "safeAddress",
665
- options.safeAddress
666
- );
667
1187
  const id = options.id ?? "local-private-key";
668
1188
  return {
669
1189
  id,
@@ -675,13 +1195,7 @@ function localPrivateKeyConnector(options) {
675
1195
  return {
676
1196
  connectorId: id,
677
1197
  connectorKind: "local-private-key",
678
- signerAddress: account.address,
679
- safeAddress,
680
- signerProvider: {
681
- kind: "local-private-key",
682
- signerAddress: account.address,
683
- safeAddress
684
- }
1198
+ signerAddress: account.address
685
1199
  };
686
1200
  }
687
1201
  };
@@ -721,11 +1235,12 @@ exports.CapxulTransportProvider = CapxulTransportProvider;
721
1235
  exports.createCapxulConfig = createCapxulConfig;
722
1236
  exports.injectedConnector = injectedConnector;
723
1237
  exports.localPrivateKeyConnector = localPrivateKeyConnector;
1238
+ exports.useAcceptInvitation = useAcceptInvitation;
724
1239
  exports.useAccount = useAccount;
1240
+ exports.useAccountBalanceLedger = useAccountBalanceLedger;
725
1241
  exports.useApiKey = useApiKey;
726
1242
  exports.useApiKeys = useApiKeys;
727
- exports.useAuthBootstrapFlow = useAuthBootstrapFlow;
728
- exports.useAuthFlow = useAuthFlow;
1243
+ exports.useAuth = useAuth;
729
1244
  exports.useBalanceLedger = useBalanceLedger;
730
1245
  exports.useBalanceLedgerEntry = useBalanceLedgerEntry;
731
1246
  exports.useCapxul = useCapxul;
@@ -734,13 +1249,14 @@ exports.useDocument = useDocument;
734
1249
  exports.useDocuments = useDocuments;
735
1250
  exports.useExternalAccount = useExternalAccount;
736
1251
  exports.useExternalAccounts = useExternalAccounts;
737
- exports.useKybProfile = useKybProfile;
1252
+ exports.useInviteMember = useInviteMember;
738
1253
  exports.useKycProfile = useKycProfile;
739
1254
  exports.useMe = useMe;
740
1255
  exports.useMember = useMember;
741
1256
  exports.useMembers = useMembers;
742
1257
  exports.useOnboardingFlow = useOnboardingFlow;
743
1258
  exports.useOperation = useOperation;
1259
+ exports.useOrgBalanceLedger = useOrgBalanceLedger;
744
1260
  exports.useOrgDocuments = useOrgDocuments;
745
1261
  exports.useOrgPayments = useOrgPayments;
746
1262
  exports.useOrgTransfers = useOrgTransfers;
@@ -750,6 +1266,9 @@ exports.useOrganizations = useOrganizations;
750
1266
  exports.usePayment = usePayment;
751
1267
  exports.usePayments = usePayments;
752
1268
  exports.useProvisioningFlow = useProvisioningFlow;
1269
+ exports.useRemoveMember = useRemoveMember;
1270
+ exports.useResendInvitation = useResendInvitation;
1271
+ exports.useRevokeMember = useRevokeMember;
753
1272
  exports.useSafe = useSafe;
754
1273
  exports.useSubAccount = useSubAccount;
755
1274
  exports.useSubAccounts = useSubAccounts;
@@ -758,6 +1277,7 @@ exports.useTokenTransfers = useTokenTransfers;
758
1277
  exports.useTransfer = useTransfer;
759
1278
  exports.useTransfers = useTransfers;
760
1279
  exports.useTreasury = useTreasury;
1280
+ exports.useUpdateMemberRole = useUpdateMemberRole;
761
1281
  exports.useVirtualAccount = useVirtualAccount;
762
1282
  exports.useVirtualAccounts = useVirtualAccounts;
763
1283
  exports.useVirtualCard = useVirtualCard;