@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/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;