@capxul/sdk-react 0.1.0-alpha.0
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 +31 -0
- package/LICENSE +44 -0
- package/README.md +173 -0
- package/dist/index.cjs +618 -0
- package/dist/index.d.cts +473 -0
- package/dist/index.d.ts +473 -0
- package/dist/index.js +568 -0
- package/package.json +86 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var sdk = require('@capxul/sdk');
|
|
6
|
+
var reactQuery = require('@tanstack/react-query');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
var errors = require('@capxul/sdk/errors');
|
|
9
|
+
var react$1 = require('@xstate/react');
|
|
10
|
+
var viem = require('viem');
|
|
11
|
+
var accounts = require('viem/accounts');
|
|
12
|
+
|
|
13
|
+
// src/provider.tsx
|
|
14
|
+
|
|
15
|
+
// ../config/src/errors.ts
|
|
16
|
+
var CapxulError = class extends Error {
|
|
17
|
+
code;
|
|
18
|
+
details;
|
|
19
|
+
correlationId;
|
|
20
|
+
layer;
|
|
21
|
+
constructor(code, message, options) {
|
|
22
|
+
super(message, options?.cause ? { cause: options.cause } : void 0);
|
|
23
|
+
this.code = code;
|
|
24
|
+
this.details = options?.details;
|
|
25
|
+
this.correlationId = options?.correlationId;
|
|
26
|
+
this.layer = options?.layer;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var Errors = {
|
|
30
|
+
notAuthenticated: () => new CapxulError("NOT_AUTHENTICATED", "Not authenticated"),
|
|
31
|
+
profileNotFound: (authUserId) => new CapxulError("PROFILE_NOT_FOUND", `Profile not found for user ${authUserId}`),
|
|
32
|
+
smartAccountMissing: (authUserId) => new CapxulError("SMART_ACCOUNT_MISSING", `Smart account not provisioned for user ${authUserId}`),
|
|
33
|
+
envMissing: (name) => new CapxulError("ENV_MISSING", `Environment variable ${name} not configured`),
|
|
34
|
+
openfortApi: (operation, cause) => new CapxulError(
|
|
35
|
+
"PROVIDER_ERROR",
|
|
36
|
+
`Openfort ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
37
|
+
{ cause, details: { provider: "openfort", operation } }
|
|
38
|
+
),
|
|
39
|
+
shieldApi: (status, detail) => new CapxulError(
|
|
40
|
+
"PROVIDER_ERROR",
|
|
41
|
+
`Shield API error (${status}): ${detail}`,
|
|
42
|
+
{ details: { provider: "shield", status } }
|
|
43
|
+
),
|
|
44
|
+
providerError: (provider, operation, cause) => new CapxulError(
|
|
45
|
+
"PROVIDER_ERROR",
|
|
46
|
+
`${provider} ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
47
|
+
{ cause, details: { provider, operation } }
|
|
48
|
+
),
|
|
49
|
+
invalidInput: (field, reason) => new CapxulError(
|
|
50
|
+
"INVALID_INPUT",
|
|
51
|
+
`Invalid ${field}: ${reason}`,
|
|
52
|
+
{ details: { field, reason } }
|
|
53
|
+
),
|
|
54
|
+
playerNotFound: (playerId) => new CapxulError(
|
|
55
|
+
"PLAYER_NOT_FOUND",
|
|
56
|
+
playerId ? `Openfort player ${playerId} not found` : "Openfort player not found"
|
|
57
|
+
),
|
|
58
|
+
accountNotFound: (accountId) => new CapxulError(
|
|
59
|
+
"ACCOUNT_NOT_FOUND",
|
|
60
|
+
accountId ? `Openfort account ${accountId} not found` : "Openfort smart account not found"
|
|
61
|
+
),
|
|
62
|
+
invalidRecipient: (reason) => new CapxulError("INVALID_RECIPIENT", reason),
|
|
63
|
+
permissionDenied: (reason = "Permission denied") => new CapxulError("PERMISSION_DENIED", reason),
|
|
64
|
+
notFound: (resource, id) => new CapxulError(
|
|
65
|
+
"NOT_FOUND",
|
|
66
|
+
id ? `${resource} ${id} not found` : `${resource} not found`
|
|
67
|
+
),
|
|
68
|
+
idempotencyConflict: (details) => new CapxulError(
|
|
69
|
+
"IDEMPOTENCY_CONFLICT",
|
|
70
|
+
"Idempotency key was already used for a different request",
|
|
71
|
+
{ details }
|
|
72
|
+
),
|
|
73
|
+
emailDeliveryFailed: (detail) => new CapxulError("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`),
|
|
74
|
+
internalError: (reason) => new CapxulError("INTERNAL_ERROR", `Internal error: ${reason}`)
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// ../config/src/org-roles.ts
|
|
78
|
+
function roleKeyFromLabel(label) {
|
|
79
|
+
const bytes = new TextEncoder().encode(label);
|
|
80
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
81
|
+
return "0x" + hex.padEnd(64, "0");
|
|
82
|
+
}
|
|
83
|
+
roleKeyFromLabel("OWNER");
|
|
84
|
+
roleKeyFromLabel("FINANCE_MANAGER");
|
|
85
|
+
roleKeyFromLabel("TEAM_LEAD");
|
|
86
|
+
var CapxulClientContext = react.createContext(null);
|
|
87
|
+
function CapxulClientProvider({
|
|
88
|
+
client,
|
|
89
|
+
children
|
|
90
|
+
}) {
|
|
91
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CapxulClientContext.Provider, { value: client, children });
|
|
92
|
+
}
|
|
93
|
+
function useCapxul() {
|
|
94
|
+
const client = react.useContext(CapxulClientContext);
|
|
95
|
+
if (!client) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"useCapxul() was called outside a <CapxulProvider>. Wrap your app in <CapxulProvider config={...}> before rendering hooks from @capxul/sdk-react."
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return client;
|
|
101
|
+
}
|
|
102
|
+
var CapxulTransportContext = react.createContext(null);
|
|
103
|
+
function CapxulTransportProvider({
|
|
104
|
+
transport,
|
|
105
|
+
children
|
|
106
|
+
}) {
|
|
107
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportContext.Provider, { value: transport, children });
|
|
108
|
+
}
|
|
109
|
+
function useCapxulStatus() {
|
|
110
|
+
const transport = react.useContext(CapxulTransportContext);
|
|
111
|
+
return react.useSyncExternalStore(
|
|
112
|
+
(listener) => {
|
|
113
|
+
if (!transport) return () => {
|
|
114
|
+
};
|
|
115
|
+
return transport.subscribe(listener);
|
|
116
|
+
},
|
|
117
|
+
() => transport?.getState() ?? FALLBACK_READY,
|
|
118
|
+
() => transport?.getState() ?? FALLBACK_READY
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
var FALLBACK_READY = Object.freeze({
|
|
122
|
+
status: "ready",
|
|
123
|
+
runtime: { authBaseUrl: "", convexUrl: "" }
|
|
124
|
+
});
|
|
125
|
+
function CapxulProvider({
|
|
126
|
+
config,
|
|
127
|
+
publishableKey,
|
|
128
|
+
browserConfig,
|
|
129
|
+
queryClient,
|
|
130
|
+
children
|
|
131
|
+
}) {
|
|
132
|
+
const wiring = react.useMemo(
|
|
133
|
+
() => buildWiring({ config, publishableKey, browserConfig }),
|
|
134
|
+
[config, publishableKey, browserConfig]
|
|
135
|
+
);
|
|
136
|
+
const defaultClient = react.useMemo(
|
|
137
|
+
() => new reactQuery.QueryClient({
|
|
138
|
+
defaultOptions: { queries: { staleTime: 3e4 } }
|
|
139
|
+
}),
|
|
140
|
+
[]
|
|
141
|
+
);
|
|
142
|
+
const effectiveClient = queryClient ?? defaultClient;
|
|
143
|
+
const inner = /* @__PURE__ */ jsxRuntime.jsx(CapxulClientProvider, { client: wiring.client, children });
|
|
144
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: effectiveClient, children: wiring.transport ? /* @__PURE__ */ jsxRuntime.jsx(CapxulTransportProvider, { transport: wiring.transport, children: inner }) : inner });
|
|
145
|
+
}
|
|
146
|
+
function buildWiring({
|
|
147
|
+
config,
|
|
148
|
+
publishableKey,
|
|
149
|
+
browserConfig
|
|
150
|
+
}) {
|
|
151
|
+
const sources = [
|
|
152
|
+
config !== void 0,
|
|
153
|
+
publishableKey !== void 0,
|
|
154
|
+
browserConfig !== void 0
|
|
155
|
+
].filter(Boolean).length;
|
|
156
|
+
if (sources === 0) {
|
|
157
|
+
throw Errors.invalidInput(
|
|
158
|
+
"CapxulProvider",
|
|
159
|
+
"Pass exactly one of `config`, `publishableKey`, or `browserConfig`."
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (sources > 1) {
|
|
163
|
+
throw Errors.invalidInput(
|
|
164
|
+
"CapxulProvider",
|
|
165
|
+
"`config`, `publishableKey`, and `browserConfig` are mutually exclusive \u2014 pass exactly one."
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (config !== void 0) {
|
|
169
|
+
return {
|
|
170
|
+
client: sdk.createCapxulClient(config),
|
|
171
|
+
transport: null
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const browserCfg = browserConfig ?? {
|
|
175
|
+
mode: "publishable-key",
|
|
176
|
+
// The narrowing above (`sources === 0` rejected; `config` not
|
|
177
|
+
// present) guarantees `publishableKey` is set on this branch.
|
|
178
|
+
publishableKey
|
|
179
|
+
};
|
|
180
|
+
const transport = sdk.makeHttpTransport(browserCfg);
|
|
181
|
+
const sdkConfig = {
|
|
182
|
+
_transport: transport,
|
|
183
|
+
publishableKey: browserCfg.mode === "publishable-key" ? browserCfg.publishableKey : void 0
|
|
184
|
+
};
|
|
185
|
+
return {
|
|
186
|
+
client: sdk.createCapxulClient(sdkConfig),
|
|
187
|
+
transport
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function notImplementedQuery(hookName) {
|
|
191
|
+
return {
|
|
192
|
+
status: "error",
|
|
193
|
+
error: new errors.CapxulError({
|
|
194
|
+
code: "NOT_IMPLEMENTED",
|
|
195
|
+
message: `${hookName} is not yet implemented in @capxul/sdk-react. The hook remains a reset placeholder until its vertical lands per sdk-surface.md \xA73b.`
|
|
196
|
+
})
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function useSdkQuery(read, dependencies) {
|
|
200
|
+
const [state, setState] = react.useState({
|
|
201
|
+
dependencies,
|
|
202
|
+
result: { status: "loading" }
|
|
203
|
+
});
|
|
204
|
+
const dependenciesChanged = didDependenciesChange(
|
|
205
|
+
state.dependencies,
|
|
206
|
+
dependencies
|
|
207
|
+
);
|
|
208
|
+
react.useEffect(() => {
|
|
209
|
+
let active = true;
|
|
210
|
+
setState({ dependencies, result: { status: "loading" } });
|
|
211
|
+
void read().then(([error, data]) => {
|
|
212
|
+
if (!active) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (error) {
|
|
216
|
+
setState({ dependencies, result: { status: "error", error } });
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
setState({ dependencies, result: { status: "data", data } });
|
|
220
|
+
}).catch((cause) => {
|
|
221
|
+
if (!active) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
setState({
|
|
225
|
+
dependencies,
|
|
226
|
+
result: {
|
|
227
|
+
status: "error",
|
|
228
|
+
error: cause instanceof errors.CapxulError ? cause : new errors.CapxulError({
|
|
229
|
+
code: "UNKNOWN",
|
|
230
|
+
message: "SDK read failed before returning a CapxulResult.",
|
|
231
|
+
cause
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
return () => {
|
|
237
|
+
active = false;
|
|
238
|
+
};
|
|
239
|
+
}, dependencies);
|
|
240
|
+
if (dependenciesChanged) {
|
|
241
|
+
return { status: "loading" };
|
|
242
|
+
}
|
|
243
|
+
return state.result;
|
|
244
|
+
}
|
|
245
|
+
function didDependenciesChange(previous, next) {
|
|
246
|
+
if (previous.length !== next.length) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
return previous.some((previousDependency, index) => {
|
|
250
|
+
return !Object.is(previousDependency, next[index]);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/hooks/singular.ts
|
|
255
|
+
function useMe() {
|
|
256
|
+
const capxul = useCapxul();
|
|
257
|
+
return reactQuery.useQuery({
|
|
258
|
+
queryKey: [capxul.id, "capxul", "me"],
|
|
259
|
+
queryFn: () => capxul.me.get().then(([error, data]) => {
|
|
260
|
+
if (error) {
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
return data;
|
|
264
|
+
}).catch((cause) => {
|
|
265
|
+
if (cause instanceof sdk.CapxulError) {
|
|
266
|
+
throw cause;
|
|
267
|
+
}
|
|
268
|
+
throw new sdk.CapxulError({
|
|
269
|
+
code: "UNKNOWN",
|
|
270
|
+
message: "SDK read failed before returning a CapxulResult.",
|
|
271
|
+
cause
|
|
272
|
+
});
|
|
273
|
+
}),
|
|
274
|
+
staleTime: 3e4
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function useAccount(_accountId) {
|
|
278
|
+
return notImplementedQuery("useAccount");
|
|
279
|
+
}
|
|
280
|
+
function useOrganization(_organizationId) {
|
|
281
|
+
return notImplementedQuery("useOrganization");
|
|
282
|
+
}
|
|
283
|
+
function useMember(_args) {
|
|
284
|
+
return notImplementedQuery("useMember");
|
|
285
|
+
}
|
|
286
|
+
function useSafe(_safeId) {
|
|
287
|
+
return notImplementedQuery("useSafe");
|
|
288
|
+
}
|
|
289
|
+
function useTreasury(_organizationId) {
|
|
290
|
+
return notImplementedQuery("useTreasury");
|
|
291
|
+
}
|
|
292
|
+
function useApiKey(_args) {
|
|
293
|
+
return notImplementedQuery("useApiKey");
|
|
294
|
+
}
|
|
295
|
+
function useKycProfile(_accountId) {
|
|
296
|
+
return notImplementedQuery("useKycProfile");
|
|
297
|
+
}
|
|
298
|
+
function useKybProfile(_organizationId) {
|
|
299
|
+
return notImplementedQuery("useKybProfile");
|
|
300
|
+
}
|
|
301
|
+
function useExternalAccount(_args) {
|
|
302
|
+
return notImplementedQuery("useExternalAccount");
|
|
303
|
+
}
|
|
304
|
+
function useSubAccount(_subAccountId) {
|
|
305
|
+
return notImplementedQuery("useSubAccount");
|
|
306
|
+
}
|
|
307
|
+
function useVirtualAccount(_virtualAccountId) {
|
|
308
|
+
return notImplementedQuery("useVirtualAccount");
|
|
309
|
+
}
|
|
310
|
+
function useVirtualCard(_virtualCardId) {
|
|
311
|
+
return notImplementedQuery("useVirtualCard");
|
|
312
|
+
}
|
|
313
|
+
function usePayment(_paymentId) {
|
|
314
|
+
return notImplementedQuery("usePayment");
|
|
315
|
+
}
|
|
316
|
+
function useTransfer(_transferId) {
|
|
317
|
+
return notImplementedQuery("useTransfer");
|
|
318
|
+
}
|
|
319
|
+
function useBalanceLedgerEntry(_args) {
|
|
320
|
+
return notImplementedQuery("useBalanceLedgerEntry");
|
|
321
|
+
}
|
|
322
|
+
function useDocument(_documentId) {
|
|
323
|
+
return notImplementedQuery("useDocument");
|
|
324
|
+
}
|
|
325
|
+
function useWithdrawal(withdrawalId) {
|
|
326
|
+
const capxul = useCapxul();
|
|
327
|
+
return useSdkQuery(() => capxul.withdrawals.retrieve(withdrawalId), [
|
|
328
|
+
capxul,
|
|
329
|
+
withdrawalId
|
|
330
|
+
]);
|
|
331
|
+
}
|
|
332
|
+
function useOperation(operationId) {
|
|
333
|
+
const capxul = useCapxul();
|
|
334
|
+
return useSdkQuery(() => capxul.operations.retrieve(operationId), [
|
|
335
|
+
capxul,
|
|
336
|
+
operationId
|
|
337
|
+
]);
|
|
338
|
+
}
|
|
339
|
+
function useWebhookEndpoint(_endpointId) {
|
|
340
|
+
return notImplementedQuery("useWebhookEndpoint");
|
|
341
|
+
}
|
|
342
|
+
function useWebhookEvent(_eventId) {
|
|
343
|
+
return notImplementedQuery("useWebhookEvent");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/hooks/list.ts
|
|
347
|
+
function useOrganizations() {
|
|
348
|
+
return notImplementedQuery("useOrganizations");
|
|
349
|
+
}
|
|
350
|
+
function useMembers(_organizationId) {
|
|
351
|
+
return notImplementedQuery("useMembers");
|
|
352
|
+
}
|
|
353
|
+
function useExternalAccounts(_args) {
|
|
354
|
+
return notImplementedQuery("useExternalAccounts");
|
|
355
|
+
}
|
|
356
|
+
function useSubAccounts(_args) {
|
|
357
|
+
return notImplementedQuery("useSubAccounts");
|
|
358
|
+
}
|
|
359
|
+
function useVirtualAccounts(_filters) {
|
|
360
|
+
return notImplementedQuery("useVirtualAccounts");
|
|
361
|
+
}
|
|
362
|
+
function useVirtualCards(_filters) {
|
|
363
|
+
return notImplementedQuery("useVirtualCards");
|
|
364
|
+
}
|
|
365
|
+
function usePayments(_filters) {
|
|
366
|
+
return notImplementedQuery("usePayments");
|
|
367
|
+
}
|
|
368
|
+
function useOrgPayments(_args) {
|
|
369
|
+
return notImplementedQuery("useOrgPayments");
|
|
370
|
+
}
|
|
371
|
+
function useTransfers(_filters) {
|
|
372
|
+
return notImplementedQuery("useTransfers");
|
|
373
|
+
}
|
|
374
|
+
function useOrgTransfers(_args) {
|
|
375
|
+
return notImplementedQuery("useOrgTransfers");
|
|
376
|
+
}
|
|
377
|
+
function useBalanceLedger(_args) {
|
|
378
|
+
return notImplementedQuery("useBalanceLedger");
|
|
379
|
+
}
|
|
380
|
+
function useDocuments(_filters) {
|
|
381
|
+
return notImplementedQuery("useDocuments");
|
|
382
|
+
}
|
|
383
|
+
function useOrgDocuments(_args) {
|
|
384
|
+
return notImplementedQuery("useOrgDocuments");
|
|
385
|
+
}
|
|
386
|
+
function useWithdrawals(filters) {
|
|
387
|
+
const capxul = useCapxul();
|
|
388
|
+
return useSdkQuery(
|
|
389
|
+
() => capxul.withdrawals.list(filters),
|
|
390
|
+
[capxul, filters?.limit, filters?.cursor]
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
function useOrgWithdrawals(args) {
|
|
394
|
+
const capxul = useCapxul();
|
|
395
|
+
return useSdkQuery(
|
|
396
|
+
() => capxul.organizations.withdrawals.list(args),
|
|
397
|
+
[capxul, args.organizationId, args.limit, args.cursor]
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
function useApiKeys(_organizationId) {
|
|
401
|
+
return notImplementedQuery("useApiKeys");
|
|
402
|
+
}
|
|
403
|
+
function useWebhookEndpoints() {
|
|
404
|
+
return notImplementedQuery("useWebhookEndpoints");
|
|
405
|
+
}
|
|
406
|
+
function useAuthFlow() {
|
|
407
|
+
const client = useCapxul();
|
|
408
|
+
const machine = react.useMemo(() => client.flows.auth(), [client]);
|
|
409
|
+
const [snapshot, send] = react$1.useActor(machine);
|
|
410
|
+
return { snapshot, send };
|
|
411
|
+
}
|
|
412
|
+
function useOnboardingFlow() {
|
|
413
|
+
const client = useCapxul();
|
|
414
|
+
const machine = react.useMemo(() => client.flows.onboarding(), [client]);
|
|
415
|
+
const [snapshot, send] = react$1.useActor(machine);
|
|
416
|
+
return { snapshot, send };
|
|
417
|
+
}
|
|
418
|
+
function useProvisioningFlow() {
|
|
419
|
+
const client = useCapxul();
|
|
420
|
+
const machine = react.useMemo(() => client.flows.provisioning(), [client]);
|
|
421
|
+
const [snapshot, send] = react$1.useActor(machine);
|
|
422
|
+
return { snapshot, send };
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/config.ts
|
|
426
|
+
function createCapxulConfig(input) {
|
|
427
|
+
assertOnlyKnownKeys(input);
|
|
428
|
+
assertModeRequiredFields(input);
|
|
429
|
+
return Object.freeze({ ...input });
|
|
430
|
+
}
|
|
431
|
+
var ALLOWED_BROWSER_CONFIG_KEYS = [
|
|
432
|
+
"mode",
|
|
433
|
+
"authBaseUrl",
|
|
434
|
+
"convexUrl",
|
|
435
|
+
"publishableKey",
|
|
436
|
+
"bootstrapUrl",
|
|
437
|
+
"fetchImpl"
|
|
438
|
+
];
|
|
439
|
+
function assertOnlyKnownKeys(input) {
|
|
440
|
+
const candidate = input;
|
|
441
|
+
const allowed = new Set(ALLOWED_BROWSER_CONFIG_KEYS);
|
|
442
|
+
const unknown = Object.keys(candidate).filter((key) => !allowed.has(key));
|
|
443
|
+
if (unknown.length === 0) return;
|
|
444
|
+
throw Errors.invalidInput(
|
|
445
|
+
"config",
|
|
446
|
+
`Browser Capxul config contains unknown or secret/server-only fields: ${unknown.join(", ")}. Allowed keys: ${ALLOWED_BROWSER_CONFIG_KEYS.join(", ")}.`
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
function assertModeRequiredFields(input) {
|
|
450
|
+
switch (input.mode) {
|
|
451
|
+
case "build-time-urls": {
|
|
452
|
+
if (!input.authBaseUrl || input.authBaseUrl.trim().length === 0) {
|
|
453
|
+
throw Errors.invalidInput("authBaseUrl", "non-empty string required.");
|
|
454
|
+
}
|
|
455
|
+
if (!input.convexUrl || input.convexUrl.trim().length === 0) {
|
|
456
|
+
throw Errors.invalidInput("convexUrl", "non-empty string required.");
|
|
457
|
+
}
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
case "publishable-key": {
|
|
461
|
+
if (!input.publishableKey || input.publishableKey.trim().length === 0) {
|
|
462
|
+
throw Errors.invalidInput("publishableKey", "non-empty string required.");
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
default: {
|
|
467
|
+
const value = input;
|
|
468
|
+
throw Errors.internalError(
|
|
469
|
+
`Unhandled BrowserCapxulConfig.mode: ${String(value.mode)}.`
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
var PRIVATE_KEY_PATTERN = /^0x[0-9a-fA-F]{64}$/;
|
|
475
|
+
var EVM_ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
|
|
476
|
+
function injectedConnector(options = {}) {
|
|
477
|
+
const id = options.id ?? "injected";
|
|
478
|
+
return {
|
|
479
|
+
id,
|
|
480
|
+
name: options.name ?? "Injected wallet",
|
|
481
|
+
kind: "injected",
|
|
482
|
+
async connect() {
|
|
483
|
+
const provider = readInjectedProvider();
|
|
484
|
+
const result = await provider.request({
|
|
485
|
+
method: "eth_requestAccounts"
|
|
486
|
+
});
|
|
487
|
+
const accounts = Array.isArray(result) ? result : void 0;
|
|
488
|
+
const rawSignerAddress = accounts?.[0];
|
|
489
|
+
if (rawSignerAddress === void 0 || rawSignerAddress === null) {
|
|
490
|
+
throw Errors.providerError(
|
|
491
|
+
"connector",
|
|
492
|
+
"injected",
|
|
493
|
+
new Error("Injected wallet did not return an account.")
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
const signerAddress = validateAndNormalizeEvmAddress(
|
|
497
|
+
"signerAddress",
|
|
498
|
+
rawSignerAddress
|
|
499
|
+
);
|
|
500
|
+
return {
|
|
501
|
+
connectorId: id,
|
|
502
|
+
connectorKind: "injected",
|
|
503
|
+
signerAddress
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function localPrivateKeyConnector(options) {
|
|
509
|
+
if (!options.privateKey || !PRIVATE_KEY_PATTERN.test(options.privateKey)) {
|
|
510
|
+
throw Errors.invalidInput(
|
|
511
|
+
"privateKey",
|
|
512
|
+
"must be a 0x-prefixed 32-byte (64 hex chars) string."
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
const safeAddress = validateAndNormalizeEvmAddress(
|
|
516
|
+
"safeAddress",
|
|
517
|
+
options.safeAddress
|
|
518
|
+
);
|
|
519
|
+
const id = options.id ?? "local-private-key";
|
|
520
|
+
return {
|
|
521
|
+
id,
|
|
522
|
+
name: options.name ?? "Local private key",
|
|
523
|
+
kind: "local-private-key",
|
|
524
|
+
autoConnect: true,
|
|
525
|
+
async connect() {
|
|
526
|
+
const account = accounts.privateKeyToAccount(options.privateKey);
|
|
527
|
+
return {
|
|
528
|
+
connectorId: id,
|
|
529
|
+
connectorKind: "local-private-key",
|
|
530
|
+
signerAddress: account.address,
|
|
531
|
+
safeAddress,
|
|
532
|
+
signerProvider: {
|
|
533
|
+
kind: "local-private-key",
|
|
534
|
+
signerAddress: account.address,
|
|
535
|
+
safeAddress
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
function readInjectedProvider() {
|
|
542
|
+
const provider = globalThis.ethereum;
|
|
543
|
+
if (!provider || typeof provider.request !== "function") {
|
|
544
|
+
throw Errors.providerError(
|
|
545
|
+
"connector",
|
|
546
|
+
"injected",
|
|
547
|
+
new Error("No injected EIP-1193 wallet was found.")
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
return provider;
|
|
551
|
+
}
|
|
552
|
+
function validateAndNormalizeEvmAddress(field, raw) {
|
|
553
|
+
if (typeof raw !== "string" || !EVM_ADDRESS_PATTERN.test(raw)) {
|
|
554
|
+
const display = typeof raw === "string" ? raw.slice(0, 64) : String(raw);
|
|
555
|
+
throw Errors.invalidInput(
|
|
556
|
+
field,
|
|
557
|
+
`must be a 0x-prefixed 40 hex char address, got ${display}.`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
try {
|
|
561
|
+
return viem.getAddress(raw);
|
|
562
|
+
} catch (cause) {
|
|
563
|
+
throw Errors.invalidInput(
|
|
564
|
+
field,
|
|
565
|
+
`failed EIP-55 checksum: ${cause instanceof Error ? cause.message : String(cause)}.`
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
exports.CapxulClientProvider = CapxulClientProvider;
|
|
571
|
+
exports.CapxulProvider = CapxulProvider;
|
|
572
|
+
exports.CapxulTransportProvider = CapxulTransportProvider;
|
|
573
|
+
exports.createCapxulConfig = createCapxulConfig;
|
|
574
|
+
exports.injectedConnector = injectedConnector;
|
|
575
|
+
exports.localPrivateKeyConnector = localPrivateKeyConnector;
|
|
576
|
+
exports.useAccount = useAccount;
|
|
577
|
+
exports.useApiKey = useApiKey;
|
|
578
|
+
exports.useApiKeys = useApiKeys;
|
|
579
|
+
exports.useAuthFlow = useAuthFlow;
|
|
580
|
+
exports.useBalanceLedger = useBalanceLedger;
|
|
581
|
+
exports.useBalanceLedgerEntry = useBalanceLedgerEntry;
|
|
582
|
+
exports.useCapxul = useCapxul;
|
|
583
|
+
exports.useCapxulStatus = useCapxulStatus;
|
|
584
|
+
exports.useDocument = useDocument;
|
|
585
|
+
exports.useDocuments = useDocuments;
|
|
586
|
+
exports.useExternalAccount = useExternalAccount;
|
|
587
|
+
exports.useExternalAccounts = useExternalAccounts;
|
|
588
|
+
exports.useKybProfile = useKybProfile;
|
|
589
|
+
exports.useKycProfile = useKycProfile;
|
|
590
|
+
exports.useMe = useMe;
|
|
591
|
+
exports.useMember = useMember;
|
|
592
|
+
exports.useMembers = useMembers;
|
|
593
|
+
exports.useOnboardingFlow = useOnboardingFlow;
|
|
594
|
+
exports.useOperation = useOperation;
|
|
595
|
+
exports.useOrgDocuments = useOrgDocuments;
|
|
596
|
+
exports.useOrgPayments = useOrgPayments;
|
|
597
|
+
exports.useOrgTransfers = useOrgTransfers;
|
|
598
|
+
exports.useOrgWithdrawals = useOrgWithdrawals;
|
|
599
|
+
exports.useOrganization = useOrganization;
|
|
600
|
+
exports.useOrganizations = useOrganizations;
|
|
601
|
+
exports.usePayment = usePayment;
|
|
602
|
+
exports.usePayments = usePayments;
|
|
603
|
+
exports.useProvisioningFlow = useProvisioningFlow;
|
|
604
|
+
exports.useSafe = useSafe;
|
|
605
|
+
exports.useSubAccount = useSubAccount;
|
|
606
|
+
exports.useSubAccounts = useSubAccounts;
|
|
607
|
+
exports.useTransfer = useTransfer;
|
|
608
|
+
exports.useTransfers = useTransfers;
|
|
609
|
+
exports.useTreasury = useTreasury;
|
|
610
|
+
exports.useVirtualAccount = useVirtualAccount;
|
|
611
|
+
exports.useVirtualAccounts = useVirtualAccounts;
|
|
612
|
+
exports.useVirtualCard = useVirtualCard;
|
|
613
|
+
exports.useVirtualCards = useVirtualCards;
|
|
614
|
+
exports.useWebhookEndpoint = useWebhookEndpoint;
|
|
615
|
+
exports.useWebhookEndpoints = useWebhookEndpoints;
|
|
616
|
+
exports.useWebhookEvent = useWebhookEvent;
|
|
617
|
+
exports.useWithdrawal = useWithdrawal;
|
|
618
|
+
exports.useWithdrawals = useWithdrawals;
|