@capxul/sdk 0.1.0-alpha.4 → 0.1.0-alpha.8
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 +87 -5
- package/dist/{client-CcCtq5XO.d.ts → client-ByzDfG98.d.ts} +77 -34
- package/dist/{client-CXRKtbfn.d.cts → client-DDAVWtzJ.d.cts} +77 -34
- package/dist/client.cjs +894 -302
- package/dist/client.d.cts +2 -3
- package/dist/client.d.ts +2 -3
- package/dist/client.js +894 -302
- package/dist/index.cjs +1000 -418
- package/dist/index.d.cts +9 -10
- package/dist/index.d.ts +9 -10
- package/dist/index.js +1000 -418
- package/dist/types-PM4AQRLP.d.ts +1136 -0
- package/dist/types-hfcOE7Oi.d.cts +1136 -0
- package/dist/webhooks.d.cts +1 -2
- package/dist/webhooks.d.ts +1 -2
- package/package.json +5 -5
- package/dist/types-75UokagF.d.ts +0 -202
- package/dist/types-DVWojoy4.d.cts +0 -202
package/dist/client.cjs
CHANGED
|
@@ -69,7 +69,268 @@ function fromConvexError(error) {
|
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
// ../observability/src/try-catch.ts
|
|
73
|
+
async function tryCatch(promise) {
|
|
74
|
+
try {
|
|
75
|
+
return [null, await promise];
|
|
76
|
+
} catch (e) {
|
|
77
|
+
return [e instanceof Error ? e : new Error(String(e)), null];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ../observability/src/debug-log.ts
|
|
82
|
+
function isDevelopmentBuild() {
|
|
83
|
+
if (typeof process === "undefined") {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return process.env?.NODE_ENV === "development" || process.env?.NODE_ENV === "test";
|
|
87
|
+
}
|
|
88
|
+
function debugLog(line) {
|
|
89
|
+
if (!isDevelopmentBuild()) return;
|
|
90
|
+
if (typeof globalThis !== "undefined" && "window" in globalThis && typeof console?.info === "function") {
|
|
91
|
+
console.info(line);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (typeof process !== "undefined" && typeof process.stderr?.write === "function") {
|
|
95
|
+
process.stderr.write(`${line}
|
|
96
|
+
`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function formatDebugValue(value) {
|
|
100
|
+
if (value === void 0 || value === "") return "";
|
|
101
|
+
if (typeof value === "string") return value;
|
|
102
|
+
try {
|
|
103
|
+
return JSON.stringify(value);
|
|
104
|
+
} catch {
|
|
105
|
+
return String(value);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function track(...args) {
|
|
109
|
+
const [name, props] = args;
|
|
110
|
+
debugLog(`[TRACK] ${name} ${formatDebugValue(props ?? "")}`);
|
|
111
|
+
}
|
|
112
|
+
function formatDebugValue2(value) {
|
|
113
|
+
if (value === void 0 || value === "") return "";
|
|
114
|
+
if (typeof value === "string") return value;
|
|
115
|
+
try {
|
|
116
|
+
return JSON.stringify(value);
|
|
117
|
+
} catch {
|
|
118
|
+
return String(value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function identify(userId, traits) {
|
|
122
|
+
debugLog(`[IDENTIFY] ${userId} ${formatDebugValue2(traits ?? "")}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ../platform-kernel/src/ids.ts
|
|
126
|
+
function makePrefixedIdConstructor(prefix, fieldName) {
|
|
127
|
+
const re = new RegExp(`^${prefix}_[A-Za-z0-9_\\-]+$`);
|
|
128
|
+
return (raw) => {
|
|
129
|
+
if (typeof raw !== "string" || !re.test(raw)) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Invalid ${fieldName}: expected string matching ^${prefix}_[A-Za-z0-9_\\-]+$, got ${String(raw)}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return raw;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
var toOperationId = makePrefixedIdConstructor(
|
|
138
|
+
"op",
|
|
139
|
+
"operationId"
|
|
140
|
+
);
|
|
141
|
+
var toCorrelationId = makePrefixedIdConstructor("ctx", "correlationId");
|
|
142
|
+
var toExternalAccountId = makePrefixedIdConstructor("ext", "externalAccountId");
|
|
143
|
+
|
|
144
|
+
// src/core/external-accounts.ts
|
|
145
|
+
function brandExternalAccount(raw) {
|
|
146
|
+
return {
|
|
147
|
+
...raw,
|
|
148
|
+
id: toExternalAccountId(raw.id),
|
|
149
|
+
operation: {
|
|
150
|
+
id: toOperationId(raw.operation.id),
|
|
151
|
+
status: raw.operation.status,
|
|
152
|
+
correlationId: toCorrelationId(raw.operation.correlationId)
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function createExternalAccountsClient(config = {}) {
|
|
157
|
+
return {
|
|
158
|
+
retrieve: async (externalAccountId) => {
|
|
159
|
+
if (!config.data) {
|
|
160
|
+
return stub(
|
|
161
|
+
"externalAccounts.retrieve"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const [err, raw] = await tryCatch(
|
|
165
|
+
config.data.query(api.externalAccounts.queries.retrievePersonal, {
|
|
166
|
+
externalAccountId
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
if (err) {
|
|
170
|
+
return [
|
|
171
|
+
fromConvexError(err),
|
|
172
|
+
null
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
if (!raw) {
|
|
176
|
+
return [
|
|
177
|
+
new CapxulError({
|
|
178
|
+
code: "NOT_FOUND",
|
|
179
|
+
message: `external_account ${externalAccountId} not found`
|
|
180
|
+
}),
|
|
181
|
+
null
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
return [null, brandExternalAccount(raw)];
|
|
185
|
+
},
|
|
186
|
+
remove: async (externalAccountId) => {
|
|
187
|
+
if (!config.data) {
|
|
188
|
+
return stub("externalAccounts.remove");
|
|
189
|
+
}
|
|
190
|
+
const [err] = await tryCatch(
|
|
191
|
+
config.data.mutation(api.externalAccounts.mutations.removePersonal, {
|
|
192
|
+
externalAccountId
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
if (err) {
|
|
196
|
+
return [
|
|
197
|
+
fromConvexError(err),
|
|
198
|
+
null
|
|
199
|
+
];
|
|
200
|
+
}
|
|
201
|
+
return [null, void 0];
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
72
206
|
// src/core/accounts.ts
|
|
207
|
+
function createAccountExternalAccountsClient(config) {
|
|
208
|
+
return {
|
|
209
|
+
create: async (input) => {
|
|
210
|
+
if (!config.data) {
|
|
211
|
+
return stub(
|
|
212
|
+
"accounts.externalAccounts.create"
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
const [err, raw] = await tryCatch(
|
|
216
|
+
config.data.mutation(
|
|
217
|
+
api.externalAccounts.mutations.createPersonal,
|
|
218
|
+
{
|
|
219
|
+
kind: input.kind,
|
|
220
|
+
label: input.label,
|
|
221
|
+
address: input.address,
|
|
222
|
+
iban: input.iban,
|
|
223
|
+
bic: input.bic,
|
|
224
|
+
accountHolder: input.accountHolder,
|
|
225
|
+
network: input.network,
|
|
226
|
+
panToken: input.panToken,
|
|
227
|
+
last4: input.last4
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
|
+
if (err) {
|
|
232
|
+
return [
|
|
233
|
+
fromConvexError(err),
|
|
234
|
+
null
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
if (!raw) {
|
|
238
|
+
return [
|
|
239
|
+
new CapxulError({
|
|
240
|
+
code: "NOT_FOUND",
|
|
241
|
+
message: "external_account creation returned no resource"
|
|
242
|
+
}),
|
|
243
|
+
null
|
|
244
|
+
];
|
|
245
|
+
}
|
|
246
|
+
return [
|
|
247
|
+
null,
|
|
248
|
+
brandExternalAccount(
|
|
249
|
+
raw
|
|
250
|
+
)
|
|
251
|
+
];
|
|
252
|
+
},
|
|
253
|
+
list: async (input) => {
|
|
254
|
+
if (!config.data) {
|
|
255
|
+
return stub(
|
|
256
|
+
"accounts.externalAccounts.list"
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
const [err, result] = await tryCatch(
|
|
260
|
+
config.data.query(api.externalAccounts.queries.listPersonal, {
|
|
261
|
+
limit: input.limit,
|
|
262
|
+
cursor: input.cursor
|
|
263
|
+
})
|
|
264
|
+
);
|
|
265
|
+
if (err) {
|
|
266
|
+
return [fromConvexError(err), null];
|
|
267
|
+
}
|
|
268
|
+
const branded = result.data.map(
|
|
269
|
+
(row) => brandExternalAccount(
|
|
270
|
+
row
|
|
271
|
+
)
|
|
272
|
+
);
|
|
273
|
+
return [
|
|
274
|
+
null,
|
|
275
|
+
{
|
|
276
|
+
object: "list",
|
|
277
|
+
data: branded,
|
|
278
|
+
page: result.page
|
|
279
|
+
}
|
|
280
|
+
];
|
|
281
|
+
},
|
|
282
|
+
retrieve: async (externalAccountId) => {
|
|
283
|
+
if (!config.data) {
|
|
284
|
+
return stub(
|
|
285
|
+
"accounts.externalAccounts.retrieve"
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const [err, raw] = await tryCatch(
|
|
289
|
+
config.data.query(api.externalAccounts.queries.retrievePersonal, {
|
|
290
|
+
externalAccountId
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
if (err) {
|
|
294
|
+
return [
|
|
295
|
+
fromConvexError(err),
|
|
296
|
+
null
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
if (!raw) {
|
|
300
|
+
return [
|
|
301
|
+
new CapxulError({
|
|
302
|
+
code: "NOT_FOUND",
|
|
303
|
+
message: `external_account ${externalAccountId} not found`
|
|
304
|
+
}),
|
|
305
|
+
null
|
|
306
|
+
];
|
|
307
|
+
}
|
|
308
|
+
return [
|
|
309
|
+
null,
|
|
310
|
+
brandExternalAccount(
|
|
311
|
+
raw
|
|
312
|
+
)
|
|
313
|
+
];
|
|
314
|
+
},
|
|
315
|
+
remove: async (externalAccountId) => {
|
|
316
|
+
if (!config.data) {
|
|
317
|
+
return stub("accounts.externalAccounts.remove");
|
|
318
|
+
}
|
|
319
|
+
const [err] = await tryCatch(
|
|
320
|
+
config.data.mutation(api.externalAccounts.mutations.removePersonal, {
|
|
321
|
+
externalAccountId
|
|
322
|
+
})
|
|
323
|
+
);
|
|
324
|
+
if (err) {
|
|
325
|
+
return [
|
|
326
|
+
fromConvexError(err),
|
|
327
|
+
null
|
|
328
|
+
];
|
|
329
|
+
}
|
|
330
|
+
return [null, void 0];
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
73
334
|
function createAccountsClient(config = {}) {
|
|
74
335
|
return {
|
|
75
336
|
retrieve: async (accountId) => {
|
|
@@ -224,18 +485,7 @@ function createAccountsClient(config = {}) {
|
|
|
224
485
|
create: async () => stub("accounts.kycProfiles.create"),
|
|
225
486
|
retrieve: async () => stub("accounts.kycProfiles.retrieve")
|
|
226
487
|
},
|
|
227
|
-
externalAccounts:
|
|
228
|
-
create: async () => stub(
|
|
229
|
-
"accounts.externalAccounts.create"
|
|
230
|
-
),
|
|
231
|
-
list: async () => stub(
|
|
232
|
-
"accounts.externalAccounts.list"
|
|
233
|
-
),
|
|
234
|
-
retrieve: async () => stub(
|
|
235
|
-
"accounts.externalAccounts.retrieve"
|
|
236
|
-
),
|
|
237
|
-
remove: async () => stub("accounts.externalAccounts.remove")
|
|
238
|
-
},
|
|
488
|
+
externalAccounts: createAccountExternalAccountsClient(config),
|
|
239
489
|
subAccounts: {
|
|
240
490
|
create: async () => stub("accounts.subAccounts.create"),
|
|
241
491
|
list: async () => stub("accounts.subAccounts.list"),
|
|
@@ -329,8 +579,35 @@ var Errors = {
|
|
|
329
579
|
"Idempotency key was already used for a different request",
|
|
330
580
|
{ details }
|
|
331
581
|
),
|
|
332
|
-
emailDeliveryFailed: (detail) => new CapxulError2("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}
|
|
333
|
-
|
|
582
|
+
emailDeliveryFailed: (detail, details) => new CapxulError2("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`, {
|
|
583
|
+
details
|
|
584
|
+
}),
|
|
585
|
+
rateLimited: (details) => new CapxulError2("RATE_LIMITED", "Request was rate limited", {
|
|
586
|
+
details: { ...details }
|
|
587
|
+
}),
|
|
588
|
+
internalError: (reason) => new CapxulError2("INTERNAL_ERROR", `Internal error: ${reason}`),
|
|
589
|
+
/**
|
|
590
|
+
* Verification gate. Surfaced when a request hits a verification
|
|
591
|
+
* boundary the actor cannot cross under their current state. Two
|
|
592
|
+
* variants share this code:
|
|
593
|
+
*
|
|
594
|
+
* - Rail gate (Withdrawals v1 W2, #465): the resolved
|
|
595
|
+
* `external_account.kind` routes to a withdrawal rail (e.g.
|
|
596
|
+
* `fiat_offramp`, `card_payout`) that is not yet supported. Carries
|
|
597
|
+
* `details.rail` + `details.currentKind`.
|
|
598
|
+
* - KYC tier gate (legacy / future): the actor's KYC tier is below
|
|
599
|
+
* the required tier. Carries `details.requiredTier`.
|
|
600
|
+
*
|
|
601
|
+
* Code is shared because both expose the same UX shape ("you cannot
|
|
602
|
+
* proceed until verification advances"); the `details.*` keys
|
|
603
|
+
* differentiate the route.
|
|
604
|
+
*/
|
|
605
|
+
verificationRequired: (details) => {
|
|
606
|
+
const message = "rail" in details ? `Withdrawal rail "${details.rail}" (kind=${details.currentKind}) is not yet supported.` : `Verification tier ${details.requiredTier} is required.`;
|
|
607
|
+
return new CapxulError2("VERIFICATION_REQUIRED", message, {
|
|
608
|
+
details: { ...details }
|
|
609
|
+
});
|
|
610
|
+
}
|
|
334
611
|
};
|
|
335
612
|
|
|
336
613
|
// ../config/src/safe.ts
|
|
@@ -380,13 +657,13 @@ function createLifecycle(initial) {
|
|
|
380
657
|
}
|
|
381
658
|
function makeBuildTimeUrlsTransport(config) {
|
|
382
659
|
if (!config.authBaseUrl || config.authBaseUrl.trim().length === 0) {
|
|
383
|
-
throw
|
|
660
|
+
throw invalidConfigError(
|
|
384
661
|
"authBaseUrl",
|
|
385
662
|
"build-time-urls transport requires a non-empty authBaseUrl."
|
|
386
663
|
);
|
|
387
664
|
}
|
|
388
665
|
if (!config.convexUrl || config.convexUrl.trim().length === 0) {
|
|
389
|
-
throw
|
|
666
|
+
throw invalidConfigError(
|
|
390
667
|
"convexUrl",
|
|
391
668
|
"build-time-urls transport requires a non-empty convexUrl."
|
|
392
669
|
);
|
|
@@ -400,6 +677,7 @@ function makeBuildTimeUrlsTransport(config) {
|
|
|
400
677
|
return {
|
|
401
678
|
authBaseUrl,
|
|
402
679
|
convexUrl,
|
|
680
|
+
ensureRuntime: async () => runtime,
|
|
403
681
|
fetch: (path, init) => fetchImpl(resolveUrl(authBaseUrl, path), init),
|
|
404
682
|
getState: lifecycle.getState,
|
|
405
683
|
subscribe: lifecycle.subscribe,
|
|
@@ -415,14 +693,15 @@ function makeBuildTimeUrlsTransport(config) {
|
|
|
415
693
|
};
|
|
416
694
|
}
|
|
417
695
|
function makePublishableKeyTransport(config) {
|
|
418
|
-
|
|
419
|
-
|
|
696
|
+
const publishableKey = config.publishableKey?.trim();
|
|
697
|
+
if (!publishableKey) {
|
|
698
|
+
throw invalidConfigError(
|
|
420
699
|
"publishableKey",
|
|
421
700
|
"publishable-key transport requires a non-empty publishableKey."
|
|
422
701
|
);
|
|
423
702
|
}
|
|
424
703
|
const fetchImpl = config.fetchImpl ?? globalThis.fetch;
|
|
425
|
-
const bootstrapUrl =
|
|
704
|
+
const bootstrapUrl = normalizeBootstrapUrl(
|
|
426
705
|
config.bootstrapUrl ?? `${CAPXUL_API_BASE_URL}/v1/client/bootstrap`
|
|
427
706
|
);
|
|
428
707
|
let authBaseUrl = "";
|
|
@@ -437,23 +716,20 @@ function makePublishableKeyTransport(config) {
|
|
|
437
716
|
const response = await fetchImpl(bootstrapUrl, {
|
|
438
717
|
method: "POST",
|
|
439
718
|
headers: { "content-type": "application/json" },
|
|
440
|
-
body: JSON.stringify({ publishableKey
|
|
719
|
+
body: JSON.stringify({ publishableKey })
|
|
441
720
|
});
|
|
442
721
|
if (!response.ok) {
|
|
443
|
-
throw
|
|
444
|
-
"publishableKey",
|
|
445
|
-
`${bootstrapUrl} failed with HTTP ${response.status}.`
|
|
446
|
-
);
|
|
722
|
+
throw await bootstrapResponseError(response, bootstrapUrl);
|
|
447
723
|
}
|
|
448
|
-
const body = await response
|
|
724
|
+
const body = await readBootstrapSuccessBody(response);
|
|
449
725
|
if (typeof body.authBaseUrl !== "string" || body.authBaseUrl.trim().length === 0) {
|
|
450
|
-
throw
|
|
726
|
+
throw bootstrapContractError(
|
|
451
727
|
"authBaseUrl",
|
|
452
728
|
"/v1/client/bootstrap returned no authBaseUrl."
|
|
453
729
|
);
|
|
454
730
|
}
|
|
455
731
|
if (typeof body.convexUrl !== "string" || body.convexUrl.trim().length === 0) {
|
|
456
|
-
throw
|
|
732
|
+
throw bootstrapContractError(
|
|
457
733
|
"convexUrl",
|
|
458
734
|
"/v1/client/bootstrap returned no convexUrl."
|
|
459
735
|
);
|
|
@@ -465,16 +741,13 @@ function makePublishableKeyTransport(config) {
|
|
|
465
741
|
return runtime;
|
|
466
742
|
})();
|
|
467
743
|
bootstrapPromise = attempt.catch((err) => {
|
|
744
|
+
const error = normalizeBootstrapThrownError(err);
|
|
468
745
|
bootstrapPromise = null;
|
|
469
746
|
lifecycle.setState({
|
|
470
747
|
status: "error",
|
|
471
|
-
error
|
|
472
|
-
code: "UNKNOWN",
|
|
473
|
-
message: "Bootstrap failed without a typed CapxulError.",
|
|
474
|
-
cause: err
|
|
475
|
-
})
|
|
748
|
+
error
|
|
476
749
|
});
|
|
477
|
-
throw
|
|
750
|
+
throw error;
|
|
478
751
|
});
|
|
479
752
|
return await bootstrapPromise;
|
|
480
753
|
}
|
|
@@ -485,6 +758,7 @@ function makePublishableKeyTransport(config) {
|
|
|
485
758
|
get convexUrl() {
|
|
486
759
|
return convexUrl;
|
|
487
760
|
},
|
|
761
|
+
ensureRuntime: ensureBootstrap,
|
|
488
762
|
fetch: async (path, init) => {
|
|
489
763
|
const resolved = await ensureBootstrap();
|
|
490
764
|
return await fetchImpl(resolveUrl(resolved.authBaseUrl, path), init);
|
|
@@ -495,7 +769,7 @@ function makePublishableKeyTransport(config) {
|
|
|
495
769
|
markAuthenticated: ({ dataClient: nextDataClient }) => {
|
|
496
770
|
const current = lifecycle.getState();
|
|
497
771
|
if (current.status !== "ready" && current.status !== "authenticated") {
|
|
498
|
-
throw
|
|
772
|
+
throw internalTransportError(
|
|
499
773
|
`markAuthenticated() called from status="${current.status}". Expected "ready" or "authenticated".`
|
|
500
774
|
);
|
|
501
775
|
}
|
|
@@ -517,6 +791,24 @@ function makePublishableKeyTransport(config) {
|
|
|
517
791
|
function stripTrailingSlash(url) {
|
|
518
792
|
return url.replace(/\/+$/, "");
|
|
519
793
|
}
|
|
794
|
+
function normalizeBootstrapUrl(url) {
|
|
795
|
+
const normalized = stripTrailingSlash(url.trim());
|
|
796
|
+
if (!isAbsoluteHttpUrl(normalized)) {
|
|
797
|
+
throw invalidConfigError(
|
|
798
|
+
"bootstrapUrl",
|
|
799
|
+
"publishable-key transport requires an absolute http(s) bootstrapUrl."
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
return normalized;
|
|
803
|
+
}
|
|
804
|
+
function isAbsoluteHttpUrl(url) {
|
|
805
|
+
try {
|
|
806
|
+
const parsed = new URL(url);
|
|
807
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
808
|
+
} catch {
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
520
812
|
function resolveUrl(authBaseUrl, path) {
|
|
521
813
|
if (path.startsWith("http://") || path.startsWith("https://")) {
|
|
522
814
|
return path;
|
|
@@ -524,10 +816,142 @@ function resolveUrl(authBaseUrl, path) {
|
|
|
524
816
|
return `${authBaseUrl}${path}`;
|
|
525
817
|
}
|
|
526
818
|
function assertNever(value) {
|
|
527
|
-
throw
|
|
819
|
+
throw internalTransportError(
|
|
528
820
|
`Unhandled BrowserCapxulConfig.mode: ${String(value.mode)}.`
|
|
529
821
|
);
|
|
530
822
|
}
|
|
823
|
+
function invalidConfigError(field, reason) {
|
|
824
|
+
return new CapxulError({
|
|
825
|
+
code: "INVALID_INPUT",
|
|
826
|
+
message: `Invalid ${field}: ${reason}`,
|
|
827
|
+
details: { source: "sdk-config", field, reason }
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
function bootstrapContractError(field, message) {
|
|
831
|
+
return new CapxulError({
|
|
832
|
+
code: "INVALID_INPUT",
|
|
833
|
+
message,
|
|
834
|
+
details: {
|
|
835
|
+
source: "backend-bootstrap",
|
|
836
|
+
phase: "publishable-key-bootstrap",
|
|
837
|
+
field,
|
|
838
|
+
reason: message
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
function internalTransportError(reason) {
|
|
843
|
+
return new CapxulError({
|
|
844
|
+
code: "INTERNAL_ERROR",
|
|
845
|
+
message: `Internal error: ${reason}`,
|
|
846
|
+
details: { source: "sdk-transport", reason }
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
async function bootstrapResponseError(response, bootstrapUrl) {
|
|
850
|
+
const envelope = await readBootstrapErrorEnvelope(response);
|
|
851
|
+
const wireCode = readNonEmptyString(envelope?.error?.code);
|
|
852
|
+
const normalized = normalizeBootstrapErrorCode(wireCode);
|
|
853
|
+
const message = readNonEmptyString(envelope?.error?.message) ?? `${bootstrapUrl} failed with HTTP ${response.status}.`;
|
|
854
|
+
const backendDetails = readRecord(envelope?.error?.details);
|
|
855
|
+
return new CapxulError({
|
|
856
|
+
code: normalized.code,
|
|
857
|
+
message,
|
|
858
|
+
details: {
|
|
859
|
+
...backendDetails,
|
|
860
|
+
source: "backend-bootstrap",
|
|
861
|
+
phase: "publishable-key-bootstrap",
|
|
862
|
+
httpStatus: response.status,
|
|
863
|
+
...normalized.wireCode ? { wireCode: normalized.wireCode } : {}
|
|
864
|
+
},
|
|
865
|
+
operationId: readNonEmptyString(envelope?.error?.operationId),
|
|
866
|
+
correlationId: readNonEmptyString(envelope?.error?.correlationId),
|
|
867
|
+
retryable: typeof envelope?.error?.retryable === "boolean" ? envelope.error.retryable : void 0
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
async function readBootstrapErrorEnvelope(response) {
|
|
871
|
+
try {
|
|
872
|
+
const parsed = await response.json();
|
|
873
|
+
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
874
|
+
} catch {
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
async function readBootstrapSuccessBody(response) {
|
|
879
|
+
try {
|
|
880
|
+
const parsed = await response.json();
|
|
881
|
+
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
882
|
+
} catch {
|
|
883
|
+
throw bootstrapContractError(
|
|
884
|
+
"body",
|
|
885
|
+
"/v1/client/bootstrap returned invalid JSON."
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
function normalizeBootstrapThrownError(error) {
|
|
890
|
+
if (error instanceof CapxulError) return error;
|
|
891
|
+
return new CapxulError({
|
|
892
|
+
code: "NETWORK_ERROR",
|
|
893
|
+
message: "Publishable-key bootstrap network failure.",
|
|
894
|
+
cause: error,
|
|
895
|
+
details: {
|
|
896
|
+
source: "bootstrap-network",
|
|
897
|
+
phase: "publishable-key-bootstrap"
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
function normalizeBootstrapErrorCode(wireCode) {
|
|
902
|
+
if (wireCode === "INTERNAL_SERVER_ERROR") {
|
|
903
|
+
return { code: "INTERNAL_ERROR", wireCode };
|
|
904
|
+
}
|
|
905
|
+
if (wireCode && isCapxulErrorCode(wireCode)) {
|
|
906
|
+
return { code: wireCode };
|
|
907
|
+
}
|
|
908
|
+
return wireCode ? { code: "UNKNOWN", wireCode } : { code: "UNKNOWN" };
|
|
909
|
+
}
|
|
910
|
+
var CAPXUL_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
911
|
+
"NOT_AUTHENTICATED",
|
|
912
|
+
"EMAIL_DELIVERY_FAILED",
|
|
913
|
+
"PROFILE_NOT_FOUND",
|
|
914
|
+
"SMART_ACCOUNT_MISSING",
|
|
915
|
+
"PLAYER_NOT_FOUND",
|
|
916
|
+
"ACCOUNT_NOT_FOUND",
|
|
917
|
+
"PROVIDER_ERROR",
|
|
918
|
+
"INVALID_INPUT",
|
|
919
|
+
"ENV_MISSING",
|
|
920
|
+
"NOT_IMPLEMENTED",
|
|
921
|
+
"VERIFICATION_REQUIRED",
|
|
922
|
+
"INSUFFICIENT_BALANCE",
|
|
923
|
+
"INVALID_RECIPIENT",
|
|
924
|
+
"TRANSACTION_FAILED",
|
|
925
|
+
"RATE_LIMITED",
|
|
926
|
+
"NETWORK_ERROR",
|
|
927
|
+
"UNKNOWN",
|
|
928
|
+
"PERMISSION_DENIED",
|
|
929
|
+
"API_KEY_INVALID",
|
|
930
|
+
"API_KEY_EXPIRED",
|
|
931
|
+
"IDEMPOTENCY_CONFLICT",
|
|
932
|
+
"NOT_FOUND",
|
|
933
|
+
"OPERATION_CANCELED",
|
|
934
|
+
"OPERATION_TIMEOUT",
|
|
935
|
+
"ACTION_REQUIRED",
|
|
936
|
+
"KYC_REQUIRED",
|
|
937
|
+
"POLICY_DENIED",
|
|
938
|
+
"SAFE_NOT_READY",
|
|
939
|
+
"PROVIDER_UNAVAILABLE",
|
|
940
|
+
"PROVIDER_REJECTED",
|
|
941
|
+
"RECONCILIATION_FAILED",
|
|
942
|
+
"INTERNAL_ERROR",
|
|
943
|
+
"QUOTE_EXPIRED",
|
|
944
|
+
"QUOTE_NOT_FOUND"
|
|
945
|
+
]);
|
|
946
|
+
function isCapxulErrorCode(value) {
|
|
947
|
+
return CAPXUL_ERROR_CODES.has(value);
|
|
948
|
+
}
|
|
949
|
+
function readRecord(value) {
|
|
950
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
951
|
+
}
|
|
952
|
+
function readNonEmptyString(value) {
|
|
953
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
954
|
+
}
|
|
531
955
|
|
|
532
956
|
// src/core/auth.ts
|
|
533
957
|
function createAuthClient(config = {}) {
|
|
@@ -582,13 +1006,16 @@ function createAuthClient(config = {}) {
|
|
|
582
1006
|
email: signIn.user.email,
|
|
583
1007
|
token: signIn.token,
|
|
584
1008
|
convexJwt,
|
|
585
|
-
expiresAt: new Date(
|
|
1009
|
+
expiresAt: new Date(
|
|
1010
|
+
Date.now() + 30 * 24 * 60 * 60 * 1e3
|
|
1011
|
+
).toISOString()
|
|
586
1012
|
};
|
|
587
1013
|
sessionStore.set(session);
|
|
588
1014
|
if (config.auth?.createDataClient) {
|
|
589
1015
|
try {
|
|
590
1016
|
dataClient = await config.auth.createDataClient(session);
|
|
591
1017
|
mutableConfig(config).data = dataClient;
|
|
1018
|
+
transport.markAuthenticated({ dataClient });
|
|
592
1019
|
} catch (cause) {
|
|
593
1020
|
return [
|
|
594
1021
|
new CapxulError({
|
|
@@ -607,6 +1034,8 @@ function createAuthClient(config = {}) {
|
|
|
607
1034
|
sessionStore.clear();
|
|
608
1035
|
dataClient = null;
|
|
609
1036
|
mutableConfig(config).data = void 0;
|
|
1037
|
+
const transport = getTransport();
|
|
1038
|
+
transport?.clearAuth();
|
|
610
1039
|
return [null, void 0];
|
|
611
1040
|
},
|
|
612
1041
|
serviceTokenMint: async () => stub("auth.serviceTokenMint"),
|
|
@@ -660,16 +1089,19 @@ async function postBetterAuth(transport, path, body, code, signal) {
|
|
|
660
1089
|
body: JSON.stringify(body),
|
|
661
1090
|
signal
|
|
662
1091
|
});
|
|
1092
|
+
const text = await response.text();
|
|
663
1093
|
if (!response.ok) {
|
|
1094
|
+
const parsedError = parseBetterAuthError(text);
|
|
664
1095
|
return [
|
|
665
1096
|
new CapxulError({
|
|
666
|
-
code,
|
|
667
|
-
message: `BetterAuth ${path} failed with HTTP ${response.status}
|
|
1097
|
+
code: parsedError.code ?? code,
|
|
1098
|
+
message: parsedError.message ?? `BetterAuth ${path} failed with HTTP ${response.status}.`,
|
|
1099
|
+
details: parsedError.details,
|
|
1100
|
+
retryable: parsedError.retryable
|
|
668
1101
|
}),
|
|
669
1102
|
null
|
|
670
1103
|
];
|
|
671
1104
|
}
|
|
672
|
-
const text = await response.text();
|
|
673
1105
|
return [null, text ? JSON.parse(text) : void 0];
|
|
674
1106
|
} catch (cause) {
|
|
675
1107
|
return [
|
|
@@ -682,6 +1114,36 @@ async function postBetterAuth(transport, path, body, code, signal) {
|
|
|
682
1114
|
];
|
|
683
1115
|
}
|
|
684
1116
|
}
|
|
1117
|
+
function parseBetterAuthError(text) {
|
|
1118
|
+
if (!text.trim()) {
|
|
1119
|
+
return {};
|
|
1120
|
+
}
|
|
1121
|
+
try {
|
|
1122
|
+
const body = JSON.parse(text);
|
|
1123
|
+
if (!body || typeof body !== "object") {
|
|
1124
|
+
return {};
|
|
1125
|
+
}
|
|
1126
|
+
const record = body;
|
|
1127
|
+
const nested = record.error && typeof record.error === "object" ? record.error : record;
|
|
1128
|
+
const code = typeof nested.code === "string" ? nested.code : void 0;
|
|
1129
|
+
const message = typeof nested.message === "string" ? nested.message : void 0;
|
|
1130
|
+
const details = nested.details && typeof nested.details === "object" ? nested.details : void 0;
|
|
1131
|
+
const correlationId = typeof nested.correlationId === "string" ? nested.correlationId : void 0;
|
|
1132
|
+
const retryable = typeof nested.retryable === "boolean" ? nested.retryable : void 0;
|
|
1133
|
+
return {
|
|
1134
|
+
code: isCapxulErrorCode2(code) ? code : void 0,
|
|
1135
|
+
message,
|
|
1136
|
+
details,
|
|
1137
|
+
correlationId,
|
|
1138
|
+
retryable
|
|
1139
|
+
};
|
|
1140
|
+
} catch {
|
|
1141
|
+
return {};
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
function isCapxulErrorCode2(code) {
|
|
1145
|
+
return code === "NOT_AUTHENTICATED" || code === "EMAIL_DELIVERY_FAILED" || code === "INVALID_INPUT" || code === "RATE_LIMITED" || code === "NETWORK_ERROR" || code === "API_KEY_INVALID" || code === "API_KEY_EXPIRED";
|
|
1146
|
+
}
|
|
685
1147
|
async function exchangeConvexToken(transport, config, token, signal) {
|
|
686
1148
|
const path = config.auth?.convexTokenUrl ?? "/convex/token";
|
|
687
1149
|
try {
|
|
@@ -742,14 +1204,6 @@ function createOrgDocumentsClient() {
|
|
|
742
1204
|
};
|
|
743
1205
|
}
|
|
744
1206
|
|
|
745
|
-
// src/core/external-accounts.ts
|
|
746
|
-
function createExternalAccountsClient() {
|
|
747
|
-
return {
|
|
748
|
-
retrieve: async () => stub("externalAccounts.retrieve"),
|
|
749
|
-
remove: async () => stub("externalAccounts.remove")
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
|
|
753
1207
|
// src/core/me.ts
|
|
754
1208
|
function createMeClient(config = {}) {
|
|
755
1209
|
return {
|
|
@@ -1197,67 +1651,68 @@ function createOrgTransfersClient() {
|
|
|
1197
1651
|
cancel: async () => stub("organizations.transfers.cancel")
|
|
1198
1652
|
};
|
|
1199
1653
|
}
|
|
1200
|
-
var EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
1201
1654
|
function createWithdrawalsClient(config = {}) {
|
|
1202
1655
|
return {
|
|
1203
1656
|
create: async (input) => {
|
|
1204
1657
|
if (!config.data) {
|
|
1205
1658
|
return stub("withdrawals.create");
|
|
1206
1659
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
details: { field: "destination.externalAccountId" }
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
const currentSigner = await config.data.query(
|
|
1249
|
-
api.safe.queries.getMySignerAddress,
|
|
1250
|
-
{}
|
|
1660
|
+
const [createErr, createdRaw] = await tryCatch(
|
|
1661
|
+
config.data.mutation(api.withdrawals.mutations.create, {
|
|
1662
|
+
amount: input.amount,
|
|
1663
|
+
destination: {
|
|
1664
|
+
externalAccountId: input.destination.externalAccountId
|
|
1665
|
+
},
|
|
1666
|
+
source: input.source,
|
|
1667
|
+
reference: input.reference,
|
|
1668
|
+
idempotencyKey: input.idempotencyKey
|
|
1669
|
+
})
|
|
1670
|
+
);
|
|
1671
|
+
if (createErr) {
|
|
1672
|
+
return [mapCreateError2(fromConvexError(createErr)), null];
|
|
1673
|
+
}
|
|
1674
|
+
const created = createdRaw;
|
|
1675
|
+
if (!created) {
|
|
1676
|
+
return [
|
|
1677
|
+
new CapxulError({
|
|
1678
|
+
code: "NETWORK_ERROR",
|
|
1679
|
+
message: "withdrawals.create returned no withdrawal resource"
|
|
1680
|
+
}),
|
|
1681
|
+
null
|
|
1682
|
+
];
|
|
1683
|
+
}
|
|
1684
|
+
if (created.status !== "processing" || created.operation.status !== "processing") {
|
|
1685
|
+
return [null, created];
|
|
1686
|
+
}
|
|
1687
|
+
if (!config.signer || !config.signing) {
|
|
1688
|
+
return [null, created];
|
|
1689
|
+
}
|
|
1690
|
+
const [signerErr, currentSigner] = await tryCatch(
|
|
1691
|
+
config.data.query(api.safe.queries.getMySignerAddress, {})
|
|
1692
|
+
);
|
|
1693
|
+
if (signerErr) {
|
|
1694
|
+
return await handleSubmissionFailure(
|
|
1695
|
+
{ data: config.data },
|
|
1696
|
+
created.id,
|
|
1697
|
+
mapCreateError2(fromConvexError(signerErr))
|
|
1251
1698
|
);
|
|
1252
|
-
|
|
1253
|
-
|
|
1699
|
+
}
|
|
1700
|
+
if (!currentSigner?.address) {
|
|
1701
|
+
return await handleSubmissionFailure(
|
|
1702
|
+
{ data: config.data },
|
|
1703
|
+
created.id,
|
|
1704
|
+
new CapxulError({
|
|
1254
1705
|
code: "PERMISSION_DENIED",
|
|
1255
1706
|
message: "No signer is registered for the authenticated account.",
|
|
1256
1707
|
details: { withdrawalId: created.id }
|
|
1257
|
-
})
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1708
|
+
})
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
if (viem.getAddress(currentSigner.address) !== viem.getAddress(config.signer.address)) {
|
|
1712
|
+
return await handleSubmissionFailure(
|
|
1713
|
+
{ data: config.data },
|
|
1714
|
+
created.id,
|
|
1715
|
+
new CapxulError({
|
|
1261
1716
|
code: "PERMISSION_DENIED",
|
|
1262
1717
|
message: "Configured signer does not match the authenticated account signer.",
|
|
1263
1718
|
details: {
|
|
@@ -1265,170 +1720,228 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1265
1720
|
expectedSignerAddress: currentSigner.address,
|
|
1266
1721
|
actualSignerAddress: config.signer.address
|
|
1267
1722
|
}
|
|
1268
|
-
})
|
|
1269
|
-
}
|
|
1270
|
-
const submission = await config.data.query(
|
|
1271
|
-
api.withdrawals.queries.prepareSubmission,
|
|
1272
|
-
{ withdrawalId: created.id }
|
|
1723
|
+
})
|
|
1273
1724
|
);
|
|
1274
|
-
|
|
1275
|
-
|
|
1725
|
+
}
|
|
1726
|
+
const [prepErr, submission] = await tryCatch(
|
|
1727
|
+
config.data.query(api.withdrawals.queries.prepareSubmission, {
|
|
1728
|
+
withdrawalId: created.id
|
|
1729
|
+
})
|
|
1730
|
+
);
|
|
1731
|
+
if (prepErr) {
|
|
1732
|
+
return await handleSubmissionFailure(
|
|
1733
|
+
{ data: config.data },
|
|
1734
|
+
created.id,
|
|
1735
|
+
mapCreateError2(fromConvexError(prepErr))
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
const destinationAddress = submission?.destinationAddress;
|
|
1739
|
+
if (!submission || !destinationAddress) {
|
|
1740
|
+
return await handleSubmissionFailure(
|
|
1741
|
+
{ data: config.data },
|
|
1742
|
+
created.id,
|
|
1743
|
+
new CapxulError({
|
|
1276
1744
|
code: "NETWORK_ERROR",
|
|
1277
1745
|
message: "withdrawals.prepareSubmission returned no destination.",
|
|
1278
1746
|
details: { withdrawalId: created.id }
|
|
1279
|
-
})
|
|
1280
|
-
|
|
1281
|
-
|
|
1747
|
+
})
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1750
|
+
const [transferErr, transferOk] = await tryCatch(
|
|
1751
|
+
transferAsOwner(
|
|
1282
1752
|
{
|
|
1283
1753
|
signer: config.signer,
|
|
1284
1754
|
signing: config.signing
|
|
1285
1755
|
},
|
|
1286
1756
|
{
|
|
1287
1757
|
tokenAddress: resolvePaymentTokenAddress(submission.amount.currency),
|
|
1288
|
-
recipientAddress:
|
|
1758
|
+
recipientAddress: destinationAddress,
|
|
1289
1759
|
amount: toTokenUnits(submission.amount.value, 6)
|
|
1290
1760
|
}
|
|
1761
|
+
)
|
|
1762
|
+
);
|
|
1763
|
+
if (transferErr) {
|
|
1764
|
+
return await handleSubmissionFailure(
|
|
1765
|
+
{ data: config.data },
|
|
1766
|
+
created.id,
|
|
1767
|
+
mapCreateError2(fromConvexError(transferErr))
|
|
1291
1768
|
);
|
|
1292
|
-
|
|
1293
|
-
|
|
1769
|
+
}
|
|
1770
|
+
if (!transferOk.success) {
|
|
1771
|
+
return await handleSubmissionFailure(
|
|
1772
|
+
{ data: config.data },
|
|
1773
|
+
created.id,
|
|
1774
|
+
new CapxulError({
|
|
1294
1775
|
code: "NETWORK_ERROR",
|
|
1295
1776
|
message: "Bundler submission did not succeed.",
|
|
1296
1777
|
details: {
|
|
1297
1778
|
withdrawalId: created.id,
|
|
1298
|
-
txHash:
|
|
1299
|
-
userOpHash:
|
|
1779
|
+
txHash: transferOk.txHash,
|
|
1780
|
+
userOpHash: transferOk.userOpHash
|
|
1300
1781
|
}
|
|
1301
|
-
})
|
|
1302
|
-
}
|
|
1303
|
-
submitted = {
|
|
1304
|
-
txHash: transfer.txHash,
|
|
1305
|
-
userOpHash: transfer.userOpHash
|
|
1306
|
-
};
|
|
1307
|
-
await config.data.mutation(
|
|
1308
|
-
api.withdrawals.mutations.recordSubmitted,
|
|
1309
|
-
{
|
|
1310
|
-
withdrawalId: created.id,
|
|
1311
|
-
txHash: transfer.txHash,
|
|
1312
|
-
userOpHash: transfer.userOpHash
|
|
1313
|
-
}
|
|
1782
|
+
})
|
|
1314
1783
|
);
|
|
1315
|
-
return [null, created];
|
|
1316
|
-
} catch (cause) {
|
|
1317
|
-
const error = mapCreateError2(fromConvexError(cause));
|
|
1318
|
-
if (created?.id && created.status === "processing" && !submitted) {
|
|
1319
|
-
await bestEffortMarkFailed2({ data: config.data }, created.id, error);
|
|
1320
|
-
}
|
|
1321
|
-
if (submitted && created?.id) {
|
|
1322
|
-
return [
|
|
1323
|
-
new CapxulError({
|
|
1324
|
-
code: "NETWORK_ERROR",
|
|
1325
|
-
message: "Withdrawal was submitted on-chain, but backend submission tracking failed.",
|
|
1326
|
-
cause,
|
|
1327
|
-
details: {
|
|
1328
|
-
withdrawalId: created.id,
|
|
1329
|
-
txHash: submitted.txHash,
|
|
1330
|
-
userOpHash: submitted.userOpHash
|
|
1331
|
-
}
|
|
1332
|
-
}),
|
|
1333
|
-
null
|
|
1334
|
-
];
|
|
1335
|
-
}
|
|
1336
|
-
return [error, null];
|
|
1337
1784
|
}
|
|
1785
|
+
const [recordErr] = await tryCatch(
|
|
1786
|
+
config.data.mutation(api.withdrawals.mutations.recordSubmitted, {
|
|
1787
|
+
withdrawalId: created.id,
|
|
1788
|
+
txHash: transferOk.txHash,
|
|
1789
|
+
userOpHash: transferOk.userOpHash
|
|
1790
|
+
})
|
|
1791
|
+
);
|
|
1792
|
+
if (recordErr) {
|
|
1793
|
+
return [
|
|
1794
|
+
new CapxulError({
|
|
1795
|
+
code: "NETWORK_ERROR",
|
|
1796
|
+
message: "Withdrawal was submitted on-chain, but backend submission tracking failed.",
|
|
1797
|
+
cause: recordErr,
|
|
1798
|
+
details: {
|
|
1799
|
+
withdrawalId: created.id,
|
|
1800
|
+
txHash: transferOk.txHash,
|
|
1801
|
+
userOpHash: transferOk.userOpHash
|
|
1802
|
+
}
|
|
1803
|
+
}),
|
|
1804
|
+
null
|
|
1805
|
+
];
|
|
1806
|
+
}
|
|
1807
|
+
return [null, created];
|
|
1338
1808
|
},
|
|
1339
1809
|
retrieve: async (withdrawalId) => {
|
|
1340
1810
|
if (!config.data) {
|
|
1341
1811
|
return stub("withdrawals.retrieve");
|
|
1342
1812
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
);
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
code: "NOT_FOUND",
|
|
1352
|
-
message: `withdrawal ${withdrawalId} not found`
|
|
1353
|
-
}),
|
|
1354
|
-
null
|
|
1355
|
-
];
|
|
1356
|
-
}
|
|
1357
|
-
return [null, withdrawal];
|
|
1358
|
-
} catch (cause) {
|
|
1813
|
+
const [err, raw] = await tryCatch(
|
|
1814
|
+
config.data.query(api.withdrawals.queries.retrieve, { withdrawalId })
|
|
1815
|
+
);
|
|
1816
|
+
if (err) {
|
|
1817
|
+
return [fromConvexError(err), null];
|
|
1818
|
+
}
|
|
1819
|
+
const withdrawal = raw;
|
|
1820
|
+
if (!withdrawal) {
|
|
1359
1821
|
return [
|
|
1360
|
-
|
|
1822
|
+
new CapxulError({
|
|
1823
|
+
code: "NOT_FOUND",
|
|
1824
|
+
message: `withdrawal ${withdrawalId} not found`
|
|
1825
|
+
}),
|
|
1361
1826
|
null
|
|
1362
1827
|
];
|
|
1363
1828
|
}
|
|
1829
|
+
return [null, withdrawal];
|
|
1364
1830
|
},
|
|
1365
1831
|
list: async (input) => {
|
|
1366
1832
|
if (!config.data) {
|
|
1367
1833
|
return stub("withdrawals.list");
|
|
1368
1834
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1835
|
+
const [err, raw] = await tryCatch(
|
|
1836
|
+
config.data.query(api.withdrawals.queries.list, {
|
|
1837
|
+
limit: input?.limit,
|
|
1838
|
+
cursor: input?.cursor
|
|
1839
|
+
})
|
|
1840
|
+
);
|
|
1841
|
+
if (err) {
|
|
1842
|
+
return [fromConvexError(err), null];
|
|
1843
|
+
}
|
|
1844
|
+
return [null, raw];
|
|
1845
|
+
},
|
|
1846
|
+
recordCompleted: async (input) => {
|
|
1847
|
+
if (!config.data) {
|
|
1848
|
+
return stub(
|
|
1849
|
+
"withdrawals.recordCompleted"
|
|
1376
1850
|
);
|
|
1377
|
-
|
|
1378
|
-
|
|
1851
|
+
}
|
|
1852
|
+
const [err] = await tryCatch(
|
|
1853
|
+
config.data.mutation(api.withdrawals.mutations.recordCompleted, {
|
|
1854
|
+
withdrawalId: input.withdrawalId,
|
|
1855
|
+
txHash: input.txHash
|
|
1856
|
+
})
|
|
1857
|
+
);
|
|
1858
|
+
if (err) {
|
|
1379
1859
|
return [
|
|
1380
|
-
fromConvexError(
|
|
1860
|
+
mapRecordCompletedError(fromConvexError(err)),
|
|
1381
1861
|
null
|
|
1382
1862
|
];
|
|
1383
1863
|
}
|
|
1864
|
+
return [null, null];
|
|
1384
1865
|
}
|
|
1385
1866
|
};
|
|
1386
1867
|
}
|
|
1387
1868
|
function createOrgWithdrawalsClient(config = {}) {
|
|
1388
1869
|
return {
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1870
|
+
/**
|
|
1871
|
+
* Org-scope create (Withdrawals v1 W2, #465).
|
|
1872
|
+
*
|
|
1873
|
+
* D6 — returns the `processing` row only. No `transferAsOwner`
|
|
1874
|
+
* tail, no `recordSubmitted` call. Org Safe + Zodiac submission
|
|
1875
|
+
* orchestration ships in W3+.
|
|
1876
|
+
*/
|
|
1877
|
+
create: async (input) => {
|
|
1878
|
+
if (!config.data) {
|
|
1879
|
+
return stub(
|
|
1880
|
+
"organizations.withdrawals.create"
|
|
1881
|
+
);
|
|
1882
|
+
}
|
|
1883
|
+
const [err, raw] = await tryCatch(
|
|
1884
|
+
config.data.mutation(api.withdrawals.mutations.createOrg, {
|
|
1885
|
+
organizationId: input.organizationId,
|
|
1886
|
+
amount: input.amount,
|
|
1887
|
+
destination: {
|
|
1888
|
+
externalAccountId: input.destination.externalAccountId
|
|
1889
|
+
},
|
|
1890
|
+
source: input.source,
|
|
1891
|
+
reference: input.reference,
|
|
1892
|
+
idempotencyKey: input.idempotencyKey
|
|
1893
|
+
})
|
|
1894
|
+
);
|
|
1895
|
+
if (err) {
|
|
1896
|
+
return [mapCreateError2(fromConvexError(err)), null];
|
|
1897
|
+
}
|
|
1898
|
+
const created = raw;
|
|
1899
|
+
if (!created) {
|
|
1900
|
+
return [
|
|
1901
|
+
new CapxulError({
|
|
1902
|
+
code: "NETWORK_ERROR",
|
|
1903
|
+
message: "organizations.withdrawals.create returned no withdrawal resource"
|
|
1904
|
+
}),
|
|
1905
|
+
null
|
|
1906
|
+
];
|
|
1907
|
+
}
|
|
1908
|
+
return [null, created];
|
|
1909
|
+
},
|
|
1395
1910
|
retrieve: async (input) => {
|
|
1396
1911
|
if (!config.data) {
|
|
1397
1912
|
return stub(
|
|
1398
1913
|
"organizations.withdrawals.retrieve"
|
|
1399
1914
|
);
|
|
1400
1915
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
}),
|
|
1412
|
-
null
|
|
1413
|
-
];
|
|
1414
|
-
}
|
|
1415
|
-
const ownerCheck = withdrawal.owner;
|
|
1416
|
-
if (ownerCheck?.type !== "organization" || ownerCheck.id !== input.organizationId) {
|
|
1417
|
-
return [
|
|
1418
|
-
new CapxulError({
|
|
1419
|
-
code: "NOT_FOUND",
|
|
1420
|
-
message: `withdrawal ${input.withdrawalId} does not belong to organization ${input.organizationId}`
|
|
1421
|
-
}),
|
|
1422
|
-
null
|
|
1423
|
-
];
|
|
1424
|
-
}
|
|
1425
|
-
return [null, withdrawal];
|
|
1426
|
-
} catch (cause) {
|
|
1916
|
+
const [err, raw] = await tryCatch(
|
|
1917
|
+
config.data.query(api.withdrawals.queries.retrieve, {
|
|
1918
|
+
withdrawalId: input.withdrawalId
|
|
1919
|
+
})
|
|
1920
|
+
);
|
|
1921
|
+
if (err) {
|
|
1922
|
+
return [fromConvexError(err), null];
|
|
1923
|
+
}
|
|
1924
|
+
const withdrawal = raw;
|
|
1925
|
+
if (!withdrawal) {
|
|
1427
1926
|
return [
|
|
1428
|
-
|
|
1927
|
+
new CapxulError({
|
|
1928
|
+
code: "NOT_FOUND",
|
|
1929
|
+
message: `withdrawal ${input.withdrawalId} not found`
|
|
1930
|
+
}),
|
|
1931
|
+
null
|
|
1932
|
+
];
|
|
1933
|
+
}
|
|
1934
|
+
const ownerCheck = withdrawal.owner;
|
|
1935
|
+
if (ownerCheck?.type !== "organization" || ownerCheck.id !== input.organizationId) {
|
|
1936
|
+
return [
|
|
1937
|
+
new CapxulError({
|
|
1938
|
+
code: "NOT_FOUND",
|
|
1939
|
+
message: `withdrawal ${input.withdrawalId} does not belong to organization ${input.organizationId}`
|
|
1940
|
+
}),
|
|
1429
1941
|
null
|
|
1430
1942
|
];
|
|
1431
1943
|
}
|
|
1944
|
+
return [null, withdrawal];
|
|
1432
1945
|
},
|
|
1433
1946
|
list: async (input) => {
|
|
1434
1947
|
if (!config.data) {
|
|
@@ -1436,34 +1949,32 @@ function createOrgWithdrawalsClient(config = {}) {
|
|
|
1436
1949
|
"organizations.withdrawals.list"
|
|
1437
1950
|
);
|
|
1438
1951
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
);
|
|
1448
|
-
return [null, result];
|
|
1449
|
-
} catch (cause) {
|
|
1450
|
-
return [
|
|
1451
|
-
fromConvexError(cause),
|
|
1452
|
-
null
|
|
1453
|
-
];
|
|
1952
|
+
const [err, raw] = await tryCatch(
|
|
1953
|
+
config.data.query(api.withdrawals.queries.listOrg, {
|
|
1954
|
+
organizationId: input.organizationId,
|
|
1955
|
+
limit: input.limit,
|
|
1956
|
+
cursor: input.cursor
|
|
1957
|
+
})
|
|
1958
|
+
);
|
|
1959
|
+
if (err) {
|
|
1960
|
+
return [fromConvexError(err), null];
|
|
1454
1961
|
}
|
|
1962
|
+
return [null, raw];
|
|
1455
1963
|
}
|
|
1456
1964
|
};
|
|
1457
1965
|
}
|
|
1966
|
+
async function handleSubmissionFailure(config, withdrawalId, error) {
|
|
1967
|
+
await bestEffortMarkFailed2(config, withdrawalId, error);
|
|
1968
|
+
return [error, null];
|
|
1969
|
+
}
|
|
1458
1970
|
async function bestEffortMarkFailed2(config, withdrawalId, error) {
|
|
1459
|
-
|
|
1460
|
-
|
|
1971
|
+
await tryCatch(
|
|
1972
|
+
config.data.mutation(api.withdrawals.mutations.markFailed, {
|
|
1461
1973
|
withdrawalId,
|
|
1462
1974
|
errorCode: error.code,
|
|
1463
1975
|
errorMessage: error.message
|
|
1464
|
-
})
|
|
1465
|
-
|
|
1466
|
-
}
|
|
1976
|
+
})
|
|
1977
|
+
);
|
|
1467
1978
|
}
|
|
1468
1979
|
function mapCreateError2(error) {
|
|
1469
1980
|
switch (error.code) {
|
|
@@ -1476,6 +1987,29 @@ function mapCreateError2(error) {
|
|
|
1476
1987
|
case "POLICY_DENIED":
|
|
1477
1988
|
case "RATE_LIMITED":
|
|
1478
1989
|
case "NETWORK_ERROR":
|
|
1990
|
+
case "NOT_FOUND":
|
|
1991
|
+
case "VERIFICATION_REQUIRED":
|
|
1992
|
+
return error;
|
|
1993
|
+
default:
|
|
1994
|
+
return new CapxulError({
|
|
1995
|
+
code: "NETWORK_ERROR",
|
|
1996
|
+
message: error.message,
|
|
1997
|
+
cause: error,
|
|
1998
|
+
details: error.details,
|
|
1999
|
+
operationId: error.operationId,
|
|
2000
|
+
correlationId: error.correlationId,
|
|
2001
|
+
retryable: error.retryable
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
function mapRecordCompletedError(error) {
|
|
2006
|
+
switch (error.code) {
|
|
2007
|
+
case "NOT_AUTHENTICATED":
|
|
2008
|
+
case "PERMISSION_DENIED":
|
|
2009
|
+
case "INVALID_INPUT":
|
|
2010
|
+
case "NOT_FOUND":
|
|
2011
|
+
case "NETWORK_ERROR":
|
|
2012
|
+
case "INTERNAL_ERROR":
|
|
1479
2013
|
return error;
|
|
1480
2014
|
default:
|
|
1481
2015
|
return new CapxulError({
|
|
@@ -1511,6 +2045,136 @@ function createWebhookEventsClient() {
|
|
|
1511
2045
|
}
|
|
1512
2046
|
|
|
1513
2047
|
// src/core/organizations.ts
|
|
2048
|
+
function createOrgExternalAccountsClient(config) {
|
|
2049
|
+
return {
|
|
2050
|
+
create: async (input) => {
|
|
2051
|
+
if (!config.data) {
|
|
2052
|
+
return stub(
|
|
2053
|
+
"organizations.externalAccounts.create"
|
|
2054
|
+
);
|
|
2055
|
+
}
|
|
2056
|
+
const [err, raw] = await tryCatch(
|
|
2057
|
+
config.data.mutation(api.externalAccounts.mutations.createOrg, {
|
|
2058
|
+
organizationId: input.organizationId,
|
|
2059
|
+
kind: input.kind,
|
|
2060
|
+
label: input.label,
|
|
2061
|
+
address: input.address,
|
|
2062
|
+
iban: input.iban,
|
|
2063
|
+
bic: input.bic,
|
|
2064
|
+
accountHolder: input.accountHolder,
|
|
2065
|
+
network: input.network,
|
|
2066
|
+
panToken: input.panToken,
|
|
2067
|
+
last4: input.last4
|
|
2068
|
+
})
|
|
2069
|
+
);
|
|
2070
|
+
if (err) {
|
|
2071
|
+
return [
|
|
2072
|
+
fromConvexError(err),
|
|
2073
|
+
null
|
|
2074
|
+
];
|
|
2075
|
+
}
|
|
2076
|
+
if (!raw) {
|
|
2077
|
+
return [
|
|
2078
|
+
new CapxulError({
|
|
2079
|
+
code: "NOT_FOUND",
|
|
2080
|
+
message: "external_account creation returned no resource"
|
|
2081
|
+
}),
|
|
2082
|
+
null
|
|
2083
|
+
];
|
|
2084
|
+
}
|
|
2085
|
+
return [
|
|
2086
|
+
null,
|
|
2087
|
+
brandExternalAccount(
|
|
2088
|
+
raw
|
|
2089
|
+
)
|
|
2090
|
+
];
|
|
2091
|
+
},
|
|
2092
|
+
list: async (input) => {
|
|
2093
|
+
if (!config.data) {
|
|
2094
|
+
return stub(
|
|
2095
|
+
"organizations.externalAccounts.list"
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2098
|
+
const [err, result] = await tryCatch(
|
|
2099
|
+
config.data.query(api.externalAccounts.queries.listOrg, {
|
|
2100
|
+
organizationId: input.organizationId,
|
|
2101
|
+
limit: input.limit,
|
|
2102
|
+
cursor: input.cursor
|
|
2103
|
+
})
|
|
2104
|
+
);
|
|
2105
|
+
if (err) {
|
|
2106
|
+
return [fromConvexError(err), null];
|
|
2107
|
+
}
|
|
2108
|
+
const branded = result.data.map(
|
|
2109
|
+
(row) => brandExternalAccount(
|
|
2110
|
+
row
|
|
2111
|
+
)
|
|
2112
|
+
);
|
|
2113
|
+
return [
|
|
2114
|
+
null,
|
|
2115
|
+
{
|
|
2116
|
+
object: "list",
|
|
2117
|
+
data: branded,
|
|
2118
|
+
page: result.page
|
|
2119
|
+
}
|
|
2120
|
+
];
|
|
2121
|
+
},
|
|
2122
|
+
retrieve: async (input) => {
|
|
2123
|
+
if (!config.data) {
|
|
2124
|
+
return stub(
|
|
2125
|
+
"organizations.externalAccounts.retrieve"
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
const [err, raw] = await tryCatch(
|
|
2129
|
+
config.data.query(api.externalAccounts.queries.retrieveOrg, {
|
|
2130
|
+
organizationId: input.organizationId,
|
|
2131
|
+
externalAccountId: input.externalAccountId
|
|
2132
|
+
})
|
|
2133
|
+
);
|
|
2134
|
+
if (err) {
|
|
2135
|
+
return [
|
|
2136
|
+
fromConvexError(err),
|
|
2137
|
+
null
|
|
2138
|
+
];
|
|
2139
|
+
}
|
|
2140
|
+
if (!raw) {
|
|
2141
|
+
return [
|
|
2142
|
+
new CapxulError({
|
|
2143
|
+
code: "NOT_FOUND",
|
|
2144
|
+
message: `external_account ${input.externalAccountId} not found`
|
|
2145
|
+
}),
|
|
2146
|
+
null
|
|
2147
|
+
];
|
|
2148
|
+
}
|
|
2149
|
+
return [
|
|
2150
|
+
null,
|
|
2151
|
+
brandExternalAccount(
|
|
2152
|
+
raw
|
|
2153
|
+
)
|
|
2154
|
+
];
|
|
2155
|
+
},
|
|
2156
|
+
remove: async (input) => {
|
|
2157
|
+
if (!config.data) {
|
|
2158
|
+
return stub(
|
|
2159
|
+
"organizations.externalAccounts.remove"
|
|
2160
|
+
);
|
|
2161
|
+
}
|
|
2162
|
+
const [err] = await tryCatch(
|
|
2163
|
+
config.data.mutation(api.externalAccounts.mutations.removeOrg, {
|
|
2164
|
+
organizationId: input.organizationId,
|
|
2165
|
+
externalAccountId: input.externalAccountId
|
|
2166
|
+
})
|
|
2167
|
+
);
|
|
2168
|
+
if (err) {
|
|
2169
|
+
return [
|
|
2170
|
+
fromConvexError(err),
|
|
2171
|
+
null
|
|
2172
|
+
];
|
|
2173
|
+
}
|
|
2174
|
+
return [null, void 0];
|
|
2175
|
+
}
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
1514
2178
|
function createOrganizationsClient(config = {}) {
|
|
1515
2179
|
return {
|
|
1516
2180
|
create: async () => stub("organizations.create"),
|
|
@@ -1566,18 +2230,7 @@ function createOrganizationsClient(config = {}) {
|
|
|
1566
2230
|
retrieve: async () => stub("organizations.subAccounts.retrieve"),
|
|
1567
2231
|
remove: async () => stub("organizations.subAccounts.remove")
|
|
1568
2232
|
},
|
|
1569
|
-
externalAccounts:
|
|
1570
|
-
create: async () => stub(
|
|
1571
|
-
"organizations.externalAccounts.create"
|
|
1572
|
-
),
|
|
1573
|
-
list: async () => stub(
|
|
1574
|
-
"organizations.externalAccounts.list"
|
|
1575
|
-
),
|
|
1576
|
-
retrieve: async () => stub(
|
|
1577
|
-
"organizations.externalAccounts.retrieve"
|
|
1578
|
-
),
|
|
1579
|
-
remove: async () => stub("organizations.externalAccounts.remove")
|
|
1580
|
-
},
|
|
2233
|
+
externalAccounts: createOrgExternalAccountsClient(config),
|
|
1581
2234
|
balanceLedger: {
|
|
1582
2235
|
list: async () => stub(
|
|
1583
2236
|
"organizations.balanceLedger.list"
|
|
@@ -1714,50 +2367,6 @@ function createVirtualCardsClient() {
|
|
|
1714
2367
|
cancel: async () => stub("virtualCards.cancel")
|
|
1715
2368
|
};
|
|
1716
2369
|
}
|
|
1717
|
-
|
|
1718
|
-
// ../observability/src/debug-log.ts
|
|
1719
|
-
function isDevelopmentBuild() {
|
|
1720
|
-
if (typeof process === "undefined") {
|
|
1721
|
-
return false;
|
|
1722
|
-
}
|
|
1723
|
-
return process.env?.NODE_ENV === "development" || process.env?.NODE_ENV === "test";
|
|
1724
|
-
}
|
|
1725
|
-
function debugLog(line) {
|
|
1726
|
-
if (!isDevelopmentBuild()) return;
|
|
1727
|
-
if (typeof globalThis !== "undefined" && "window" in globalThis && typeof console?.info === "function") {
|
|
1728
|
-
console.info(line);
|
|
1729
|
-
return;
|
|
1730
|
-
}
|
|
1731
|
-
if (typeof process !== "undefined" && typeof process.stderr?.write === "function") {
|
|
1732
|
-
process.stderr.write(`${line}
|
|
1733
|
-
`);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
function formatDebugValue(value) {
|
|
1737
|
-
if (value === void 0 || value === "") return "";
|
|
1738
|
-
if (typeof value === "string") return value;
|
|
1739
|
-
try {
|
|
1740
|
-
return JSON.stringify(value);
|
|
1741
|
-
} catch {
|
|
1742
|
-
return String(value);
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
function track(...args) {
|
|
1746
|
-
const [name, props] = args;
|
|
1747
|
-
debugLog(`[TRACK] ${name} ${formatDebugValue(props ?? "")}`);
|
|
1748
|
-
}
|
|
1749
|
-
function formatDebugValue2(value) {
|
|
1750
|
-
if (value === void 0 || value === "") return "";
|
|
1751
|
-
if (typeof value === "string") return value;
|
|
1752
|
-
try {
|
|
1753
|
-
return JSON.stringify(value);
|
|
1754
|
-
} catch {
|
|
1755
|
-
return String(value);
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
function identify(userId, traits) {
|
|
1759
|
-
debugLog(`[IDENTIFY] ${userId} ${formatDebugValue2(traits ?? "")}`);
|
|
1760
|
-
}
|
|
1761
2370
|
function createAuthFlowMachine(client) {
|
|
1762
2371
|
return xstate.setup({
|
|
1763
2372
|
types: {},
|
|
@@ -2033,23 +2642,6 @@ function emailDomain(email) {
|
|
|
2033
2642
|
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
2034
2643
|
return domain || "unknown";
|
|
2035
2644
|
}
|
|
2036
|
-
|
|
2037
|
-
// ../platform-kernel/src/ids.ts
|
|
2038
|
-
function makePrefixedIdConstructor(prefix, fieldName) {
|
|
2039
|
-
const re = new RegExp(`^${prefix}_[A-Za-z0-9_\\-]+$`);
|
|
2040
|
-
return (raw) => {
|
|
2041
|
-
if (typeof raw !== "string" || !re.test(raw)) {
|
|
2042
|
-
throw new Error(
|
|
2043
|
-
`Invalid ${fieldName}: expected string matching ^${prefix}_[A-Za-z0-9_\\-]+$, got ${String(raw)}`
|
|
2044
|
-
);
|
|
2045
|
-
}
|
|
2046
|
-
return raw;
|
|
2047
|
-
};
|
|
2048
|
-
}
|
|
2049
|
-
var toOperationId = makePrefixedIdConstructor(
|
|
2050
|
-
"op",
|
|
2051
|
-
"operationId"
|
|
2052
|
-
);
|
|
2053
2645
|
function createProvisioningMachine(client) {
|
|
2054
2646
|
return xstate.setup({
|
|
2055
2647
|
types: {},
|
|
@@ -2442,7 +3034,7 @@ function createCapxulClient(config = {}) {
|
|
|
2442
3034
|
subAccounts: createSubAccountsClient(),
|
|
2443
3035
|
virtualAccounts: createVirtualAccountsClient(),
|
|
2444
3036
|
virtualCards: createVirtualCardsClient(),
|
|
2445
|
-
externalAccounts: createExternalAccountsClient(),
|
|
3037
|
+
externalAccounts: createExternalAccountsClient(config),
|
|
2446
3038
|
operations: createOperationsClient(config),
|
|
2447
3039
|
webhookEndpoints: createWebhookEndpointsClient(),
|
|
2448
3040
|
webhookEvents: createWebhookEventsClient(),
|