@capxul/sdk 0.1.0-alpha.8 → 0.1.0-alpha.9
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 +14 -0
- package/dist/{client-ByzDfG98.d.ts → client-ChZrdf3R.d.ts} +197 -6
- package/dist/{client-DDAVWtzJ.d.cts → client-DG6ODWu6.d.cts} +197 -6
- package/dist/client.cjs +418 -10
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +418 -10
- package/dist/index.cjs +419 -10
- package/dist/index.d.cts +14 -35
- package/dist/index.d.ts +14 -35
- package/dist/index.js +419 -11
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,36 +1,15 @@
|
|
|
1
|
-
import { S as Session, C as CapxulClient, A as AccountProvisionPersonalInput } from './client-
|
|
2
|
-
export {
|
|
1
|
+
import { S as Session, C as CapxulError$1, a as CapxulClient, A as AccountProvisionPersonalInput } from './client-ChZrdf3R.js';
|
|
2
|
+
export { b as AccountsClient, c as ApiKeyCreateResult, d as ApiKeysClient, e as AuthBootstrapFlowContext, f as AuthBootstrapFlowError, g as AuthBootstrapFlowEvent, h as AuthBootstrapReason, i as AuthBootstrapToken, j as AuthClient, k as AuthSessionStore, B as BrowserCapxulConfig, l as CapxulAuthConfig, m as CapxulConfig, n as CapxulDataClient, o as CapxulFlowFactories, p as CapxulSigningConfig, q as CompleteBootstrapInput, r as CompleteBootstrapResult, D as DocumentsClient, E as ExternalAccountsClient, H as HttpTransport, L as LocalPrivateKeySignerProvider, M as MeClient, O as OperationsClient, s as OrgDocumentsClient, t as OrgPaymentsClient, u as OrgSafesClient, v as OrgTransfersClient, w as OrgTreasuryClient, x as OrgWithdrawalsClient, y as OrganizationsClient, P as PaymentsClient, z as SubAccountsClient, T as TokenTransfer, F as TokenTransferId, G as TokenTransfersClient, I as TokenTransfersListInput, J as TokenTransfersListPage, K as TokenTransfersRetrieveInput, N as TransfersClient, Q as TransportRuntime, R as TransportState, V as VerifyOtpResult, U as VirtualAccountsClient, W as VirtualCardsClient, X as WebhookEndpointCreateResult, Y as WebhookEndpointsClient, Z as WebhookEventsClient, _ as WithdrawalsClient, $ as createAuthBootstrapFlowMachine, a0 as createCapxulClient, a1 as makeHttpTransport, a2 as toTokenTransferId } from './client-ChZrdf3R.js';
|
|
3
3
|
import * as xstate from 'xstate';
|
|
4
4
|
import { E as Email, U as Username, O as OperationId, N as NextAction } from './next-action-DkrwXYay.js';
|
|
5
5
|
export { A as AccountId, a as ApiKeyId, B as BalanceLedgerEntryId, C as CorrelationId, D as DocumentId, b as ExternalAccountId, K as KybProfileId, c as KycProfileId, M as MemberId, d as OrganizationId, P as PaymentId, e as PhoneNumber, S as SafeId, f as SubAccountId, T as TransactionIntentId, g as TransferId, h as TreasuryId, V as VirtualAccountId, i as VirtualCardId, W as WebhookEndpointId, j as WebhookEventId, k as WithdrawalId, t as toAccountId, l as toApiKeyId, m as toBalanceLedgerEntryId, n as toDocumentId, o as toEmail, p as toExternalAccountId, q as toKybProfileId, r as toKycProfileId, s as toMemberId, u as toOperationId, v as toOrganizationId, w as toPaymentId, x as toPhoneNumber, y as toSafeId, z as toSubAccountId, F as toTransferId, G as toTreasuryId, H as toUsername, I as toVirtualAccountId, J as toVirtualCardId, L as toWebhookEndpointId, Q as toWebhookEventId, R as toWithdrawalId } from './next-action-DkrwXYay.js';
|
|
6
|
-
import { C as CapxulError
|
|
6
|
+
import { C as CapxulError, a as CapxulErrorCode } from './errors-QHD5Tlok.js';
|
|
7
7
|
export { b as CapxulErrorDetails, c as CapxulErrorEnvelope, d as CapxulResult } from './errors-QHD5Tlok.js';
|
|
8
8
|
import { A as Account } from './types-PM4AQRLP.js';
|
|
9
9
|
export { a as AccountLookupResult, b as ApiKey, c as ApiKeyEnvironment, d as ApiKeyType, B as BalanceLedgerEntry, e as BankStatementDocument, C as CreatePaymentResult, f as CreateTransferResult, g as CreateWithdrawalResult, D as Document, E as ExternalAccount, h as ExternalAccountKind, I as InvoiceDocument, K as KybProfile, i as KycProfile, j as KycUploadDocument, L as List, M as Member, k as Money, O as Operation, l as OperationStatus, m as OperationSummary, n as Organization, P as PageInfo, o as Payment, p as PaymentParty, q as PaymentStatus, r as PayrollRunDocument, s as PayrollScheduleDocument, R as ReceiptDocument, S as Safe, t as Scope, u as Settlement, v as SubAccount, w as SubAccountOwnerKind, T as TaxFormDocument, x as TimestampIso, y as Transfer, z as TransferCustody, F as TransferEndpoint, G as TransferFx, H as TransferStatus, J as Treasury, U as UserIdentifier, V as VirtualAccount, N as VirtualAccountOwnerKind, Q as VirtualCard, W as VirtualCardLimits, X as VirtualCardOwnerKind, Y as WebhookEndpoint, Z as WebhookEvent, _ as Withdrawal, $ as WithdrawalStatus } from './types-PM4AQRLP.js';
|
|
10
10
|
import { Account as Account$1 } from 'viem';
|
|
11
11
|
export { WebhookVerificationOptions, WebhookVerificationResult, verifyWebhook } from './webhooks.js';
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Unified error type used across the entire stack: backend, SDK, and frontend.
|
|
15
|
-
* One class, one set of codes, one language.
|
|
16
|
-
*
|
|
17
|
-
* Backend throws CapxulError → withErrorBoundary serializes to ConvexError →
|
|
18
|
-
* SDK deserializes back to CapxulError → frontend routes on err.code.
|
|
19
|
-
*/
|
|
20
|
-
type CapxulErrorCode = "NOT_AUTHENTICATED" | "EMAIL_DELIVERY_FAILED" | "API_KEY_INVALID" | "API_KEY_EXPIRED" | "PROFILE_NOT_FOUND" | "SMART_ACCOUNT_MISSING" | "PLAYER_NOT_FOUND" | "ACCOUNT_NOT_FOUND" | "PROVIDER_ERROR" | "INVALID_INPUT" | "ENV_MISSING" | "NOT_IMPLEMENTED" | "VERIFICATION_REQUIRED" | "INSUFFICIENT_BALANCE" | "INVALID_RECIPIENT" | "TRANSACTION_FAILED" | "RATE_LIMITED" | "NETWORK_ERROR" | "PERMISSION_DENIED" | "IDEMPOTENCY_CONFLICT" | "NOT_FOUND" | "OPERATION_CANCELED" | "OPERATION_TIMEOUT" | "ACTION_REQUIRED" | "KYC_REQUIRED" | "POLICY_DENIED" | "SAFE_NOT_READY" | "PROVIDER_UNAVAILABLE" | "PROVIDER_REJECTED" | "RECONCILIATION_FAILED" | "INTERNAL_ERROR" | "QUOTE_EXPIRED" | "QUOTE_NOT_FOUND" | "UNKNOWN";
|
|
21
|
-
declare class CapxulError extends Error {
|
|
22
|
-
readonly code: CapxulErrorCode;
|
|
23
|
-
readonly details?: Record<string, unknown>;
|
|
24
|
-
readonly correlationId?: string;
|
|
25
|
-
readonly layer?: string;
|
|
26
|
-
constructor(code: CapxulErrorCode, message: string, options?: {
|
|
27
|
-
cause?: unknown;
|
|
28
|
-
details?: Record<string, unknown>;
|
|
29
|
-
correlationId?: string;
|
|
30
|
-
layer?: string;
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
13
|
/**
|
|
35
14
|
* Auth flow errors may originate from two CapxulError surfaces:
|
|
36
15
|
* - the SDK-local generic `CapxulError<Codes>` returned by
|
|
@@ -42,7 +21,7 @@ declare class CapxulError extends Error {
|
|
|
42
21
|
* union keeps either origin assignable to `context.error` without an
|
|
43
22
|
* `as` cast at the call site.
|
|
44
23
|
*/
|
|
45
|
-
type AuthFlowError = CapxulError
|
|
24
|
+
type AuthFlowError = CapxulError | CapxulError$1;
|
|
46
25
|
type AuthFlowContext = {
|
|
47
26
|
readonly email: Email | null;
|
|
48
27
|
readonly session: Session | null;
|
|
@@ -118,7 +97,7 @@ declare function createAuthFlowMachine(client: CapxulClient): xstate.StateMachin
|
|
|
118
97
|
} | {
|
|
119
98
|
type: "trackSignedOut";
|
|
120
99
|
params: unknown;
|
|
121
|
-
}, never, never, "
|
|
100
|
+
}, never, never, "idle" | "authenticated" | "error" | "sending_otp" | "otp_requested" | "verifying" | "signing_out", string, xstate.NonReducibleUnknown, xstate.NonReducibleUnknown, xstate.EventObject, xstate.MetaObject, {
|
|
122
101
|
id: "auth";
|
|
123
102
|
states: {
|
|
124
103
|
readonly idle: {};
|
|
@@ -141,7 +120,7 @@ declare function createAuthFlowMachine(client: CapxulClient): xstate.StateMachin
|
|
|
141
120
|
*
|
|
142
121
|
* Both share `.code`, `.message`, `.details`, and extend `Error`.
|
|
143
122
|
*/
|
|
144
|
-
type ProvisioningFlowError = CapxulError
|
|
123
|
+
type ProvisioningFlowError = CapxulError | CapxulError$1;
|
|
145
124
|
type ProvisioningFlowContext = {
|
|
146
125
|
readonly input: AccountProvisionPersonalInput | null;
|
|
147
126
|
readonly account: Account | null;
|
|
@@ -218,7 +197,7 @@ declare function createProvisioningMachine(client: CapxulClient): xstate.StateMa
|
|
|
218
197
|
}, {
|
|
219
198
|
type: "hasInput";
|
|
220
199
|
params: unknown;
|
|
221
|
-
}, never, "
|
|
200
|
+
}, never, "idle" | "error" | "done" | "starting" | "running", string, {
|
|
222
201
|
readonly input: AccountProvisionPersonalInput;
|
|
223
202
|
}, {
|
|
224
203
|
readonly account: Account;
|
|
@@ -248,7 +227,7 @@ declare function createProvisioningMachine(client: CapxulClient): xstate.StateMa
|
|
|
248
227
|
*
|
|
249
228
|
* Both share `.code`, `.message`, `.details`, and extend `Error`.
|
|
250
229
|
*/
|
|
251
|
-
type OnboardingFlowError = CapxulError
|
|
230
|
+
type OnboardingFlowError = CapxulError | CapxulError$1;
|
|
252
231
|
/** Subjects supported by the onboarding flow. */
|
|
253
232
|
type OnboardingSubjectKind = "account" | "organization";
|
|
254
233
|
/**
|
|
@@ -326,7 +305,7 @@ declare function createOnboardingFlowMachine(client: CapxulClient): xstate.State
|
|
|
326
305
|
}, {
|
|
327
306
|
type: "hasInput";
|
|
328
307
|
params: unknown;
|
|
329
|
-
}, never, "
|
|
308
|
+
}, never, "idle" | "error" | "done" | "starting" | "running", string, {
|
|
330
309
|
readonly input: AccountProvisionPersonalInput;
|
|
331
310
|
}, {
|
|
332
311
|
readonly account: Account;
|
|
@@ -368,7 +347,7 @@ declare function createOnboardingFlowMachine(client: CapxulClient): xstate.State
|
|
|
368
347
|
}, {
|
|
369
348
|
type: "hasInput";
|
|
370
349
|
params: unknown;
|
|
371
|
-
}, never, "
|
|
350
|
+
}, never, "idle" | "error" | "done" | "starting" | "running", string, {
|
|
372
351
|
readonly input: AccountProvisionPersonalInput;
|
|
373
352
|
}, {
|
|
374
353
|
readonly account: Account;
|
|
@@ -438,7 +417,7 @@ declare function createOnboardingFlowMachine(client: CapxulClient): xstate.State
|
|
|
438
417
|
} | {
|
|
439
418
|
type: "childReportedError";
|
|
440
419
|
params: unknown;
|
|
441
|
-
}, never, "
|
|
420
|
+
}, never, "action_required" | "provisioning" | "error" | "profile" | "complete", string, xstate.NonReducibleUnknown, xstate.NonReducibleUnknown, xstate.EventObject, xstate.MetaObject, {
|
|
442
421
|
id: "onboarding";
|
|
443
422
|
states: {
|
|
444
423
|
readonly profile: {};
|
|
@@ -461,8 +440,8 @@ declare function createOnboardingFlowMachine(client: CapxulClient): xstate.State
|
|
|
461
440
|
* No `default:` arm needed — the compile-time exhaustiveness check is
|
|
462
441
|
* the contract.
|
|
463
442
|
*/
|
|
464
|
-
declare function matchError<Codes extends CapxulErrorCode
|
|
465
|
-
[K in Codes]: (err: CapxulError
|
|
443
|
+
declare function matchError<Codes extends CapxulErrorCode, R>(err: CapxulError<Codes>, handlers: {
|
|
444
|
+
[K in Codes]: (err: CapxulError<K>) => R;
|
|
466
445
|
}): R;
|
|
467
446
|
/**
|
|
468
447
|
* Exhaustive resource-status dispatch per CANON.md §4.44.
|
|
@@ -518,4 +497,4 @@ declare function tryCatch<T>(promise: Promise<T>): Promise<[Error, null] | [null
|
|
|
518
497
|
*/
|
|
519
498
|
declare function createLocalSigner(privateKey: `0x${string}`): Account$1;
|
|
520
499
|
|
|
521
|
-
export { Account, AccountProvisionPersonalInput, type AuthFlowContext, type AuthFlowError, type AuthFlowEvent, CapxulClient, CapxulError
|
|
500
|
+
export { Account, AccountProvisionPersonalInput, type AuthFlowContext, type AuthFlowError, type AuthFlowEvent, CapxulClient, CapxulError, CapxulErrorCode, Email, NextAction, type OnboardingFlowContext, type OnboardingFlowError, type OnboardingFlowEvent, type OnboardingProfileInput, type OnboardingSubjectKind, OperationId, type ProvisioningFlowContext, type ProvisioningFlowError, type ProvisioningFlowEvent, type ProvisioningFlowInput, type ProvisioningFlowOutput, Session, Username, createAuthFlowMachine, createLocalSigner, createOnboardingFlowMachine, createProvisioningMachine as createProvisioningFlowMachine, matchAction, matchError, matchStatus, tryCatch };
|
package/dist/index.js
CHANGED
|
@@ -1125,7 +1125,68 @@ function createAuthClient(config = {}) {
|
|
|
1125
1125
|
];
|
|
1126
1126
|
}
|
|
1127
1127
|
}
|
|
1128
|
-
|
|
1128
|
+
if (!dataClient) {
|
|
1129
|
+
return [
|
|
1130
|
+
new CapxulError({
|
|
1131
|
+
code: "NOT_AUTHENTICATED",
|
|
1132
|
+
message: "Auth bootstrap requires an authenticated Convex data client."
|
|
1133
|
+
}),
|
|
1134
|
+
null
|
|
1135
|
+
];
|
|
1136
|
+
}
|
|
1137
|
+
try {
|
|
1138
|
+
const resolution = await dataClient.mutation(
|
|
1139
|
+
api.authBootstrap.resolveAfterOtp,
|
|
1140
|
+
{
|
|
1141
|
+
email: session.email,
|
|
1142
|
+
sessionToken: session.token
|
|
1143
|
+
}
|
|
1144
|
+
);
|
|
1145
|
+
if (resolution.kind === "existing_member") {
|
|
1146
|
+
return [null, { ...resolution, session }];
|
|
1147
|
+
}
|
|
1148
|
+
return [null, { ...resolution, session }];
|
|
1149
|
+
} catch (cause) {
|
|
1150
|
+
return [fromConvexError(cause), null];
|
|
1151
|
+
}
|
|
1152
|
+
},
|
|
1153
|
+
completeBootstrap: async (input) => {
|
|
1154
|
+
const session = sessionStore.get();
|
|
1155
|
+
const data = dataClient ?? config.data;
|
|
1156
|
+
if (!session || !data) {
|
|
1157
|
+
return [
|
|
1158
|
+
new CapxulError({
|
|
1159
|
+
code: "INVALID_INPUT",
|
|
1160
|
+
message: "completeBootstrap requires the OTP-verified session that issued the bootstrap token."
|
|
1161
|
+
}),
|
|
1162
|
+
null
|
|
1163
|
+
];
|
|
1164
|
+
}
|
|
1165
|
+
if (input.signerProvider.kind !== "local-private-key") {
|
|
1166
|
+
return [
|
|
1167
|
+
new CapxulError({
|
|
1168
|
+
code: "INVALID_INPUT",
|
|
1169
|
+
message: "completeBootstrap currently supports local-private-key signer providers only."
|
|
1170
|
+
}),
|
|
1171
|
+
null
|
|
1172
|
+
];
|
|
1173
|
+
}
|
|
1174
|
+
try {
|
|
1175
|
+
const result = await data.mutation(api.authBootstrap.completeBootstrap, {
|
|
1176
|
+
bootstrapToken: input.bootstrapToken,
|
|
1177
|
+
sessionToken: session.token,
|
|
1178
|
+
username: input.username,
|
|
1179
|
+
displayName: input.displayName,
|
|
1180
|
+
countryCode: input.countryCode,
|
|
1181
|
+
signerProvider: input.signerProvider
|
|
1182
|
+
});
|
|
1183
|
+
return [null, { kind: "authenticated", session, ...result }];
|
|
1184
|
+
} catch (cause) {
|
|
1185
|
+
return [
|
|
1186
|
+
fromConvexError(cause),
|
|
1187
|
+
null
|
|
1188
|
+
];
|
|
1189
|
+
}
|
|
1129
1190
|
},
|
|
1130
1191
|
getSession: async () => [null, sessionStore.get()],
|
|
1131
1192
|
signOut: async () => {
|
|
@@ -2484,7 +2545,7 @@ function createAuthFlowMachine(client) {
|
|
|
2484
2545
|
}),
|
|
2485
2546
|
verifyOtp: fromPromise(
|
|
2486
2547
|
async ({ input, signal }) => {
|
|
2487
|
-
const [error,
|
|
2548
|
+
const [error, result] = await client.auth.verifyOtp(
|
|
2488
2549
|
{
|
|
2489
2550
|
email: input.email,
|
|
2490
2551
|
otp: input.code
|
|
@@ -2492,7 +2553,14 @@ function createAuthFlowMachine(client) {
|
|
|
2492
2553
|
{ signal }
|
|
2493
2554
|
);
|
|
2494
2555
|
if (error) throw error;
|
|
2495
|
-
|
|
2556
|
+
if (result.kind === "bootstrap_required") {
|
|
2557
|
+
throw new CapxulError({
|
|
2558
|
+
code: "ACTION_REQUIRED",
|
|
2559
|
+
message: "OTP verified but auth bootstrap is required. Use createAuthBootstrapFlowMachine for product sign-up.",
|
|
2560
|
+
details: { reason: result.reason }
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2563
|
+
return result.session;
|
|
2496
2564
|
}
|
|
2497
2565
|
),
|
|
2498
2566
|
signOut: fromPromise(async () => {
|
|
@@ -2740,6 +2808,345 @@ function emailDomain(email) {
|
|
|
2740
2808
|
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
2741
2809
|
return domain || "unknown";
|
|
2742
2810
|
}
|
|
2811
|
+
var initialContext = {
|
|
2812
|
+
email: null,
|
|
2813
|
+
code: null,
|
|
2814
|
+
username: null,
|
|
2815
|
+
signerProvider: null,
|
|
2816
|
+
bootstrapToken: null,
|
|
2817
|
+
bootstrapReason: null,
|
|
2818
|
+
session: null,
|
|
2819
|
+
account: null,
|
|
2820
|
+
safe: null,
|
|
2821
|
+
error: null
|
|
2822
|
+
};
|
|
2823
|
+
function createAuthBootstrapFlowMachine(client) {
|
|
2824
|
+
return setup({
|
|
2825
|
+
types: {},
|
|
2826
|
+
actors: {
|
|
2827
|
+
sendOtp: fromPromise(async ({ input, signal }) => {
|
|
2828
|
+
const [error] = await client.auth.sendOtp(
|
|
2829
|
+
{ email: input.email },
|
|
2830
|
+
{ signal }
|
|
2831
|
+
);
|
|
2832
|
+
if (error) throw error;
|
|
2833
|
+
}),
|
|
2834
|
+
verifyOtp: fromPromise(
|
|
2835
|
+
async ({ input, signal }) => {
|
|
2836
|
+
const [error, result] = await client.auth.verifyOtp(
|
|
2837
|
+
{ email: input.email, otp: input.code },
|
|
2838
|
+
{ signal }
|
|
2839
|
+
);
|
|
2840
|
+
if (error) throw error;
|
|
2841
|
+
return result;
|
|
2842
|
+
}
|
|
2843
|
+
),
|
|
2844
|
+
completeBootstrap: fromPromise(async ({ input }) => {
|
|
2845
|
+
const [error, result] = await client.auth.completeBootstrap(input);
|
|
2846
|
+
if (error) throw error;
|
|
2847
|
+
return result;
|
|
2848
|
+
}),
|
|
2849
|
+
signOut: fromPromise(async () => {
|
|
2850
|
+
const [error] = await client.auth.signOut();
|
|
2851
|
+
if (error) throw error;
|
|
2852
|
+
})
|
|
2853
|
+
},
|
|
2854
|
+
actions: {
|
|
2855
|
+
trackOtpRequested: ({ context }) => {
|
|
2856
|
+
if (!context.email) return;
|
|
2857
|
+
track("auth_otp_requested", {
|
|
2858
|
+
email_domain: emailDomain2(context.email)
|
|
2859
|
+
});
|
|
2860
|
+
},
|
|
2861
|
+
trackFailed: ({ event }) => {
|
|
2862
|
+
track("auth_failed", {
|
|
2863
|
+
auth_type: "email_otp",
|
|
2864
|
+
reason: errorFromEvent2(event).code
|
|
2865
|
+
});
|
|
2866
|
+
},
|
|
2867
|
+
trackTimeoutFailed: () => {
|
|
2868
|
+
track("auth_failed", {
|
|
2869
|
+
auth_type: "email_otp",
|
|
2870
|
+
reason: "timeout"
|
|
2871
|
+
});
|
|
2872
|
+
},
|
|
2873
|
+
trackVerified: () => {
|
|
2874
|
+
track("auth_verified", { auth_type: "email_otp" });
|
|
2875
|
+
},
|
|
2876
|
+
trackBootstrapRequired: ({ context }) => {
|
|
2877
|
+
track("auth_verified", {
|
|
2878
|
+
auth_type: "email_otp",
|
|
2879
|
+
auth_mode: context.bootstrapReason ?? "bootstrap_required"
|
|
2880
|
+
});
|
|
2881
|
+
},
|
|
2882
|
+
identifyAndTrack: ({ context }) => {
|
|
2883
|
+
if (!context.session) return;
|
|
2884
|
+
identify(context.session.authUserId, {
|
|
2885
|
+
email_domain: emailDomain2(context.session.email)
|
|
2886
|
+
});
|
|
2887
|
+
track("auth_identified", {
|
|
2888
|
+
email_domain: emailDomain2(context.session.email)
|
|
2889
|
+
});
|
|
2890
|
+
},
|
|
2891
|
+
trackSignedOut: () => {
|
|
2892
|
+
track("auth_signed_out");
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
}).createMachine({
|
|
2896
|
+
id: "authBootstrap",
|
|
2897
|
+
initial: "email",
|
|
2898
|
+
context: initialContext,
|
|
2899
|
+
states: {
|
|
2900
|
+
email: {
|
|
2901
|
+
on: {
|
|
2902
|
+
ENTER_EMAIL: {
|
|
2903
|
+
actions: assign({
|
|
2904
|
+
email: ({ event }) => event.email,
|
|
2905
|
+
error: () => null
|
|
2906
|
+
})
|
|
2907
|
+
},
|
|
2908
|
+
REQUEST_OTP: { target: "sending_otp" }
|
|
2909
|
+
}
|
|
2910
|
+
},
|
|
2911
|
+
sending_otp: {
|
|
2912
|
+
invoke: {
|
|
2913
|
+
src: "sendOtp",
|
|
2914
|
+
input: ({ context }) => ({ email: requireEmail2(context) }),
|
|
2915
|
+
onDone: { target: "otp_requested", actions: "trackOtpRequested" },
|
|
2916
|
+
onError: {
|
|
2917
|
+
target: "otp_requested",
|
|
2918
|
+
actions: [
|
|
2919
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
2920
|
+
"trackFailed"
|
|
2921
|
+
]
|
|
2922
|
+
}
|
|
2923
|
+
},
|
|
2924
|
+
after: {
|
|
2925
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
2926
|
+
target: "otp_requested",
|
|
2927
|
+
actions: [
|
|
2928
|
+
assign({ error: () => timeoutError2("sending_otp") }),
|
|
2929
|
+
"trackTimeoutFailed"
|
|
2930
|
+
]
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
},
|
|
2934
|
+
otp_requested: {
|
|
2935
|
+
on: {
|
|
2936
|
+
ENTER_OTP: {
|
|
2937
|
+
actions: assign({
|
|
2938
|
+
code: ({ event }) => event.code,
|
|
2939
|
+
error: () => null
|
|
2940
|
+
})
|
|
2941
|
+
},
|
|
2942
|
+
VERIFY_OTP: { target: "verifying_otp" },
|
|
2943
|
+
BACK: { target: "email" },
|
|
2944
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
2945
|
+
}
|
|
2946
|
+
},
|
|
2947
|
+
verifying_otp: {
|
|
2948
|
+
invoke: {
|
|
2949
|
+
src: "verifyOtp",
|
|
2950
|
+
input: ({ context }) => ({
|
|
2951
|
+
email: requireEmail2(context),
|
|
2952
|
+
code: requireCode(context)
|
|
2953
|
+
}),
|
|
2954
|
+
onDone: [
|
|
2955
|
+
{
|
|
2956
|
+
guard: ({ event }) => event.output.kind === "existing_member",
|
|
2957
|
+
target: "authenticated",
|
|
2958
|
+
actions: [
|
|
2959
|
+
assign({
|
|
2960
|
+
session: ({ event }) => event.output.session,
|
|
2961
|
+
account: ({ event }) => event.output.kind === "existing_member" ? event.output.account : null,
|
|
2962
|
+
username: ({ event }) => event.output.kind === "existing_member" ? event.output.username : null,
|
|
2963
|
+
safe: ({ event }) => event.output.kind === "existing_member" ? event.output.safe : null,
|
|
2964
|
+
email: () => null,
|
|
2965
|
+
error: () => null
|
|
2966
|
+
}),
|
|
2967
|
+
"trackVerified",
|
|
2968
|
+
"identifyAndTrack"
|
|
2969
|
+
]
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
target: "bootstrap_required",
|
|
2973
|
+
actions: [
|
|
2974
|
+
assign({
|
|
2975
|
+
session: ({ event }) => event.output.session,
|
|
2976
|
+
bootstrapToken: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.bootstrapToken : null,
|
|
2977
|
+
bootstrapReason: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.reason : null,
|
|
2978
|
+
username: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.username ?? null : null,
|
|
2979
|
+
email: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.email : null,
|
|
2980
|
+
error: () => null
|
|
2981
|
+
}),
|
|
2982
|
+
"trackVerified",
|
|
2983
|
+
"trackBootstrapRequired"
|
|
2984
|
+
]
|
|
2985
|
+
}
|
|
2986
|
+
],
|
|
2987
|
+
onError: {
|
|
2988
|
+
target: "otp_requested",
|
|
2989
|
+
actions: [
|
|
2990
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
2991
|
+
"trackFailed"
|
|
2992
|
+
]
|
|
2993
|
+
}
|
|
2994
|
+
},
|
|
2995
|
+
after: {
|
|
2996
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
2997
|
+
target: "otp_requested",
|
|
2998
|
+
actions: [
|
|
2999
|
+
assign({ error: () => timeoutError2("verifying_otp") }),
|
|
3000
|
+
"trackTimeoutFailed"
|
|
3001
|
+
]
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
},
|
|
3005
|
+
bootstrap_required: {
|
|
3006
|
+
on: {
|
|
3007
|
+
ENTER_USERNAME: {
|
|
3008
|
+
actions: assign({
|
|
3009
|
+
username: ({ event }) => event.username,
|
|
3010
|
+
error: () => null
|
|
3011
|
+
})
|
|
3012
|
+
},
|
|
3013
|
+
ENTER_SIGNER_PROVIDER: {
|
|
3014
|
+
actions: assign({
|
|
3015
|
+
signerProvider: ({ event }) => event.signerProvider,
|
|
3016
|
+
error: () => null
|
|
3017
|
+
})
|
|
3018
|
+
},
|
|
3019
|
+
COMPLETE_BOOTSTRAP: { target: "completing_bootstrap" },
|
|
3020
|
+
BACK: { target: "otp_requested" },
|
|
3021
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
3022
|
+
}
|
|
3023
|
+
},
|
|
3024
|
+
completing_bootstrap: {
|
|
3025
|
+
invoke: {
|
|
3026
|
+
src: "completeBootstrap",
|
|
3027
|
+
input: ({ context }) => ({
|
|
3028
|
+
bootstrapToken: requireBootstrapToken(context),
|
|
3029
|
+
username: requireUsername(context),
|
|
3030
|
+
signerProvider: requireSignerProvider(context)
|
|
3031
|
+
}),
|
|
3032
|
+
onDone: {
|
|
3033
|
+
target: "authenticated",
|
|
3034
|
+
actions: [
|
|
3035
|
+
assign({
|
|
3036
|
+
session: ({ event }) => event.output.session,
|
|
3037
|
+
account: ({ event }) => event.output.account,
|
|
3038
|
+
username: ({ event }) => event.output.username,
|
|
3039
|
+
safe: ({ event }) => event.output.safe,
|
|
3040
|
+
bootstrapToken: () => null,
|
|
3041
|
+
bootstrapReason: () => null,
|
|
3042
|
+
signerProvider: () => null,
|
|
3043
|
+
email: () => null,
|
|
3044
|
+
error: () => null
|
|
3045
|
+
}),
|
|
3046
|
+
"identifyAndTrack"
|
|
3047
|
+
]
|
|
3048
|
+
},
|
|
3049
|
+
onError: {
|
|
3050
|
+
target: "bootstrap_required",
|
|
3051
|
+
actions: [
|
|
3052
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
3053
|
+
"trackFailed"
|
|
3054
|
+
]
|
|
3055
|
+
}
|
|
3056
|
+
},
|
|
3057
|
+
after: {
|
|
3058
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
3059
|
+
target: "bootstrap_required",
|
|
3060
|
+
actions: [
|
|
3061
|
+
assign({ error: () => timeoutError2("completing_bootstrap") }),
|
|
3062
|
+
"trackTimeoutFailed"
|
|
3063
|
+
]
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
},
|
|
3067
|
+
authenticated: {
|
|
3068
|
+
on: {
|
|
3069
|
+
SIGN_OUT: { target: "signing_out" }
|
|
3070
|
+
}
|
|
3071
|
+
},
|
|
3072
|
+
signing_out: {
|
|
3073
|
+
invoke: {
|
|
3074
|
+
src: "signOut",
|
|
3075
|
+
onDone: {
|
|
3076
|
+
target: "email",
|
|
3077
|
+
actions: [
|
|
3078
|
+
assign(() => initialContext),
|
|
3079
|
+
"trackSignedOut"
|
|
3080
|
+
]
|
|
3081
|
+
},
|
|
3082
|
+
onError: {
|
|
3083
|
+
target: "error",
|
|
3084
|
+
actions: assign({ error: ({ event }) => errorFromEvent2(event) })
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
},
|
|
3088
|
+
error: {
|
|
3089
|
+
on: {
|
|
3090
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
});
|
|
3095
|
+
}
|
|
3096
|
+
function requireEmail2(context) {
|
|
3097
|
+
if (!context.email) {
|
|
3098
|
+
throw Errors.invalidInput("email", "Auth bootstrap requires an email.");
|
|
3099
|
+
}
|
|
3100
|
+
return context.email;
|
|
3101
|
+
}
|
|
3102
|
+
function requireCode(context) {
|
|
3103
|
+
if (!context.code) {
|
|
3104
|
+
throw Errors.invalidInput("code", "Auth bootstrap requires an OTP code.");
|
|
3105
|
+
}
|
|
3106
|
+
return context.code;
|
|
3107
|
+
}
|
|
3108
|
+
function requireBootstrapToken(context) {
|
|
3109
|
+
if (!context.bootstrapToken) {
|
|
3110
|
+
throw Errors.invalidInput(
|
|
3111
|
+
"bootstrapToken",
|
|
3112
|
+
"Auth bootstrap requires a continuation token."
|
|
3113
|
+
);
|
|
3114
|
+
}
|
|
3115
|
+
return context.bootstrapToken;
|
|
3116
|
+
}
|
|
3117
|
+
function requireUsername(context) {
|
|
3118
|
+
if (!context.username) {
|
|
3119
|
+
throw Errors.invalidInput("username", "Auth bootstrap requires a username.");
|
|
3120
|
+
}
|
|
3121
|
+
return context.username;
|
|
3122
|
+
}
|
|
3123
|
+
function requireSignerProvider(context) {
|
|
3124
|
+
if (!context.signerProvider) {
|
|
3125
|
+
throw Errors.invalidInput(
|
|
3126
|
+
"signerProvider",
|
|
3127
|
+
"Auth bootstrap requires a signer provider."
|
|
3128
|
+
);
|
|
3129
|
+
}
|
|
3130
|
+
return context.signerProvider;
|
|
3131
|
+
}
|
|
3132
|
+
function errorFromEvent2(event) {
|
|
3133
|
+
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
3134
|
+
if (cause instanceof CapxulError || cause instanceof CapxulError2) {
|
|
3135
|
+
return cause;
|
|
3136
|
+
}
|
|
3137
|
+
return Errors.providerError("auth", "bootstrap", cause);
|
|
3138
|
+
}
|
|
3139
|
+
function timeoutError2(state) {
|
|
3140
|
+
return Errors.providerError(
|
|
3141
|
+
"auth",
|
|
3142
|
+
"bootstrap",
|
|
3143
|
+
new Error(`timeout: ${state} exceeded ${FLOW_INVOKE_TIMEOUT_MS}ms`)
|
|
3144
|
+
);
|
|
3145
|
+
}
|
|
3146
|
+
function emailDomain2(email) {
|
|
3147
|
+
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
3148
|
+
return domain || "unknown";
|
|
3149
|
+
}
|
|
2743
3150
|
function createProvisioningMachine(client) {
|
|
2744
3151
|
return setup({
|
|
2745
3152
|
types: {},
|
|
@@ -2812,13 +3219,13 @@ function createProvisioningMachine(client) {
|
|
|
2812
3219
|
},
|
|
2813
3220
|
onError: {
|
|
2814
3221
|
target: "error",
|
|
2815
|
-
actions: assign({ error: ({ event }) =>
|
|
3222
|
+
actions: assign({ error: ({ event }) => errorFromEvent3(event) })
|
|
2816
3223
|
}
|
|
2817
3224
|
},
|
|
2818
3225
|
after: {
|
|
2819
3226
|
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
2820
3227
|
target: "error",
|
|
2821
|
-
actions: assign({ error: () =>
|
|
3228
|
+
actions: assign({ error: () => timeoutError3() })
|
|
2822
3229
|
}
|
|
2823
3230
|
}
|
|
2824
3231
|
},
|
|
@@ -2836,7 +3243,7 @@ function createProvisioningMachine(client) {
|
|
|
2836
3243
|
* this payload on its `onDone` transition and branches via guards
|
|
2837
3244
|
* on `event.output.error`.
|
|
2838
3245
|
*/
|
|
2839
|
-
output: ({ context }) => context.error ? { error: context.error } : context.account ? { account: context.account } : { error:
|
|
3246
|
+
output: ({ context }) => context.error ? { error: context.error } : context.account ? { account: context.account } : { error: timeoutError3() }
|
|
2840
3247
|
});
|
|
2841
3248
|
}
|
|
2842
3249
|
function requireProvisionInput(context) {
|
|
@@ -2848,13 +3255,13 @@ function requireProvisionInput(context) {
|
|
|
2848
3255
|
}
|
|
2849
3256
|
return context.input;
|
|
2850
3257
|
}
|
|
2851
|
-
function
|
|
3258
|
+
function errorFromEvent3(event) {
|
|
2852
3259
|
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
2853
3260
|
if (cause instanceof CapxulError) return cause;
|
|
2854
3261
|
if (cause instanceof CapxulError2) return cause;
|
|
2855
3262
|
return Errors.providerError("provisioning", "flow", cause);
|
|
2856
3263
|
}
|
|
2857
|
-
function
|
|
3264
|
+
function timeoutError3() {
|
|
2858
3265
|
return Errors.providerError(
|
|
2859
3266
|
"provisioning",
|
|
2860
3267
|
"flow",
|
|
@@ -2947,7 +3354,7 @@ function createOnboardingFlowMachine(client) {
|
|
|
2947
3354
|
error: ({ event }) => extractChildErrorOrFallback(event)
|
|
2948
3355
|
}),
|
|
2949
3356
|
assignChildThrown: assign({
|
|
2950
|
-
error: ({ event }) =>
|
|
3357
|
+
error: ({ event }) => errorFromEvent4(event)
|
|
2951
3358
|
}),
|
|
2952
3359
|
assignAccountFromChild: assign({
|
|
2953
3360
|
account: ({ event }) => extractChildAccountOrNull(event)
|
|
@@ -3109,7 +3516,7 @@ function extractChildAccountOrNull(event) {
|
|
|
3109
3516
|
if (output && "account" in output && output.account) return output.account;
|
|
3110
3517
|
return null;
|
|
3111
3518
|
}
|
|
3112
|
-
function
|
|
3519
|
+
function errorFromEvent4(event) {
|
|
3113
3520
|
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
3114
3521
|
if (cause instanceof CapxulError) return cause;
|
|
3115
3522
|
if (cause instanceof CapxulError2) return cause;
|
|
@@ -3141,6 +3548,7 @@ function createCapxulClient(config = {}) {
|
|
|
3141
3548
|
const client = clientWithoutFlows;
|
|
3142
3549
|
client.flows = {
|
|
3143
3550
|
auth: () => createAuthFlowMachine(client),
|
|
3551
|
+
authBootstrap: () => createAuthBootstrapFlowMachine(client),
|
|
3144
3552
|
onboarding: () => createOnboardingFlowMachine(client),
|
|
3145
3553
|
provisioning: () => createProvisioningMachine(client)
|
|
3146
3554
|
};
|
|
@@ -3245,4 +3653,4 @@ function isWebhookEvent(value) {
|
|
|
3245
3653
|
return typeof candidate.id === "string" && typeof candidate.type === "string" && typeof candidate.createdAt === "string" && (candidate.operationId === void 0 || typeof candidate.operationId === "string") && (candidate.correlationId === void 0 || typeof candidate.correlationId === "string") && !!candidate.data && typeof candidate.data === "object" && !Array.isArray(candidate.data);
|
|
3246
3654
|
}
|
|
3247
3655
|
|
|
3248
|
-
export { CapxulError, createAuthFlowMachine, createCapxulClient, createLocalSigner, createOnboardingFlowMachine, createProvisioningMachine as createProvisioningFlowMachine, makeHttpTransport, matchAction, matchError, matchStatus, toAccountId, toApiKeyId, toBalanceLedgerEntryId, toDocumentId, toEmail, toExternalAccountId, toKybProfileId, toKycProfileId, toMemberId, toOperationId, toOrganizationId, toPaymentId, toPhoneNumber, toSafeId, toSubAccountId, toTokenTransferId, toTransferId, toTreasuryId, toUsername, toVirtualAccountId, toVirtualCardId, toWebhookEndpointId, toWebhookEventId, toWithdrawalId, tryCatch, verifyWebhook };
|
|
3656
|
+
export { CapxulError, createAuthBootstrapFlowMachine, createAuthFlowMachine, createCapxulClient, createLocalSigner, createOnboardingFlowMachine, createProvisioningMachine as createProvisioningFlowMachine, makeHttpTransport, matchAction, matchError, matchStatus, toAccountId, toApiKeyId, toBalanceLedgerEntryId, toDocumentId, toEmail, toExternalAccountId, toKybProfileId, toKycProfileId, toMemberId, toOperationId, toOrganizationId, toPaymentId, toPhoneNumber, toSafeId, toSubAccountId, toTokenTransferId, toTransferId, toTreasuryId, toUsername, toVirtualAccountId, toVirtualCardId, toWebhookEndpointId, toWebhookEventId, toWithdrawalId, tryCatch, verifyWebhook };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.9",
|
|
4
4
|
"description": "Headless TypeScript client for Capxul's /v1/* HTTP contract.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"viem": "2.47.10",
|
|
74
74
|
"vitest": "^4.1.2",
|
|
75
75
|
"zod": "^4.3.6",
|
|
76
|
-
"@repo/api-contract": "0.0.0",
|
|
77
76
|
"@repo/backend": "0.0.0",
|
|
77
|
+
"@repo/api-contract": "0.0.0",
|
|
78
78
|
"@repo/config": "0.0.0",
|
|
79
79
|
"@repo/observability": "0.0.0",
|
|
80
80
|
"@repo/platform-kernel": "0.0.0",
|