@capxul/sdk-react 0.2.0-alpha.3 → 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/CHANGELOG.md +21 -0
- package/README.md +33 -39
- package/dist/index.cjs +182 -40
- package/dist/index.d.cts +33 -100
- package/dist/index.d.ts +33 -100
- package/dist/index.js +185 -41
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @capxul/sdk-react
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.4
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b6c1f94: Complete the auth dogfooding epic around the canonical auth surface.
|
|
8
|
+
|
|
9
|
+
The SDK now carries the guarded OTP proof path, bootstrap continuation states,
|
|
10
|
+
canonical auth service behavior, and final funnel proof support needed for
|
|
11
|
+
first-run auth dogfooding. The React SDK aligns its auth hooks and provider
|
|
12
|
+
state with that canonical flow, including signout cleanup, bootstrap-required
|
|
13
|
+
continuations, and funnel telemetry integration.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 50d3c55: Bundle the internal Safe derivation package into the SDK artifact instead of
|
|
18
|
+
publishing it as a runtime dependency, and add a packaging guard that fails when
|
|
19
|
+
publishable packages leak private `@repo/*` runtime dependencies.
|
|
20
|
+
- Updated dependencies [b6c1f94]
|
|
21
|
+
- Updated dependencies [50d3c55]
|
|
22
|
+
- @capxul/sdk@0.2.0-alpha.4
|
|
23
|
+
|
|
3
24
|
## 0.2.0-alpha.3
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -68,29 +68,23 @@ function Header() {
|
|
|
68
68
|
}
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Drive an OTP sign-in flow with `
|
|
72
|
-
|
|
73
|
-
over the canonical XState v5 machine in `@capxul/sdk`:
|
|
71
|
+
Drive an OTP sign-in flow with `useAuth()` — the canonical React auth
|
|
72
|
+
wrapper over `AuthService`:
|
|
74
73
|
|
|
75
74
|
```tsx
|
|
76
|
-
import {
|
|
77
|
-
import { toEmail } from "@capxul/sdk";
|
|
75
|
+
import { useAuth } from "@capxul/sdk-react";
|
|
78
76
|
|
|
79
77
|
function SignIn() {
|
|
80
|
-
const
|
|
78
|
+
const auth = useAuth();
|
|
81
79
|
|
|
82
|
-
if (
|
|
80
|
+
if (auth.state === "idle") {
|
|
83
81
|
return (
|
|
84
|
-
<button
|
|
85
|
-
onClick={() =>
|
|
86
|
-
send({ type: "REQUEST_OTP", email: toEmail("alice@example.com") })
|
|
87
|
-
}
|
|
88
|
-
>
|
|
82
|
+
<button onClick={() => auth.signIn("alice@example.com")}>
|
|
89
83
|
Send code
|
|
90
84
|
</button>
|
|
91
85
|
);
|
|
92
86
|
}
|
|
93
|
-
// … handle "
|
|
87
|
+
// … handle "sendingOtp", "awaitingOtp", "bootstrapping", "authenticated"
|
|
94
88
|
}
|
|
95
89
|
```
|
|
96
90
|
|
|
@@ -106,11 +100,11 @@ function Banner() {
|
|
|
106
100
|
const status = useCapxulStatus();
|
|
107
101
|
|
|
108
102
|
switch (status.status) {
|
|
109
|
-
case "idle":
|
|
110
|
-
case "bootstrapping":
|
|
103
|
+
case "idle": // no network call yet
|
|
104
|
+
case "bootstrapping": // /v1/client/bootstrap in flight
|
|
111
105
|
return <Spinner />;
|
|
112
|
-
case "ready":
|
|
113
|
-
case "authenticated":
|
|
106
|
+
case "ready": // bootstrapped, no session
|
|
107
|
+
case "authenticated": // bootstrapped + session live
|
|
114
108
|
return null;
|
|
115
109
|
case "error":
|
|
116
110
|
return <ErrorBanner error={status.error} />;
|
|
@@ -129,11 +123,11 @@ itself never re-renders.
|
|
|
129
123
|
The publishable-key path is runtime-proven where the repo can run it
|
|
130
124
|
without secrets:
|
|
131
125
|
|
|
132
|
-
| Surface
|
|
133
|
-
|
|
134
|
-
| Provider + `useMe()` | `corepack pnpm --filter @capxul/sdk-react check-types` plus the headless proof tests under `packages/sdk-react/ops/proof` | provider reaches `useCapxulStatus().status === "ready"` after one bootstrap request
|
|
135
|
-
| Reference CLI mock
|
|
136
|
-
| Reference CLI live
|
|
126
|
+
| Surface | Runtime proof | Expected safe signal |
|
|
127
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
128
|
+
| Provider + `useMe()` | `corepack pnpm --filter @capxul/sdk-react check-types` plus the headless proof tests under `packages/sdk-react/ops/proof` | provider reaches `useCapxulStatus().status === "ready"` after one bootstrap request |
|
|
129
|
+
| Reference CLI mock | `corepack pnpm --filter @capxul/reference-cli build && node apps/reference-cli/dist/cli.js bootstrap probe --mock --json` | `ok:true`, `mode:"publishable-key"`, `bootstrapRequests:1`, `authRequests:1`, `keyLengthClass:"provided"` |
|
|
130
|
+
| Reference CLI live | same command without `--mock`, with `CAPXUL_REF_PUBLISHABLE_KEY` and optional `CAPXUL_REF_BOOTSTRAP_URL` set locally | success only when the key/origin/runtime are valid; otherwise sanitized SDK error JSON |
|
|
137
131
|
|
|
138
132
|
Do not paste or commit publishable keys, session tokens, Convex JWTs,
|
|
139
133
|
cookies, or provider payloads. Proof output reports only
|
|
@@ -141,22 +135,22 @@ cookies, or provider payloads. Proof output reports only
|
|
|
141
135
|
|
|
142
136
|
## Hooks catalogue
|
|
143
137
|
|
|
144
|
-
| Surface
|
|
145
|
-
|
|
146
|
-
| Imperative client
|
|
147
|
-
| Identity
|
|
148
|
-
| Organizations
|
|
149
|
-
| Payments
|
|
150
|
-
| Transfers
|
|
151
|
-
| Withdrawals
|
|
152
|
-
| Documents
|
|
153
|
-
| Sub-accounts / virtual | `useSubAccount`, `useSubAccounts`, `useVirtualAccount`, `useVirtualAccounts`, `useVirtualCard`, `useVirtualCards`
|
|
154
|
-
| Settings
|
|
155
|
-
| KYC / KYB
|
|
156
|
-
| Treasury
|
|
157
|
-
| Operations
|
|
158
|
-
| Lifecycle
|
|
159
|
-
| Flows
|
|
138
|
+
| Surface | Hook |
|
|
139
|
+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
140
|
+
| Imperative client | `useCapxul()` |
|
|
141
|
+
| Identity | `useMe`, `useAccount` |
|
|
142
|
+
| Organizations | `useOrganization`, `useOrganizations`, `useMember`, `useMembers` |
|
|
143
|
+
| Payments | `usePayment`, `usePayments`, `useOrgPayments` |
|
|
144
|
+
| Transfers | `useTransfer`, `useTransfers`, `useOrgTransfers` |
|
|
145
|
+
| Withdrawals | `useWithdrawal`, `useWithdrawals`, `useOrgWithdrawals` |
|
|
146
|
+
| Documents | `useDocument`, `useDocuments`, `useOrgDocuments` |
|
|
147
|
+
| Sub-accounts / virtual | `useSubAccount`, `useSubAccounts`, `useVirtualAccount`, `useVirtualAccounts`, `useVirtualCard`, `useVirtualCards` |
|
|
148
|
+
| Settings | `useApiKey`, `useApiKeys`, `useWebhookEndpoint`, `useWebhookEndpoints`, `useWebhookEvent`, `useExternalAccount`, `useExternalAccounts`, `useBalanceLedgerEntry`, `useBalanceLedger` |
|
|
149
|
+
| KYC / KYB | `useKycProfile` |
|
|
150
|
+
| Treasury | `useTreasury`, `useSafe` |
|
|
151
|
+
| Operations | `useOperation` (correlation join key per CANON.md §3.3) |
|
|
152
|
+
| Lifecycle | `useCapxulStatus` |
|
|
153
|
+
| Flows | `useOnboardingFlow`, `useProvisioningFlow` |
|
|
160
154
|
|
|
161
155
|
Most "not-yet-implemented" verticals return a `QueryResult<T>` in the
|
|
162
156
|
`error` state with `code: "NOT_IMPLEMENTED"` — they compile, render
|
|
@@ -169,7 +163,7 @@ Read hooks return a discriminated union:
|
|
|
169
163
|
```ts
|
|
170
164
|
type QueryResult<T> =
|
|
171
165
|
| { readonly status: "loading" }
|
|
172
|
-
| { readonly status: "data";
|
|
166
|
+
| { readonly status: "data"; readonly data: T }
|
|
173
167
|
| { readonly status: "error"; readonly error: CapxulError };
|
|
174
168
|
```
|
|
175
169
|
|
package/dist/index.cjs
CHANGED
|
@@ -859,12 +859,62 @@ function useResendInvitation() {
|
|
|
859
859
|
}
|
|
860
860
|
});
|
|
861
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
|
+
}
|
|
862
908
|
function useAuth(options) {
|
|
863
909
|
const authService = useAuthService();
|
|
864
910
|
const signerProvisioner = useMemoizedSignerProvisioner();
|
|
865
911
|
const injectedSigner = options?.signer;
|
|
866
912
|
const [state, setState] = react.useState("idle");
|
|
867
913
|
const [user, setUser] = react.useState(null);
|
|
914
|
+
const [bootstrap, setBootstrap] = react.useState(
|
|
915
|
+
null
|
|
916
|
+
);
|
|
917
|
+
const bootstrapRef = react.useRef(null);
|
|
868
918
|
const [error, setError] = react.useState(null);
|
|
869
919
|
const signIn = react.useCallback(
|
|
870
920
|
async (email) => {
|
|
@@ -872,9 +922,13 @@ function useAuth(options) {
|
|
|
872
922
|
setError(null);
|
|
873
923
|
try {
|
|
874
924
|
await authService.sendOtp(email);
|
|
925
|
+
track("auth_otp_requested", {
|
|
926
|
+
email_domain: emailDomain(email)
|
|
927
|
+
});
|
|
875
928
|
setState("awaitingOtp");
|
|
876
929
|
} catch (err) {
|
|
877
930
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
931
|
+
trackAuthFailure("otp_request", wrapped);
|
|
878
932
|
setError(wrapped);
|
|
879
933
|
setState("error");
|
|
880
934
|
throw wrapped;
|
|
@@ -889,25 +943,96 @@ function useAuth(options) {
|
|
|
889
943
|
try {
|
|
890
944
|
const result = await authService.verifyOtp(email, otp);
|
|
891
945
|
if (result.kind === "existing_member") {
|
|
892
|
-
|
|
946
|
+
track("auth_otp_verified", {
|
|
947
|
+
email_domain: emailDomain(result.session.email),
|
|
948
|
+
branch: "existing_member"
|
|
949
|
+
});
|
|
950
|
+
const nextUser = {
|
|
893
951
|
account: result.account,
|
|
894
952
|
username: result.username,
|
|
895
953
|
safe: result.safe,
|
|
896
954
|
session: result.session
|
|
897
955
|
};
|
|
898
|
-
setUser(
|
|
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
|
+
});
|
|
899
966
|
setState("authenticated");
|
|
900
|
-
return
|
|
967
|
+
return {
|
|
968
|
+
kind: "existing_member",
|
|
969
|
+
session: result.session,
|
|
970
|
+
user: nextUser
|
|
971
|
+
};
|
|
901
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 });
|
|
902
1029
|
setState("bootstrapping");
|
|
903
|
-
const signer = injectedSigner ?? signerProvisioner.provision().signer;
|
|
904
|
-
const username = result.username ?? generateUsernameFromEmail(result.email);
|
|
905
1030
|
const bootstrapResult = await authService.completeBootstrap(
|
|
906
1031
|
{
|
|
907
|
-
bootstrapToken:
|
|
1032
|
+
bootstrapToken: pendingBootstrap.bootstrapToken,
|
|
908
1033
|
username
|
|
909
1034
|
},
|
|
910
|
-
|
|
1035
|
+
selectedSigner
|
|
911
1036
|
);
|
|
912
1037
|
const nextUser = {
|
|
913
1038
|
account: bootstrapResult.account,
|
|
@@ -915,26 +1040,47 @@ function useAuth(options) {
|
|
|
915
1040
|
safe: bootstrapResult.safe,
|
|
916
1041
|
session: bootstrapResult.session
|
|
917
1042
|
};
|
|
1043
|
+
track("auth_safe_provisioned", {
|
|
1044
|
+
safe_status: bootstrapResult.safe.status
|
|
1045
|
+
});
|
|
918
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
|
+
});
|
|
919
1059
|
setState("authenticated");
|
|
920
|
-
return
|
|
1060
|
+
return nextUser;
|
|
921
1061
|
} catch (err) {
|
|
922
1062
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
1063
|
+
trackAuthFailure("complete_bootstrap", wrapped);
|
|
923
1064
|
setError(wrapped);
|
|
924
1065
|
setState("error");
|
|
925
1066
|
throw wrapped;
|
|
926
1067
|
}
|
|
927
1068
|
},
|
|
928
|
-
[authService,
|
|
1069
|
+
[authService, injectedSigner, signerProvisioner]
|
|
929
1070
|
);
|
|
930
1071
|
const signOut = react.useCallback(async () => {
|
|
931
1072
|
setError(null);
|
|
932
1073
|
try {
|
|
933
1074
|
await authService.signOut();
|
|
1075
|
+
track("auth_signed_out");
|
|
1076
|
+
resetIdentity();
|
|
934
1077
|
setUser(null);
|
|
1078
|
+
setBootstrap(null);
|
|
1079
|
+
bootstrapRef.current = null;
|
|
935
1080
|
setState("idle");
|
|
936
1081
|
} catch (err) {
|
|
937
1082
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
1083
|
+
trackAuthFailure("sign_out", wrapped);
|
|
938
1084
|
setError(wrapped);
|
|
939
1085
|
setState("error");
|
|
940
1086
|
throw wrapped;
|
|
@@ -944,48 +1090,46 @@ function useAuth(options) {
|
|
|
944
1090
|
() => ({
|
|
945
1091
|
state,
|
|
946
1092
|
user,
|
|
1093
|
+
bootstrap,
|
|
947
1094
|
error,
|
|
948
1095
|
signIn,
|
|
949
1096
|
verifyOtp,
|
|
1097
|
+
completeBootstrap,
|
|
950
1098
|
signOut
|
|
951
1099
|
}),
|
|
952
|
-
[
|
|
1100
|
+
[
|
|
1101
|
+
state,
|
|
1102
|
+
user,
|
|
1103
|
+
bootstrap,
|
|
1104
|
+
error,
|
|
1105
|
+
signIn,
|
|
1106
|
+
verifyOtp,
|
|
1107
|
+
completeBootstrap,
|
|
1108
|
+
signOut
|
|
1109
|
+
]
|
|
953
1110
|
);
|
|
954
1111
|
}
|
|
955
1112
|
function useMemoizedSignerProvisioner() {
|
|
956
1113
|
const [provisioner] = react.useState(() => new sdk.SignerProvisioner());
|
|
957
1114
|
return provisioner;
|
|
958
1115
|
}
|
|
959
|
-
function
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
if (/^[0-9]/.test(sanitized)) {
|
|
963
|
-
sanitized = "u" + sanitized;
|
|
964
|
-
}
|
|
965
|
-
if (sanitized.length < 3) {
|
|
966
|
-
sanitized = sanitized + "_".repeat(3 - sanitized.length);
|
|
967
|
-
}
|
|
968
|
-
if (sanitized.length > 30) {
|
|
969
|
-
sanitized = sanitized.slice(0, 30);
|
|
970
|
-
}
|
|
971
|
-
try {
|
|
972
|
-
return sdk.toUsername(sanitized);
|
|
973
|
-
} catch {
|
|
974
|
-
const fallback = `user_${Date.now() % 1e6}`;
|
|
975
|
-
return sdk.toUsername(fallback);
|
|
976
|
-
}
|
|
1116
|
+
function emailDomain(email) {
|
|
1117
|
+
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
1118
|
+
return domain && /^[a-z0-9.-]+$/.test(domain) ? domain : "unknown";
|
|
977
1119
|
}
|
|
978
|
-
function
|
|
979
|
-
const
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
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
|
+
});
|
|
983
1129
|
}
|
|
984
|
-
function
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
const [snapshot, send] = react$1.useActor(machine);
|
|
988
|
-
return { snapshot, send };
|
|
1130
|
+
function errorCode(error) {
|
|
1131
|
+
const code = error.code;
|
|
1132
|
+
return typeof code === "string" && code.length > 0 ? code : error.name || "Error";
|
|
989
1133
|
}
|
|
990
1134
|
function useOnboardingFlow() {
|
|
991
1135
|
const client = useCapxul();
|
|
@@ -1097,8 +1241,6 @@ exports.useAccountBalanceLedger = useAccountBalanceLedger;
|
|
|
1097
1241
|
exports.useApiKey = useApiKey;
|
|
1098
1242
|
exports.useApiKeys = useApiKeys;
|
|
1099
1243
|
exports.useAuth = useAuth;
|
|
1100
|
-
exports.useAuthBootstrapFlow = useAuthBootstrapFlow;
|
|
1101
|
-
exports.useAuthFlow = useAuthFlow;
|
|
1102
1244
|
exports.useBalanceLedger = useBalanceLedger;
|
|
1103
1245
|
exports.useBalanceLedgerEntry = useBalanceLedgerEntry;
|
|
1104
1246
|
exports.useCapxul = useCapxul;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export { AuthBootstrapFlowContext, AuthBootstrapFlowEvent, AuthFlowContext, AuthFlowEvent, BrowserCapxulConfig, OnboardingFlowContext, OnboardingFlowEvent, ProvisioningFlowContext, ProvisioningFlowEvent } from '@capxul/sdk';
|
|
2
|
+
import { HttpTransport, TransportState, BrowserCapxulConfig, AuthSessionStore, AccountId, OrganizationId, ApiKeyId, BalanceLedgerEntryId, ExternalAccountId, MemberId, Account, ApiKey, BalanceLedgerEntry, DocumentId, Document, ExternalAccount, KycProfile, CapxulError as CapxulError$1, Member, OperationId, Operation, Organization, PaymentId, Payment, SafeId, Safe, SubAccountId, SubAccount, TokenTransfer, TransferId, Transfer, Treasury, VirtualAccountId, VirtualAccount, VirtualCardId, VirtualCard, WebhookEndpointId, WebhookEndpoint, WebhookEventId, WebhookEvent, WithdrawalId, Withdrawal, List, MembershipStatus, TokenTransfersListInput, TokenTransfersListPage, MemberInviteResponse, Session, AuthBootstrapToken, AuthBootstrapReason } from '@capxul/sdk';
|
|
3
|
+
export { BrowserCapxulConfig, OnboardingFlowContext, OnboardingFlowEvent, ProvisioningFlowContext, ProvisioningFlowEvent } from '@capxul/sdk';
|
|
5
4
|
import { QueryClient, UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
|
6
5
|
import { CapxulClient } from '@capxul/sdk/client';
|
|
7
6
|
import { CapxulError } from '@capxul/sdk/errors';
|
|
@@ -517,14 +516,6 @@ declare function useRevokeMember(): UseMutationResult<Member, CapxulError$1, Rev
|
|
|
517
516
|
declare function useRemoveMember(): UseMutationResult<void, CapxulError$1, RemoveMemberArgs>;
|
|
518
517
|
declare function useResendInvitation(): UseMutationResult<MemberInviteResponse, CapxulError$1, ResendInvitationArgs>;
|
|
519
518
|
|
|
520
|
-
/**
|
|
521
|
-
* Lowercased, shape-validated email address. Brand prevents swapping
|
|
522
|
-
* with `phoneNumber`, `username`, or other string identifiers (per
|
|
523
|
-
* `CANON.md` §4.54 and `sdk-surface.md` §5h).
|
|
524
|
-
*/
|
|
525
|
-
type Email = string & {
|
|
526
|
-
readonly __capxulEmailBrand: "Email";
|
|
527
|
-
};
|
|
528
519
|
/**
|
|
529
520
|
* Public Capxul username. 3–30 chars, letter-first, lowercased,
|
|
530
521
|
* remaining chars from `[a-z0-9_-]` (per `CANON.md` §4.54 and
|
|
@@ -543,13 +534,31 @@ type User = {
|
|
|
543
534
|
readonly safe: Safe;
|
|
544
535
|
readonly session: Session;
|
|
545
536
|
};
|
|
546
|
-
type AuthState = "idle" | "sendingOtp" | "awaitingOtp" | "bootstrapping" | "authenticated" | "error";
|
|
537
|
+
type AuthState = "idle" | "sendingOtp" | "awaitingOtp" | "bootstrapRequired" | "provisioningSigner" | "bootstrapping" | "authenticated" | "error";
|
|
538
|
+
type BootstrapContinuation = {
|
|
539
|
+
readonly bootstrapToken: AuthBootstrapToken;
|
|
540
|
+
readonly email: string;
|
|
541
|
+
readonly reason: AuthBootstrapReason;
|
|
542
|
+
readonly username?: Username;
|
|
543
|
+
readonly session: Session;
|
|
544
|
+
};
|
|
545
|
+
type AuthVerifyResult = {
|
|
546
|
+
readonly kind: "existing_member";
|
|
547
|
+
readonly session: Session;
|
|
548
|
+
readonly user: User;
|
|
549
|
+
} | {
|
|
550
|
+
readonly kind: "bootstrap_required";
|
|
551
|
+
readonly session: Session;
|
|
552
|
+
readonly bootstrap: BootstrapContinuation;
|
|
553
|
+
};
|
|
547
554
|
type UseAuthResult = {
|
|
548
555
|
readonly state: AuthState;
|
|
549
556
|
readonly user: User | null;
|
|
557
|
+
readonly bootstrap: BootstrapContinuation | null;
|
|
550
558
|
readonly error: Error | null;
|
|
551
559
|
readonly signIn: (email: string) => Promise<void>;
|
|
552
|
-
readonly verifyOtp: (email: string, otp: string) => Promise<
|
|
560
|
+
readonly verifyOtp: (email: string, otp: string) => Promise<AuthVerifyResult>;
|
|
561
|
+
readonly completeBootstrap: (username: Username, signer?: Account$1) => Promise<User>;
|
|
553
562
|
readonly signOut: () => Promise<void>;
|
|
554
563
|
};
|
|
555
564
|
type UseAuthOptions = {
|
|
@@ -557,100 +566,24 @@ type UseAuthOptions = {
|
|
|
557
566
|
readonly signer?: Account$1;
|
|
558
567
|
};
|
|
559
568
|
/**
|
|
560
|
-
* Canonical auth hook
|
|
569
|
+
* Canonical auth hook.
|
|
561
570
|
*
|
|
562
571
|
* Reactive state (`state`, `user`, `error`) is suitable for UI
|
|
563
572
|
* observers; `signIn`, `verifyOtp`, and `signOut` return promises so
|
|
564
573
|
* the reference CLI can drive the flow imperatively.
|
|
565
574
|
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
575
|
+
* OTP verification is intentionally branch-explicit: existing members
|
|
576
|
+
* authenticate immediately, while first-run or incomplete accounts stop
|
|
577
|
+
* at `bootstrapRequired` until the caller chooses a username and calls
|
|
578
|
+
* `completeBootstrap()`.
|
|
579
|
+
*
|
|
580
|
+
* `completeBootstrap()` auto-provisions a fresh local-private-key signer
|
|
581
|
+
* via `SignerProvisioner` unless the caller passes or configures an
|
|
582
|
+
* explicit signer. Test harnesses use that override to keep the actor's
|
|
583
|
+
* signer stable across later dogfooding operations.
|
|
570
584
|
*/
|
|
571
585
|
declare function useAuth(options?: UseAuthOptions): UseAuthResult;
|
|
572
586
|
|
|
573
|
-
/**
|
|
574
|
-
* @deprecated Use `useAuth()` instead. `useAuthFlow` will be removed
|
|
575
|
-
* in a future release.
|
|
576
|
-
*/
|
|
577
|
-
declare function useAuthFlow(): {
|
|
578
|
-
readonly snapshot: xstate.MachineSnapshot<any, any, any, any, any, any, any, any>;
|
|
579
|
-
readonly send: (event: any) => void;
|
|
580
|
-
};
|
|
581
|
-
/**
|
|
582
|
-
* @deprecated Use `useAuth()` instead. `useAuthBootstrapFlow` will be
|
|
583
|
-
* removed in a future release.
|
|
584
|
-
*/
|
|
585
|
-
declare function useAuthBootstrapFlow(): {
|
|
586
|
-
readonly snapshot: xstate.MachineSnapshot<_capxul_sdk.AuthBootstrapFlowContext, {
|
|
587
|
-
readonly type: "ENTER_EMAIL";
|
|
588
|
-
readonly email: Email;
|
|
589
|
-
} | {
|
|
590
|
-
readonly type: "REQUEST_OTP";
|
|
591
|
-
} | {
|
|
592
|
-
readonly type: "ENTER_OTP";
|
|
593
|
-
readonly code: string;
|
|
594
|
-
} | {
|
|
595
|
-
readonly type: "VERIFY_OTP";
|
|
596
|
-
} | {
|
|
597
|
-
readonly type: "ENTER_USERNAME";
|
|
598
|
-
readonly username: Username;
|
|
599
|
-
} | {
|
|
600
|
-
readonly type: "COMPLETE_BOOTSTRAP";
|
|
601
|
-
} | {
|
|
602
|
-
readonly type: "BACK";
|
|
603
|
-
} | {
|
|
604
|
-
readonly type: "RESET";
|
|
605
|
-
} | {
|
|
606
|
-
readonly type: "SIGN_OUT";
|
|
607
|
-
}, {
|
|
608
|
-
[x: string]: xstate.ActorRefFromLogic<xstate.PromiseActorLogic<void, void, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<_capxul_sdk.CompleteBootstrapResult, {
|
|
609
|
-
bootstrapToken: _capxul_sdk.AuthBootstrapToken;
|
|
610
|
-
username: Username;
|
|
611
|
-
}, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<void, {
|
|
612
|
-
email: Email;
|
|
613
|
-
}, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<_capxul_sdk.VerifyOtpResult, {
|
|
614
|
-
email: Email;
|
|
615
|
-
code: string;
|
|
616
|
-
}, xstate.EventObject>> | undefined;
|
|
617
|
-
}, "email" | "error" | "bootstrap_required" | "authenticated" | "sending_otp" | "otp_requested" | "signing_out" | "verifying_otp" | "completing_bootstrap", string, xstate.NonReducibleUnknown, xstate.MetaObject, {
|
|
618
|
-
id: "authBootstrap";
|
|
619
|
-
states: {
|
|
620
|
-
readonly email: {};
|
|
621
|
-
readonly sending_otp: {};
|
|
622
|
-
readonly otp_requested: {};
|
|
623
|
-
readonly verifying_otp: {};
|
|
624
|
-
readonly bootstrap_required: {};
|
|
625
|
-
readonly completing_bootstrap: {};
|
|
626
|
-
readonly authenticated: {};
|
|
627
|
-
readonly signing_out: {};
|
|
628
|
-
readonly error: {};
|
|
629
|
-
};
|
|
630
|
-
}>;
|
|
631
|
-
readonly send: (event: {
|
|
632
|
-
readonly type: "ENTER_EMAIL";
|
|
633
|
-
readonly email: Email;
|
|
634
|
-
} | {
|
|
635
|
-
readonly type: "REQUEST_OTP";
|
|
636
|
-
} | {
|
|
637
|
-
readonly type: "ENTER_OTP";
|
|
638
|
-
readonly code: string;
|
|
639
|
-
} | {
|
|
640
|
-
readonly type: "VERIFY_OTP";
|
|
641
|
-
} | {
|
|
642
|
-
readonly type: "ENTER_USERNAME";
|
|
643
|
-
readonly username: Username;
|
|
644
|
-
} | {
|
|
645
|
-
readonly type: "COMPLETE_BOOTSTRAP";
|
|
646
|
-
} | {
|
|
647
|
-
readonly type: "BACK";
|
|
648
|
-
} | {
|
|
649
|
-
readonly type: "RESET";
|
|
650
|
-
} | {
|
|
651
|
-
readonly type: "SIGN_OUT";
|
|
652
|
-
}) => void;
|
|
653
|
-
};
|
|
654
587
|
declare function useOnboardingFlow(): {
|
|
655
588
|
readonly snapshot: xstate.MachineSnapshot<any, any, any, any, any, any, any, any>;
|
|
656
589
|
readonly send: (event: any) => void;
|
|
@@ -737,4 +670,4 @@ declare function injectedConnector(options?: InjectedConnectorOptions): CapxulCo
|
|
|
737
670
|
*/
|
|
738
671
|
declare function localPrivateKeyConnector(options: LocalPrivateKeyConnectorOptions): CapxulConnector;
|
|
739
672
|
|
|
740
|
-
export { type AuthState, CapxulClientProvider, type CapxulClientProviderProps, type CapxulConnector, type CapxulConnectorKind, type CapxulConnectorSession, CapxulProvider, type CapxulProviderProps, CapxulTransportProvider, type CapxulTransportProviderProps, type DocumentsFilters, type InjectedConnectorOptions, type LocalPrivateKeyConnectorOptions, type OrgDocumentsFilters, type OrgScopedFilters, type OwnerRef, type OwnerScopedFilters, type PaginationFilters, type PaymentsFilters, type QueryResult, type TransfersFilters, type UseApiKeyArgs, type UseAuthOptions, type UseAuthResult, type UseBalanceLedgerEntryArgs, type UseExternalAccountArgs, type UseMemberArgs, type UseTokenTransferArgs, type User, type VirtualAccountsFilters, type VirtualCardsFilters, type WithdrawalsFilters, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth,
|
|
673
|
+
export { type AuthState, type AuthVerifyResult, type BootstrapContinuation, CapxulClientProvider, type CapxulClientProviderProps, type CapxulConnector, type CapxulConnectorKind, type CapxulConnectorSession, CapxulProvider, type CapxulProviderProps, CapxulTransportProvider, type CapxulTransportProviderProps, type DocumentsFilters, type InjectedConnectorOptions, type LocalPrivateKeyConnectorOptions, type OrgDocumentsFilters, type OrgScopedFilters, type OwnerRef, type OwnerScopedFilters, type PaginationFilters, type PaymentsFilters, type QueryResult, type TransfersFilters, type UseApiKeyArgs, type UseAuthOptions, type UseAuthResult, type UseBalanceLedgerEntryArgs, type UseExternalAccountArgs, type UseMemberArgs, type UseTokenTransferArgs, type User, type VirtualAccountsFilters, type VirtualCardsFilters, type WithdrawalsFilters, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth, useBalanceLedger, useBalanceLedgerEntry, useCapxul, useCapxulStatus, useDocument, useDocuments, useExternalAccount, useExternalAccounts, useInviteMember, useKycProfile, useMe, useMember, useMembers, useOnboardingFlow, useOperation, useOrgBalanceLedger, useOrgDocuments, useOrgPayments, useOrgTransfers, useOrgWithdrawals, useOrganization, useOrganizations, usePayment, usePayments, useProvisioningFlow, useRemoveMember, useResendInvitation, useRevokeMember, useSafe, useSubAccount, useSubAccounts, useTokenTransfer, useTokenTransfers, useTransfer, useTransfers, useTreasury, useUpdateMemberRole, useVirtualAccount, useVirtualAccounts, useVirtualCard, useVirtualCards, useWebhookEndpoint, useWebhookEndpoints, useWebhookEvent, useWithdrawal, useWithdrawals };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export { AuthBootstrapFlowContext, AuthBootstrapFlowEvent, AuthFlowContext, AuthFlowEvent, BrowserCapxulConfig, OnboardingFlowContext, OnboardingFlowEvent, ProvisioningFlowContext, ProvisioningFlowEvent } from '@capxul/sdk';
|
|
2
|
+
import { HttpTransport, TransportState, BrowserCapxulConfig, AuthSessionStore, AccountId, OrganizationId, ApiKeyId, BalanceLedgerEntryId, ExternalAccountId, MemberId, Account, ApiKey, BalanceLedgerEntry, DocumentId, Document, ExternalAccount, KycProfile, CapxulError as CapxulError$1, Member, OperationId, Operation, Organization, PaymentId, Payment, SafeId, Safe, SubAccountId, SubAccount, TokenTransfer, TransferId, Transfer, Treasury, VirtualAccountId, VirtualAccount, VirtualCardId, VirtualCard, WebhookEndpointId, WebhookEndpoint, WebhookEventId, WebhookEvent, WithdrawalId, Withdrawal, List, MembershipStatus, TokenTransfersListInput, TokenTransfersListPage, MemberInviteResponse, Session, AuthBootstrapToken, AuthBootstrapReason } from '@capxul/sdk';
|
|
3
|
+
export { BrowserCapxulConfig, OnboardingFlowContext, OnboardingFlowEvent, ProvisioningFlowContext, ProvisioningFlowEvent } from '@capxul/sdk';
|
|
5
4
|
import { QueryClient, UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
|
6
5
|
import { CapxulClient } from '@capxul/sdk/client';
|
|
7
6
|
import { CapxulError } from '@capxul/sdk/errors';
|
|
@@ -517,14 +516,6 @@ declare function useRevokeMember(): UseMutationResult<Member, CapxulError$1, Rev
|
|
|
517
516
|
declare function useRemoveMember(): UseMutationResult<void, CapxulError$1, RemoveMemberArgs>;
|
|
518
517
|
declare function useResendInvitation(): UseMutationResult<MemberInviteResponse, CapxulError$1, ResendInvitationArgs>;
|
|
519
518
|
|
|
520
|
-
/**
|
|
521
|
-
* Lowercased, shape-validated email address. Brand prevents swapping
|
|
522
|
-
* with `phoneNumber`, `username`, or other string identifiers (per
|
|
523
|
-
* `CANON.md` §4.54 and `sdk-surface.md` §5h).
|
|
524
|
-
*/
|
|
525
|
-
type Email = string & {
|
|
526
|
-
readonly __capxulEmailBrand: "Email";
|
|
527
|
-
};
|
|
528
519
|
/**
|
|
529
520
|
* Public Capxul username. 3–30 chars, letter-first, lowercased,
|
|
530
521
|
* remaining chars from `[a-z0-9_-]` (per `CANON.md` §4.54 and
|
|
@@ -543,13 +534,31 @@ type User = {
|
|
|
543
534
|
readonly safe: Safe;
|
|
544
535
|
readonly session: Session;
|
|
545
536
|
};
|
|
546
|
-
type AuthState = "idle" | "sendingOtp" | "awaitingOtp" | "bootstrapping" | "authenticated" | "error";
|
|
537
|
+
type AuthState = "idle" | "sendingOtp" | "awaitingOtp" | "bootstrapRequired" | "provisioningSigner" | "bootstrapping" | "authenticated" | "error";
|
|
538
|
+
type BootstrapContinuation = {
|
|
539
|
+
readonly bootstrapToken: AuthBootstrapToken;
|
|
540
|
+
readonly email: string;
|
|
541
|
+
readonly reason: AuthBootstrapReason;
|
|
542
|
+
readonly username?: Username;
|
|
543
|
+
readonly session: Session;
|
|
544
|
+
};
|
|
545
|
+
type AuthVerifyResult = {
|
|
546
|
+
readonly kind: "existing_member";
|
|
547
|
+
readonly session: Session;
|
|
548
|
+
readonly user: User;
|
|
549
|
+
} | {
|
|
550
|
+
readonly kind: "bootstrap_required";
|
|
551
|
+
readonly session: Session;
|
|
552
|
+
readonly bootstrap: BootstrapContinuation;
|
|
553
|
+
};
|
|
547
554
|
type UseAuthResult = {
|
|
548
555
|
readonly state: AuthState;
|
|
549
556
|
readonly user: User | null;
|
|
557
|
+
readonly bootstrap: BootstrapContinuation | null;
|
|
550
558
|
readonly error: Error | null;
|
|
551
559
|
readonly signIn: (email: string) => Promise<void>;
|
|
552
|
-
readonly verifyOtp: (email: string, otp: string) => Promise<
|
|
560
|
+
readonly verifyOtp: (email: string, otp: string) => Promise<AuthVerifyResult>;
|
|
561
|
+
readonly completeBootstrap: (username: Username, signer?: Account$1) => Promise<User>;
|
|
553
562
|
readonly signOut: () => Promise<void>;
|
|
554
563
|
};
|
|
555
564
|
type UseAuthOptions = {
|
|
@@ -557,100 +566,24 @@ type UseAuthOptions = {
|
|
|
557
566
|
readonly signer?: Account$1;
|
|
558
567
|
};
|
|
559
568
|
/**
|
|
560
|
-
* Canonical auth hook
|
|
569
|
+
* Canonical auth hook.
|
|
561
570
|
*
|
|
562
571
|
* Reactive state (`state`, `user`, `error`) is suitable for UI
|
|
563
572
|
* observers; `signIn`, `verifyOtp`, and `signOut` return promises so
|
|
564
573
|
* the reference CLI can drive the flow imperatively.
|
|
565
574
|
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
575
|
+
* OTP verification is intentionally branch-explicit: existing members
|
|
576
|
+
* authenticate immediately, while first-run or incomplete accounts stop
|
|
577
|
+
* at `bootstrapRequired` until the caller chooses a username and calls
|
|
578
|
+
* `completeBootstrap()`.
|
|
579
|
+
*
|
|
580
|
+
* `completeBootstrap()` auto-provisions a fresh local-private-key signer
|
|
581
|
+
* via `SignerProvisioner` unless the caller passes or configures an
|
|
582
|
+
* explicit signer. Test harnesses use that override to keep the actor's
|
|
583
|
+
* signer stable across later dogfooding operations.
|
|
570
584
|
*/
|
|
571
585
|
declare function useAuth(options?: UseAuthOptions): UseAuthResult;
|
|
572
586
|
|
|
573
|
-
/**
|
|
574
|
-
* @deprecated Use `useAuth()` instead. `useAuthFlow` will be removed
|
|
575
|
-
* in a future release.
|
|
576
|
-
*/
|
|
577
|
-
declare function useAuthFlow(): {
|
|
578
|
-
readonly snapshot: xstate.MachineSnapshot<any, any, any, any, any, any, any, any>;
|
|
579
|
-
readonly send: (event: any) => void;
|
|
580
|
-
};
|
|
581
|
-
/**
|
|
582
|
-
* @deprecated Use `useAuth()` instead. `useAuthBootstrapFlow` will be
|
|
583
|
-
* removed in a future release.
|
|
584
|
-
*/
|
|
585
|
-
declare function useAuthBootstrapFlow(): {
|
|
586
|
-
readonly snapshot: xstate.MachineSnapshot<_capxul_sdk.AuthBootstrapFlowContext, {
|
|
587
|
-
readonly type: "ENTER_EMAIL";
|
|
588
|
-
readonly email: Email;
|
|
589
|
-
} | {
|
|
590
|
-
readonly type: "REQUEST_OTP";
|
|
591
|
-
} | {
|
|
592
|
-
readonly type: "ENTER_OTP";
|
|
593
|
-
readonly code: string;
|
|
594
|
-
} | {
|
|
595
|
-
readonly type: "VERIFY_OTP";
|
|
596
|
-
} | {
|
|
597
|
-
readonly type: "ENTER_USERNAME";
|
|
598
|
-
readonly username: Username;
|
|
599
|
-
} | {
|
|
600
|
-
readonly type: "COMPLETE_BOOTSTRAP";
|
|
601
|
-
} | {
|
|
602
|
-
readonly type: "BACK";
|
|
603
|
-
} | {
|
|
604
|
-
readonly type: "RESET";
|
|
605
|
-
} | {
|
|
606
|
-
readonly type: "SIGN_OUT";
|
|
607
|
-
}, {
|
|
608
|
-
[x: string]: xstate.ActorRefFromLogic<xstate.PromiseActorLogic<void, void, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<_capxul_sdk.CompleteBootstrapResult, {
|
|
609
|
-
bootstrapToken: _capxul_sdk.AuthBootstrapToken;
|
|
610
|
-
username: Username;
|
|
611
|
-
}, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<void, {
|
|
612
|
-
email: Email;
|
|
613
|
-
}, xstate.EventObject>> | xstate.ActorRefFromLogic<xstate.PromiseActorLogic<_capxul_sdk.VerifyOtpResult, {
|
|
614
|
-
email: Email;
|
|
615
|
-
code: string;
|
|
616
|
-
}, xstate.EventObject>> | undefined;
|
|
617
|
-
}, "email" | "error" | "bootstrap_required" | "authenticated" | "sending_otp" | "otp_requested" | "signing_out" | "verifying_otp" | "completing_bootstrap", string, xstate.NonReducibleUnknown, xstate.MetaObject, {
|
|
618
|
-
id: "authBootstrap";
|
|
619
|
-
states: {
|
|
620
|
-
readonly email: {};
|
|
621
|
-
readonly sending_otp: {};
|
|
622
|
-
readonly otp_requested: {};
|
|
623
|
-
readonly verifying_otp: {};
|
|
624
|
-
readonly bootstrap_required: {};
|
|
625
|
-
readonly completing_bootstrap: {};
|
|
626
|
-
readonly authenticated: {};
|
|
627
|
-
readonly signing_out: {};
|
|
628
|
-
readonly error: {};
|
|
629
|
-
};
|
|
630
|
-
}>;
|
|
631
|
-
readonly send: (event: {
|
|
632
|
-
readonly type: "ENTER_EMAIL";
|
|
633
|
-
readonly email: Email;
|
|
634
|
-
} | {
|
|
635
|
-
readonly type: "REQUEST_OTP";
|
|
636
|
-
} | {
|
|
637
|
-
readonly type: "ENTER_OTP";
|
|
638
|
-
readonly code: string;
|
|
639
|
-
} | {
|
|
640
|
-
readonly type: "VERIFY_OTP";
|
|
641
|
-
} | {
|
|
642
|
-
readonly type: "ENTER_USERNAME";
|
|
643
|
-
readonly username: Username;
|
|
644
|
-
} | {
|
|
645
|
-
readonly type: "COMPLETE_BOOTSTRAP";
|
|
646
|
-
} | {
|
|
647
|
-
readonly type: "BACK";
|
|
648
|
-
} | {
|
|
649
|
-
readonly type: "RESET";
|
|
650
|
-
} | {
|
|
651
|
-
readonly type: "SIGN_OUT";
|
|
652
|
-
}) => void;
|
|
653
|
-
};
|
|
654
587
|
declare function useOnboardingFlow(): {
|
|
655
588
|
readonly snapshot: xstate.MachineSnapshot<any, any, any, any, any, any, any, any>;
|
|
656
589
|
readonly send: (event: any) => void;
|
|
@@ -737,4 +670,4 @@ declare function injectedConnector(options?: InjectedConnectorOptions): CapxulCo
|
|
|
737
670
|
*/
|
|
738
671
|
declare function localPrivateKeyConnector(options: LocalPrivateKeyConnectorOptions): CapxulConnector;
|
|
739
672
|
|
|
740
|
-
export { type AuthState, CapxulClientProvider, type CapxulClientProviderProps, type CapxulConnector, type CapxulConnectorKind, type CapxulConnectorSession, CapxulProvider, type CapxulProviderProps, CapxulTransportProvider, type CapxulTransportProviderProps, type DocumentsFilters, type InjectedConnectorOptions, type LocalPrivateKeyConnectorOptions, type OrgDocumentsFilters, type OrgScopedFilters, type OwnerRef, type OwnerScopedFilters, type PaginationFilters, type PaymentsFilters, type QueryResult, type TransfersFilters, type UseApiKeyArgs, type UseAuthOptions, type UseAuthResult, type UseBalanceLedgerEntryArgs, type UseExternalAccountArgs, type UseMemberArgs, type UseTokenTransferArgs, type User, type VirtualAccountsFilters, type VirtualCardsFilters, type WithdrawalsFilters, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth,
|
|
673
|
+
export { type AuthState, type AuthVerifyResult, type BootstrapContinuation, CapxulClientProvider, type CapxulClientProviderProps, type CapxulConnector, type CapxulConnectorKind, type CapxulConnectorSession, CapxulProvider, type CapxulProviderProps, CapxulTransportProvider, type CapxulTransportProviderProps, type DocumentsFilters, type InjectedConnectorOptions, type LocalPrivateKeyConnectorOptions, type OrgDocumentsFilters, type OrgScopedFilters, type OwnerRef, type OwnerScopedFilters, type PaginationFilters, type PaymentsFilters, type QueryResult, type TransfersFilters, type UseApiKeyArgs, type UseAuthOptions, type UseAuthResult, type UseBalanceLedgerEntryArgs, type UseExternalAccountArgs, type UseMemberArgs, type UseTokenTransferArgs, type User, type VirtualAccountsFilters, type VirtualCardsFilters, type WithdrawalsFilters, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth, useBalanceLedger, useBalanceLedgerEntry, useCapxul, useCapxulStatus, useDocument, useDocuments, useExternalAccount, useExternalAccounts, useInviteMember, useKycProfile, useMe, useMember, useMembers, useOnboardingFlow, useOperation, useOrgBalanceLedger, useOrgDocuments, useOrgPayments, useOrgTransfers, useOrgWithdrawals, useOrganization, useOrganizations, usePayment, usePayments, useProvisioningFlow, useRemoveMember, useResendInvitation, useRevokeMember, useSafe, useSubAccount, useSubAccounts, useTokenTransfer, useTokenTransfers, useTransfer, useTransfers, useTreasury, useUpdateMemberRole, useVirtualAccount, useVirtualAccounts, useVirtualCard, useVirtualCards, useWebhookEndpoint, useWebhookEndpoints, useWebhookEvent, useWithdrawal, useWithdrawals };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createContext, useContext, useSyncExternalStore, useMemo, useEffect, useState, useCallback } from 'react';
|
|
3
|
-
import { makeHttpTransport, createCapxulClient, AuthService, CapxulError as CapxulError$1, SignerProvisioner
|
|
2
|
+
import { createContext, useContext, useSyncExternalStore, useMemo, useEffect, useState, useRef, useCallback } from 'react';
|
|
3
|
+
import { makeHttpTransport, createCapxulClient, AuthService, CapxulError as CapxulError$1, SignerProvisioner } from '@capxul/sdk';
|
|
4
4
|
import { QueryClient, QueryClientProvider, useQuery, useMutation } from '@tanstack/react-query';
|
|
5
5
|
import { jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { ConvexReactClient } from 'convex/react';
|
|
@@ -857,12 +857,62 @@ function useResendInvitation() {
|
|
|
857
857
|
}
|
|
858
858
|
});
|
|
859
859
|
}
|
|
860
|
+
|
|
861
|
+
// ../observability/src/debug-log.ts
|
|
862
|
+
function isDevelopmentBuild() {
|
|
863
|
+
if (typeof process === "undefined") {
|
|
864
|
+
return false;
|
|
865
|
+
}
|
|
866
|
+
return process.env?.NODE_ENV === "development" || process.env?.NODE_ENV === "test";
|
|
867
|
+
}
|
|
868
|
+
function debugLog(line) {
|
|
869
|
+
if (!isDevelopmentBuild()) return;
|
|
870
|
+
if (typeof globalThis !== "undefined" && "window" in globalThis && typeof console?.info === "function") {
|
|
871
|
+
console.info(line);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
if (typeof process !== "undefined" && typeof process.stderr?.write === "function") {
|
|
875
|
+
process.stderr.write(`${line}
|
|
876
|
+
`);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function formatDebugValue(value) {
|
|
880
|
+
if (value === void 0 || value === "") return "";
|
|
881
|
+
if (typeof value === "string") return value;
|
|
882
|
+
try {
|
|
883
|
+
return JSON.stringify(value);
|
|
884
|
+
} catch {
|
|
885
|
+
return String(value);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function track(...args) {
|
|
889
|
+
const [name, props] = args;
|
|
890
|
+
debugLog(`[TRACK] ${name} ${formatDebugValue(props ?? "")}`);
|
|
891
|
+
}
|
|
892
|
+
function formatDebugValue2(value) {
|
|
893
|
+
if (value === void 0 || value === "") return "";
|
|
894
|
+
if (typeof value === "string") return value;
|
|
895
|
+
try {
|
|
896
|
+
return JSON.stringify(value);
|
|
897
|
+
} catch {
|
|
898
|
+
return String(value);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
function identify(userId, traits) {
|
|
902
|
+
debugLog(`[IDENTIFY] ${userId} ${formatDebugValue2(traits ?? "")}`);
|
|
903
|
+
}
|
|
904
|
+
function resetIdentity() {
|
|
905
|
+
}
|
|
860
906
|
function useAuth(options) {
|
|
861
907
|
const authService = useAuthService();
|
|
862
908
|
const signerProvisioner = useMemoizedSignerProvisioner();
|
|
863
909
|
const injectedSigner = options?.signer;
|
|
864
910
|
const [state, setState] = useState("idle");
|
|
865
911
|
const [user, setUser] = useState(null);
|
|
912
|
+
const [bootstrap, setBootstrap] = useState(
|
|
913
|
+
null
|
|
914
|
+
);
|
|
915
|
+
const bootstrapRef = useRef(null);
|
|
866
916
|
const [error, setError] = useState(null);
|
|
867
917
|
const signIn = useCallback(
|
|
868
918
|
async (email) => {
|
|
@@ -870,9 +920,13 @@ function useAuth(options) {
|
|
|
870
920
|
setError(null);
|
|
871
921
|
try {
|
|
872
922
|
await authService.sendOtp(email);
|
|
923
|
+
track("auth_otp_requested", {
|
|
924
|
+
email_domain: emailDomain(email)
|
|
925
|
+
});
|
|
873
926
|
setState("awaitingOtp");
|
|
874
927
|
} catch (err) {
|
|
875
928
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
929
|
+
trackAuthFailure("otp_request", wrapped);
|
|
876
930
|
setError(wrapped);
|
|
877
931
|
setState("error");
|
|
878
932
|
throw wrapped;
|
|
@@ -887,25 +941,96 @@ function useAuth(options) {
|
|
|
887
941
|
try {
|
|
888
942
|
const result = await authService.verifyOtp(email, otp);
|
|
889
943
|
if (result.kind === "existing_member") {
|
|
890
|
-
|
|
944
|
+
track("auth_otp_verified", {
|
|
945
|
+
email_domain: emailDomain(result.session.email),
|
|
946
|
+
branch: "existing_member"
|
|
947
|
+
});
|
|
948
|
+
const nextUser = {
|
|
891
949
|
account: result.account,
|
|
892
950
|
username: result.username,
|
|
893
951
|
safe: result.safe,
|
|
894
952
|
session: result.session
|
|
895
953
|
};
|
|
896
|
-
setUser(
|
|
954
|
+
setUser(nextUser);
|
|
955
|
+
setBootstrap(null);
|
|
956
|
+
bootstrapRef.current = null;
|
|
957
|
+
identify(result.session.authUserId, {
|
|
958
|
+
auth_branch: "existing_member"
|
|
959
|
+
});
|
|
960
|
+
track("auth_session_ready", {
|
|
961
|
+
branch: "existing_member",
|
|
962
|
+
has_convex_jwt: typeof result.session.convexJwt === "string"
|
|
963
|
+
});
|
|
897
964
|
setState("authenticated");
|
|
898
|
-
return
|
|
965
|
+
return {
|
|
966
|
+
kind: "existing_member",
|
|
967
|
+
session: result.session,
|
|
968
|
+
user: nextUser
|
|
969
|
+
};
|
|
899
970
|
}
|
|
971
|
+
const nextBootstrap = {
|
|
972
|
+
bootstrapToken: result.bootstrapToken,
|
|
973
|
+
email: result.email,
|
|
974
|
+
reason: result.reason,
|
|
975
|
+
username: result.username,
|
|
976
|
+
session: result.session
|
|
977
|
+
};
|
|
978
|
+
setUser(null);
|
|
979
|
+
setBootstrap(nextBootstrap);
|
|
980
|
+
bootstrapRef.current = nextBootstrap;
|
|
981
|
+
track("auth_otp_verified", {
|
|
982
|
+
email_domain: emailDomain(result.session.email),
|
|
983
|
+
branch: "bootstrap_required"
|
|
984
|
+
});
|
|
985
|
+
track("auth_bootstrap_required", {
|
|
986
|
+
reason: result.reason,
|
|
987
|
+
has_suggested_username: result.username !== void 0,
|
|
988
|
+
has_convex_jwt: typeof result.session.convexJwt === "string"
|
|
989
|
+
});
|
|
990
|
+
setState("bootstrapRequired");
|
|
991
|
+
return {
|
|
992
|
+
kind: "bootstrap_required",
|
|
993
|
+
session: result.session,
|
|
994
|
+
bootstrap: nextBootstrap
|
|
995
|
+
};
|
|
996
|
+
} catch (err) {
|
|
997
|
+
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
998
|
+
trackAuthFailure("otp_verify", wrapped);
|
|
999
|
+
setError(wrapped);
|
|
1000
|
+
setState("error");
|
|
1001
|
+
throw wrapped;
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
[authService]
|
|
1005
|
+
);
|
|
1006
|
+
const completeBootstrap = useCallback(
|
|
1007
|
+
async (username, signer) => {
|
|
1008
|
+
const pendingBootstrap = bootstrapRef.current;
|
|
1009
|
+
if (!pendingBootstrap) {
|
|
1010
|
+
const missing = new Error(
|
|
1011
|
+
"completeBootstrap requires a prior bootstrap_required OTP result."
|
|
1012
|
+
);
|
|
1013
|
+
track("auth_session_lost", { step: "complete_bootstrap" });
|
|
1014
|
+
setError(missing);
|
|
1015
|
+
setState("error");
|
|
1016
|
+
throw missing;
|
|
1017
|
+
}
|
|
1018
|
+
setError(null);
|
|
1019
|
+
track("auth_username_submitted", {
|
|
1020
|
+
has_suggested_username: pendingBootstrap.username !== void 0
|
|
1021
|
+
});
|
|
1022
|
+
setState("provisioningSigner");
|
|
1023
|
+
try {
|
|
1024
|
+
const signerKind = signer ? "provided" : injectedSigner ? "configured" : "generated";
|
|
1025
|
+
const selectedSigner = signer ?? injectedSigner ?? signerProvisioner.provision().signer;
|
|
1026
|
+
track("auth_signer_provisioned", { signer_kind: signerKind });
|
|
900
1027
|
setState("bootstrapping");
|
|
901
|
-
const signer = injectedSigner ?? signerProvisioner.provision().signer;
|
|
902
|
-
const username = result.username ?? generateUsernameFromEmail(result.email);
|
|
903
1028
|
const bootstrapResult = await authService.completeBootstrap(
|
|
904
1029
|
{
|
|
905
|
-
bootstrapToken:
|
|
1030
|
+
bootstrapToken: pendingBootstrap.bootstrapToken,
|
|
906
1031
|
username
|
|
907
1032
|
},
|
|
908
|
-
|
|
1033
|
+
selectedSigner
|
|
909
1034
|
);
|
|
910
1035
|
const nextUser = {
|
|
911
1036
|
account: bootstrapResult.account,
|
|
@@ -913,26 +1038,47 @@ function useAuth(options) {
|
|
|
913
1038
|
safe: bootstrapResult.safe,
|
|
914
1039
|
session: bootstrapResult.session
|
|
915
1040
|
};
|
|
1041
|
+
track("auth_safe_provisioned", {
|
|
1042
|
+
safe_status: bootstrapResult.safe.status
|
|
1043
|
+
});
|
|
916
1044
|
setUser(nextUser);
|
|
1045
|
+
setBootstrap(null);
|
|
1046
|
+
bootstrapRef.current = null;
|
|
1047
|
+
identify(bootstrapResult.session.authUserId, {
|
|
1048
|
+
auth_branch: "bootstrap_required"
|
|
1049
|
+
});
|
|
1050
|
+
track("auth_bootstrap_completed", {
|
|
1051
|
+
reason: pendingBootstrap.reason
|
|
1052
|
+
});
|
|
1053
|
+
track("auth_session_ready", {
|
|
1054
|
+
branch: "bootstrap_required",
|
|
1055
|
+
has_convex_jwt: typeof bootstrapResult.session.convexJwt === "string"
|
|
1056
|
+
});
|
|
917
1057
|
setState("authenticated");
|
|
918
|
-
return
|
|
1058
|
+
return nextUser;
|
|
919
1059
|
} catch (err) {
|
|
920
1060
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
1061
|
+
trackAuthFailure("complete_bootstrap", wrapped);
|
|
921
1062
|
setError(wrapped);
|
|
922
1063
|
setState("error");
|
|
923
1064
|
throw wrapped;
|
|
924
1065
|
}
|
|
925
1066
|
},
|
|
926
|
-
[authService,
|
|
1067
|
+
[authService, injectedSigner, signerProvisioner]
|
|
927
1068
|
);
|
|
928
1069
|
const signOut = useCallback(async () => {
|
|
929
1070
|
setError(null);
|
|
930
1071
|
try {
|
|
931
1072
|
await authService.signOut();
|
|
1073
|
+
track("auth_signed_out");
|
|
1074
|
+
resetIdentity();
|
|
932
1075
|
setUser(null);
|
|
1076
|
+
setBootstrap(null);
|
|
1077
|
+
bootstrapRef.current = null;
|
|
933
1078
|
setState("idle");
|
|
934
1079
|
} catch (err) {
|
|
935
1080
|
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
1081
|
+
trackAuthFailure("sign_out", wrapped);
|
|
936
1082
|
setError(wrapped);
|
|
937
1083
|
setState("error");
|
|
938
1084
|
throw wrapped;
|
|
@@ -942,48 +1088,46 @@ function useAuth(options) {
|
|
|
942
1088
|
() => ({
|
|
943
1089
|
state,
|
|
944
1090
|
user,
|
|
1091
|
+
bootstrap,
|
|
945
1092
|
error,
|
|
946
1093
|
signIn,
|
|
947
1094
|
verifyOtp,
|
|
1095
|
+
completeBootstrap,
|
|
948
1096
|
signOut
|
|
949
1097
|
}),
|
|
950
|
-
[
|
|
1098
|
+
[
|
|
1099
|
+
state,
|
|
1100
|
+
user,
|
|
1101
|
+
bootstrap,
|
|
1102
|
+
error,
|
|
1103
|
+
signIn,
|
|
1104
|
+
verifyOtp,
|
|
1105
|
+
completeBootstrap,
|
|
1106
|
+
signOut
|
|
1107
|
+
]
|
|
951
1108
|
);
|
|
952
1109
|
}
|
|
953
1110
|
function useMemoizedSignerProvisioner() {
|
|
954
1111
|
const [provisioner] = useState(() => new SignerProvisioner());
|
|
955
1112
|
return provisioner;
|
|
956
1113
|
}
|
|
957
|
-
function
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
if (/^[0-9]/.test(sanitized)) {
|
|
961
|
-
sanitized = "u" + sanitized;
|
|
962
|
-
}
|
|
963
|
-
if (sanitized.length < 3) {
|
|
964
|
-
sanitized = sanitized + "_".repeat(3 - sanitized.length);
|
|
965
|
-
}
|
|
966
|
-
if (sanitized.length > 30) {
|
|
967
|
-
sanitized = sanitized.slice(0, 30);
|
|
968
|
-
}
|
|
969
|
-
try {
|
|
970
|
-
return toUsername(sanitized);
|
|
971
|
-
} catch {
|
|
972
|
-
const fallback = `user_${Date.now() % 1e6}`;
|
|
973
|
-
return toUsername(fallback);
|
|
974
|
-
}
|
|
1114
|
+
function emailDomain(email) {
|
|
1115
|
+
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
1116
|
+
return domain && /^[a-z0-9.-]+$/.test(domain) ? domain : "unknown";
|
|
975
1117
|
}
|
|
976
|
-
function
|
|
977
|
-
const
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1118
|
+
function trackAuthFailure(step, error) {
|
|
1119
|
+
const reason = errorCode(error);
|
|
1120
|
+
if (reason === "PERMISSION_DENIED" || reason === "AUTHZ_DENIED") {
|
|
1121
|
+
track("authz_denied", { step, reason });
|
|
1122
|
+
}
|
|
1123
|
+
track("auth_failed", {
|
|
1124
|
+
step,
|
|
1125
|
+
reason
|
|
1126
|
+
});
|
|
981
1127
|
}
|
|
982
|
-
function
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
const [snapshot, send] = useActor(machine);
|
|
986
|
-
return { snapshot, send };
|
|
1128
|
+
function errorCode(error) {
|
|
1129
|
+
const code = error.code;
|
|
1130
|
+
return typeof code === "string" && code.length > 0 ? code : error.name || "Error";
|
|
987
1131
|
}
|
|
988
1132
|
function useOnboardingFlow() {
|
|
989
1133
|
const client = useCapxul();
|
|
@@ -1083,4 +1227,4 @@ function validateAndNormalizeEvmAddress(field, raw) {
|
|
|
1083
1227
|
}
|
|
1084
1228
|
}
|
|
1085
1229
|
|
|
1086
|
-
export { CapxulClientProvider, CapxulProvider, CapxulTransportProvider, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth,
|
|
1230
|
+
export { CapxulClientProvider, CapxulProvider, CapxulTransportProvider, createCapxulConfig, injectedConnector, localPrivateKeyConnector, useAcceptInvitation, useAccount, useAccountBalanceLedger, useApiKey, useApiKeys, useAuth, useBalanceLedger, useBalanceLedgerEntry, useCapxul, useCapxulStatus, useDocument, useDocuments, useExternalAccount, useExternalAccounts, useInviteMember, useKycProfile, useMe, useMember, useMembers, useOnboardingFlow, useOperation, useOrgBalanceLedger, useOrgDocuments, useOrgPayments, useOrgTransfers, useOrgWithdrawals, useOrganization, useOrganizations, usePayment, usePayments, useProvisioningFlow, useRemoveMember, useResendInvitation, useRevokeMember, useSafe, useSubAccount, useSubAccounts, useTokenTransfer, useTokenTransfers, useTransfer, useTransfers, useTreasury, useUpdateMemberRole, useVirtualAccount, useVirtualAccounts, useVirtualCard, useVirtualCards, useWebhookEndpoint, useWebhookEndpoints, useWebhookEvent, useWithdrawal, useWithdrawals };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/sdk-react",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.4",
|
|
4
4
|
"description": "React provider + hooks for the @capxul/sdk headless client.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@capxul/sdk": "0.2.0-alpha.
|
|
49
|
+
"@capxul/sdk": "0.2.0-alpha.4"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@tanstack/react-query": "^5",
|