@capxul/sdk 0.1.0-alpha.8 → 0.2.0-alpha.3
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 +122 -0
- package/README.md +45 -0
- package/dist/{client-DDAVWtzJ.d.cts → client-B_Z3ThFO.d.cts} +231 -42
- package/dist/{client-ByzDfG98.d.ts → client-pMBRFcsz.d.ts} +231 -42
- package/dist/client.cjs +1678 -406
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.js +1678 -406
- package/dist/{errors-QHD5Tlok.d.ts → errors-CwhCWGxm.d.ts} +1 -1
- package/dist/{errors-GgKrSUKp.d.cts → errors-rqxuUhQP.d.cts} +1 -1
- package/dist/errors.d.cts +2 -2
- package/dist/errors.d.ts +2 -2
- package/dist/index.cjs +1735 -394
- package/dist/index.d.cts +90 -40
- package/dist/index.d.ts +90 -40
- package/dist/index.js +1733 -396
- package/dist/{next-action-DkrwXYay.d.cts → next-action-CTGl8wpy.d.cts} +2 -2
- package/dist/{next-action-DkrwXYay.d.ts → next-action-CTGl8wpy.d.ts} +2 -2
- package/dist/{types-hfcOE7Oi.d.cts → types-Brucpq0Z.d.cts} +63 -8
- package/dist/{types-PM4AQRLP.d.ts → types-V_D7qjxY.d.ts} +63 -8
- package/dist/webhooks.cjs +1 -1
- package/dist/webhooks.d.cts +2 -2
- package/dist/webhooks.d.ts +2 -2
- package/dist/webhooks.js +1 -1
- package/package.json +7 -5
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { componentsGeneric, anyApi } from 'convex/server';
|
|
2
|
-
import { getAddress, parseUnits, createPublicClient, http, encodeFunctionData } from 'viem';
|
|
3
2
|
import { toSafeSmartAccount } from 'permissionless/accounts';
|
|
3
|
+
import { getAddress, parseUnits, createPublicClient, http, encodeFunctionData } from 'viem';
|
|
4
4
|
import { entryPoint07Address, createPaymasterClient, createBundlerClient } from 'viem/account-abstraction';
|
|
5
5
|
import { baseSepolia } from 'viem/chains';
|
|
6
|
+
import { deriveSafeAddress as deriveSafeAddress$1, defaultSafeDeriveConfig } from '@repo/safe-derive';
|
|
7
|
+
import { ConvexHttpClient } from 'convex/browser';
|
|
6
8
|
import { setup, fromPromise, assign } from 'xstate';
|
|
7
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
9
|
+
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts';
|
|
8
10
|
|
|
9
11
|
// src/_generated/api.js
|
|
10
12
|
var api = anyApi;
|
|
@@ -121,6 +123,160 @@ function identify(userId, traits) {
|
|
|
121
123
|
debugLog(`[IDENTIFY] ${userId} ${formatDebugValue2(traits ?? "")}`);
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
// ../config/src/chain.ts
|
|
127
|
+
var CAPXUL_PAYMENTS_ADDRESS = "0xe740ea65521edc9bef0ea75d30b5334711db99f4";
|
|
128
|
+
var TEST_USDC_ADDRESS = "0xf09fcbb6df9f8f918e58f9c8ab15a76ade862b77";
|
|
129
|
+
var CAPXUL_API_BASE_URL = "https://elated-oyster-269.convex.site";
|
|
130
|
+
|
|
131
|
+
// ../config/src/timing.ts
|
|
132
|
+
var FLOW_INVOKE_TIMEOUT_MS = 3e4;
|
|
133
|
+
var WEBHOOK_FRESHNESS_WINDOW_MS = 5 * 60 * 1e3;
|
|
134
|
+
|
|
135
|
+
// ../config/src/errors.ts
|
|
136
|
+
var CapxulError2 = class extends Error {
|
|
137
|
+
code;
|
|
138
|
+
details;
|
|
139
|
+
correlationId;
|
|
140
|
+
layer;
|
|
141
|
+
constructor(code, message, options) {
|
|
142
|
+
super(message, options?.cause ? { cause: options.cause } : void 0);
|
|
143
|
+
this.code = code;
|
|
144
|
+
this.details = options?.details;
|
|
145
|
+
this.correlationId = options?.correlationId;
|
|
146
|
+
this.layer = options?.layer;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
var Errors = {
|
|
150
|
+
notAuthenticated: () => new CapxulError2("NOT_AUTHENTICATED", "Not authenticated"),
|
|
151
|
+
profileNotFound: (authUserId) => new CapxulError2("PROFILE_NOT_FOUND", `Profile not found for user ${authUserId}`),
|
|
152
|
+
smartAccountMissing: (authUserId) => new CapxulError2("SMART_ACCOUNT_MISSING", `Smart account not provisioned for user ${authUserId}`),
|
|
153
|
+
envMissing: (name) => new CapxulError2("ENV_MISSING", `Environment variable ${name} not configured`),
|
|
154
|
+
openfortApi: (operation, cause) => new CapxulError2(
|
|
155
|
+
"PROVIDER_ERROR",
|
|
156
|
+
`Openfort ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
157
|
+
{ cause, details: { provider: "openfort", operation } }
|
|
158
|
+
),
|
|
159
|
+
shieldApi: (status, detail) => new CapxulError2(
|
|
160
|
+
"PROVIDER_ERROR",
|
|
161
|
+
`Shield API error (${status}): ${detail}`,
|
|
162
|
+
{ details: { provider: "shield", status } }
|
|
163
|
+
),
|
|
164
|
+
providerError: (provider, operation, cause) => (
|
|
165
|
+
// Public `message` is redacted to a fixed shape so provider-side
|
|
166
|
+
// exception text never leaks to the client. The original `cause`
|
|
167
|
+
// is preserved on `Error.cause` for server-side debugging via
|
|
168
|
+
// observability sinks (Sentry, console traces).
|
|
169
|
+
new CapxulError2(
|
|
170
|
+
"PROVIDER_ERROR",
|
|
171
|
+
`Provider error: ${provider} ${operation}`,
|
|
172
|
+
{ cause, details: { provider, operation } }
|
|
173
|
+
)
|
|
174
|
+
),
|
|
175
|
+
invalidInput: (field, reason) => new CapxulError2(
|
|
176
|
+
"INVALID_INPUT",
|
|
177
|
+
`Invalid ${field}: ${reason}`,
|
|
178
|
+
{ details: { field, reason } }
|
|
179
|
+
),
|
|
180
|
+
playerNotFound: (playerId) => new CapxulError2(
|
|
181
|
+
"PLAYER_NOT_FOUND",
|
|
182
|
+
playerId ? `Openfort player ${playerId} not found` : "Openfort player not found"
|
|
183
|
+
),
|
|
184
|
+
accountNotFound: (accountId) => new CapxulError2(
|
|
185
|
+
"ACCOUNT_NOT_FOUND",
|
|
186
|
+
accountId ? `Openfort account ${accountId} not found` : "Openfort smart account not found"
|
|
187
|
+
),
|
|
188
|
+
invalidRecipient: (reason) => new CapxulError2("INVALID_RECIPIENT", reason),
|
|
189
|
+
permissionDenied: (reason = "Permission denied") => new CapxulError2("PERMISSION_DENIED", reason),
|
|
190
|
+
notFound: (resource, id) => new CapxulError2(
|
|
191
|
+
"NOT_FOUND",
|
|
192
|
+
id ? `${resource} ${id} not found` : `${resource} not found`
|
|
193
|
+
),
|
|
194
|
+
idempotencyConflict: (details) => new CapxulError2(
|
|
195
|
+
"IDEMPOTENCY_CONFLICT",
|
|
196
|
+
"Idempotency key was already used for a different request",
|
|
197
|
+
{ details }
|
|
198
|
+
),
|
|
199
|
+
emailDeliveryFailed: (detail, details) => new CapxulError2("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`, {
|
|
200
|
+
details
|
|
201
|
+
}),
|
|
202
|
+
rateLimited: (details) => new CapxulError2("RATE_LIMITED", "Request was rate limited", {
|
|
203
|
+
details: { ...details }
|
|
204
|
+
}),
|
|
205
|
+
internalError: (reason) => new CapxulError2("INTERNAL_ERROR", `Internal error: ${reason}`),
|
|
206
|
+
/**
|
|
207
|
+
* Verification gate. Surfaced when a request hits a verification
|
|
208
|
+
* boundary the actor cannot cross under their current state. Two
|
|
209
|
+
* variants share this code:
|
|
210
|
+
*
|
|
211
|
+
* - Rail gate (Withdrawals v1 W2, #465): the resolved
|
|
212
|
+
* `external_account.kind` routes to a withdrawal rail (e.g.
|
|
213
|
+
* `fiat_offramp`, `card_payout`) that is not yet supported. Carries
|
|
214
|
+
* `details.rail` + `details.currentKind`.
|
|
215
|
+
* - KYC tier gate (legacy / future): the actor's KYC tier is below
|
|
216
|
+
* the required tier. Carries `details.requiredTier`.
|
|
217
|
+
*
|
|
218
|
+
* Code is shared because both expose the same UX shape ("you cannot
|
|
219
|
+
* proceed until verification advances"); the `details.*` keys
|
|
220
|
+
* differentiate the route.
|
|
221
|
+
*/
|
|
222
|
+
verificationRequired: (details) => {
|
|
223
|
+
const message = "rail" in details ? `Withdrawal rail "${details.rail}" (kind=${details.currentKind}) is not yet supported.` : `Verification tier ${details.requiredTier} is required.`;
|
|
224
|
+
return new CapxulError2("VERIFICATION_REQUIRED", message, {
|
|
225
|
+
details: { ...details }
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// ../config/src/safe.ts
|
|
231
|
+
var SAFE_PROXY_FACTORY = "0x4e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67";
|
|
232
|
+
var SAFE_L2_SINGLETON = "0x29fcb43b46531bca003ddc8fcb67ffe91900c762";
|
|
233
|
+
var SAFE_MODULE_SETUP = "0x2dd68b007b46fbe91b9a7c3eda5a7a1063cb5b47";
|
|
234
|
+
var SAFE_4337_MODULE = "0x75cf11467937ce3f2f357ce24ffc3dbf8fd5c226";
|
|
235
|
+
|
|
236
|
+
// ../config/src/org-roles.ts
|
|
237
|
+
function roleKeyFromLabel(label) {
|
|
238
|
+
const bytes = new TextEncoder().encode(label);
|
|
239
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
240
|
+
return "0x" + hex.padEnd(64, "0");
|
|
241
|
+
}
|
|
242
|
+
roleKeyFromLabel("OWNER");
|
|
243
|
+
roleKeyFromLabel("FINANCE_MANAGER");
|
|
244
|
+
roleKeyFromLabel("PAYMENTS_OPERATOR");
|
|
245
|
+
async function buildSafeAccount(signer, chain) {
|
|
246
|
+
try {
|
|
247
|
+
const publicClient = createPublicClient({
|
|
248
|
+
chain: baseSepolia,
|
|
249
|
+
transport: http(chain.rpcUrl)
|
|
250
|
+
});
|
|
251
|
+
return await toSafeSmartAccount({
|
|
252
|
+
client: publicClient,
|
|
253
|
+
entryPoint: { address: entryPoint07Address, version: "0.7" },
|
|
254
|
+
version: "1.4.1",
|
|
255
|
+
owners: [signer],
|
|
256
|
+
saltNonce: computeSaltNonce(signer.address),
|
|
257
|
+
safeSingletonAddress: SAFE_L2_SINGLETON,
|
|
258
|
+
safeProxyFactoryAddress: SAFE_PROXY_FACTORY,
|
|
259
|
+
safeModuleSetupAddress: SAFE_MODULE_SETUP,
|
|
260
|
+
safe4337ModuleAddress: SAFE_4337_MODULE,
|
|
261
|
+
safeModules: [],
|
|
262
|
+
setupTransactions: []
|
|
263
|
+
});
|
|
264
|
+
} catch (cause) {
|
|
265
|
+
throw new CapxulError({
|
|
266
|
+
code: "NETWORK_ERROR",
|
|
267
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
268
|
+
cause,
|
|
269
|
+
details: { chainId: chain.chainId }
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function computeSaltNonce(ownerAddress) {
|
|
274
|
+
return BigInt(`0x${ownerAddress.toLowerCase().slice(2).padEnd(64, "0")}`);
|
|
275
|
+
}
|
|
276
|
+
function deriveSafeAddress(signerAddress) {
|
|
277
|
+
return deriveSafeAddress$1(signerAddress, defaultSafeDeriveConfig);
|
|
278
|
+
}
|
|
279
|
+
|
|
124
280
|
// ../platform-kernel/src/ids.ts
|
|
125
281
|
function makePrefixedIdConstructor(prefix, fieldName) {
|
|
126
282
|
const re = new RegExp(`^${prefix}_[A-Za-z0-9_\\-]+$`);
|
|
@@ -139,7 +295,7 @@ var toAccountId = makePrefixedIdConstructor(
|
|
|
139
295
|
);
|
|
140
296
|
var toOrganizationId = makePrefixedIdConstructor("org", "organizationId");
|
|
141
297
|
var toMemberId = makePrefixedIdConstructor(
|
|
142
|
-
"
|
|
298
|
+
"mb",
|
|
143
299
|
"memberId"
|
|
144
300
|
);
|
|
145
301
|
var toSafeId = makePrefixedIdConstructor(
|
|
@@ -253,13 +409,13 @@ function brandExternalAccount(raw) {
|
|
|
253
409
|
function createExternalAccountsClient(config = {}) {
|
|
254
410
|
return {
|
|
255
411
|
retrieve: async (externalAccountId) => {
|
|
256
|
-
if (!config.
|
|
412
|
+
if (!config._data) {
|
|
257
413
|
return stub(
|
|
258
414
|
"externalAccounts.retrieve"
|
|
259
415
|
);
|
|
260
416
|
}
|
|
261
417
|
const [err, raw] = await tryCatch(
|
|
262
|
-
config.
|
|
418
|
+
config._data.query(api.externalAccounts.queries.retrievePersonal, {
|
|
263
419
|
externalAccountId
|
|
264
420
|
})
|
|
265
421
|
);
|
|
@@ -281,11 +437,11 @@ function createExternalAccountsClient(config = {}) {
|
|
|
281
437
|
return [null, brandExternalAccount(raw)];
|
|
282
438
|
},
|
|
283
439
|
remove: async (externalAccountId) => {
|
|
284
|
-
if (!config.
|
|
440
|
+
if (!config._data) {
|
|
285
441
|
return stub("externalAccounts.remove");
|
|
286
442
|
}
|
|
287
443
|
const [err] = await tryCatch(
|
|
288
|
-
config.
|
|
444
|
+
config._data.mutation(api.externalAccounts.mutations.removePersonal, {
|
|
289
445
|
externalAccountId
|
|
290
446
|
})
|
|
291
447
|
);
|
|
@@ -300,17 +456,203 @@ function createExternalAccountsClient(config = {}) {
|
|
|
300
456
|
};
|
|
301
457
|
}
|
|
302
458
|
|
|
459
|
+
// src/core/sub-accounts.ts
|
|
460
|
+
function malformedWireError(reason, raw) {
|
|
461
|
+
return new CapxulError({
|
|
462
|
+
code: "PROVIDER_ERROR",
|
|
463
|
+
message: `convex brandSubAccount failed: ${reason}`,
|
|
464
|
+
details: {
|
|
465
|
+
provider: "convex",
|
|
466
|
+
operation: "brandSubAccount",
|
|
467
|
+
reason,
|
|
468
|
+
// PII discipline (`.claude/rules/posthog.md`): user-authored
|
|
469
|
+
// strings on the wire (`name`, `purpose`) are customer-confidential
|
|
470
|
+
// — sub-account names like "Q3 Acquisition Reserve" or
|
|
471
|
+
// "Vendor ABC payments" must not flow into telemetry. We emit a
|
|
472
|
+
// structural keys-only sample via a strict ALLOWLIST so any future
|
|
473
|
+
// wire-shape addition (e.g. `recipientEmail`, `tags`) is dropped
|
|
474
|
+
// by construction rather than leaked through a denylist gap.
|
|
475
|
+
sample: safeSampleShape(raw)
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
function safeSampleShape(raw) {
|
|
480
|
+
if (raw === null || typeof raw !== "object") {
|
|
481
|
+
return { type: typeof raw };
|
|
482
|
+
}
|
|
483
|
+
const r = raw;
|
|
484
|
+
const balance = r.balance;
|
|
485
|
+
return {
|
|
486
|
+
object: typeof r.object === "string" ? r.object : typeof r.object,
|
|
487
|
+
idPresent: typeof r.id === "string" && r.id.length > 0,
|
|
488
|
+
// First 4 chars only — enough to distinguish "sub_" prefixed IDs
|
|
489
|
+
// from accidental other resource IDs without leaking the full ID.
|
|
490
|
+
idPrefix: typeof r.id === "string" ? r.id.slice(0, 4) : void 0,
|
|
491
|
+
parentKind: r.parent !== null && typeof r.parent === "object" ? r.parent.kind : typeof r.parent,
|
|
492
|
+
status: r.status,
|
|
493
|
+
hasName: typeof r.name === "string",
|
|
494
|
+
hasPurpose: r.purpose !== void 0,
|
|
495
|
+
balanceShape: balance !== null && typeof balance === "object" ? Object.keys(balance).sort() : typeof balance,
|
|
496
|
+
createdAtType: typeof r.createdAt,
|
|
497
|
+
updatedAtType: typeof r.updatedAt
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function isMoneyShape(v) {
|
|
501
|
+
if (typeof v !== "object" || v === null) return false;
|
|
502
|
+
const m = v;
|
|
503
|
+
return typeof m.value === "string" && typeof m.currency === "string";
|
|
504
|
+
}
|
|
505
|
+
function isParentShape(v) {
|
|
506
|
+
if (typeof v !== "object" || v === null) return false;
|
|
507
|
+
const p = v;
|
|
508
|
+
return (p.kind === "account" || p.kind === "organization") && typeof p.id === "string";
|
|
509
|
+
}
|
|
510
|
+
function isFiniteNonNegativeInteger(v) {
|
|
511
|
+
return typeof v === "number" && Number.isFinite(v) && Number.isInteger(v) && v >= 0;
|
|
512
|
+
}
|
|
513
|
+
function validateWireSubAccount(raw) {
|
|
514
|
+
if (typeof raw !== "object" || raw === null) {
|
|
515
|
+
return { ok: false, reason: "not an object" };
|
|
516
|
+
}
|
|
517
|
+
const r = raw;
|
|
518
|
+
if (r.object !== "sub_account") {
|
|
519
|
+
return { ok: false, reason: `object must be "sub_account" (got ${String(r.object)})` };
|
|
520
|
+
}
|
|
521
|
+
if (typeof r.id !== "string" || r.id.length === 0) {
|
|
522
|
+
return { ok: false, reason: "id must be a non-empty string" };
|
|
523
|
+
}
|
|
524
|
+
if (!isParentShape(r.parent)) {
|
|
525
|
+
return { ok: false, reason: "parent must be { kind: 'account' | 'organization', id: string }" };
|
|
526
|
+
}
|
|
527
|
+
if (typeof r.name !== "string") {
|
|
528
|
+
return { ok: false, reason: "name must be a string" };
|
|
529
|
+
}
|
|
530
|
+
if (r.purpose !== void 0 && typeof r.purpose !== "string") {
|
|
531
|
+
return { ok: false, reason: "purpose must be a string when present" };
|
|
532
|
+
}
|
|
533
|
+
if (r.status !== "active" && r.status !== "archived") {
|
|
534
|
+
return { ok: false, reason: `status must be "active" | "archived" (got ${String(r.status)})` };
|
|
535
|
+
}
|
|
536
|
+
if (!isMoneyShape(r.balance)) {
|
|
537
|
+
return { ok: false, reason: "balance must be { value: string, currency: string }" };
|
|
538
|
+
}
|
|
539
|
+
if (!isFiniteNonNegativeInteger(r.createdAt)) {
|
|
540
|
+
return { ok: false, reason: "createdAt must be a finite non-negative integer (epoch ms)" };
|
|
541
|
+
}
|
|
542
|
+
if (r.updatedAt !== void 0 && !isFiniteNonNegativeInteger(r.updatedAt)) {
|
|
543
|
+
return { ok: false, reason: "updatedAt must be a finite non-negative integer when present" };
|
|
544
|
+
}
|
|
545
|
+
return { ok: true, value: r };
|
|
546
|
+
}
|
|
547
|
+
function brandSubAccount(raw) {
|
|
548
|
+
const result = validateWireSubAccount(raw);
|
|
549
|
+
if (!result.ok) {
|
|
550
|
+
throw malformedWireError(result.reason, raw);
|
|
551
|
+
}
|
|
552
|
+
const wire = result.value;
|
|
553
|
+
return {
|
|
554
|
+
object: wire.object,
|
|
555
|
+
id: toSubAccountId(wire.id),
|
|
556
|
+
parent: wire.parent,
|
|
557
|
+
name: wire.name,
|
|
558
|
+
...wire.purpose !== void 0 ? { purpose: wire.purpose } : {},
|
|
559
|
+
status: wire.status,
|
|
560
|
+
balance: wire.balance,
|
|
561
|
+
createdAt: new Date(wire.createdAt).toISOString()
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function tryBrandSubAccount(raw) {
|
|
565
|
+
try {
|
|
566
|
+
return [null, brandSubAccount(raw)];
|
|
567
|
+
} catch (err) {
|
|
568
|
+
if (err instanceof CapxulError && err.code === "PROVIDER_ERROR") {
|
|
569
|
+
return [err, null];
|
|
570
|
+
}
|
|
571
|
+
return [
|
|
572
|
+
malformedWireError(
|
|
573
|
+
err instanceof Error ? err.message : String(err),
|
|
574
|
+
raw
|
|
575
|
+
),
|
|
576
|
+
null
|
|
577
|
+
];
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
function createSubAccountsClient(config = {}) {
|
|
581
|
+
return {
|
|
582
|
+
retrieve: async (subAccountId) => {
|
|
583
|
+
if (!config._data) {
|
|
584
|
+
return stub("subAccounts.retrieve");
|
|
585
|
+
}
|
|
586
|
+
const [err, raw] = await tryCatch(
|
|
587
|
+
config._data.query(api.subAccounts.queries.retrieve, {
|
|
588
|
+
subAccountId
|
|
589
|
+
})
|
|
590
|
+
);
|
|
591
|
+
if (err) {
|
|
592
|
+
return [
|
|
593
|
+
fromConvexError(err),
|
|
594
|
+
null
|
|
595
|
+
];
|
|
596
|
+
}
|
|
597
|
+
if (!raw) {
|
|
598
|
+
return [
|
|
599
|
+
new CapxulError({
|
|
600
|
+
code: "NOT_FOUND",
|
|
601
|
+
message: `sub_account ${subAccountId} not found`
|
|
602
|
+
}),
|
|
603
|
+
null
|
|
604
|
+
];
|
|
605
|
+
}
|
|
606
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
607
|
+
if (brandErr) {
|
|
608
|
+
return [brandErr, null];
|
|
609
|
+
}
|
|
610
|
+
return [null, branded];
|
|
611
|
+
},
|
|
612
|
+
remove: async (subAccountId) => {
|
|
613
|
+
if (!config._data) {
|
|
614
|
+
return stub("subAccounts.remove");
|
|
615
|
+
}
|
|
616
|
+
const [err, raw] = await tryCatch(
|
|
617
|
+
config._data.mutation(api.subAccounts.mutations.archive, {
|
|
618
|
+
subAccountId
|
|
619
|
+
})
|
|
620
|
+
);
|
|
621
|
+
if (err) {
|
|
622
|
+
return [
|
|
623
|
+
fromConvexError(err),
|
|
624
|
+
null
|
|
625
|
+
];
|
|
626
|
+
}
|
|
627
|
+
if (!raw) {
|
|
628
|
+
return [
|
|
629
|
+
new CapxulError({
|
|
630
|
+
code: "NOT_FOUND",
|
|
631
|
+
message: `sub_account ${subAccountId} not found`
|
|
632
|
+
}),
|
|
633
|
+
null
|
|
634
|
+
];
|
|
635
|
+
}
|
|
636
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
637
|
+
if (brandErr) {
|
|
638
|
+
return [brandErr, null];
|
|
639
|
+
}
|
|
640
|
+
return [null, branded];
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
303
645
|
// src/core/accounts.ts
|
|
304
646
|
function createAccountExternalAccountsClient(config) {
|
|
305
647
|
return {
|
|
306
648
|
create: async (input) => {
|
|
307
|
-
if (!config.
|
|
649
|
+
if (!config._data) {
|
|
308
650
|
return stub(
|
|
309
651
|
"accounts.externalAccounts.create"
|
|
310
652
|
);
|
|
311
653
|
}
|
|
312
654
|
const [err, raw] = await tryCatch(
|
|
313
|
-
config.
|
|
655
|
+
config._data.mutation(
|
|
314
656
|
api.externalAccounts.mutations.createPersonal,
|
|
315
657
|
{
|
|
316
658
|
kind: input.kind,
|
|
@@ -348,13 +690,13 @@ function createAccountExternalAccountsClient(config) {
|
|
|
348
690
|
];
|
|
349
691
|
},
|
|
350
692
|
list: async (input) => {
|
|
351
|
-
if (!config.
|
|
693
|
+
if (!config._data) {
|
|
352
694
|
return stub(
|
|
353
695
|
"accounts.externalAccounts.list"
|
|
354
696
|
);
|
|
355
697
|
}
|
|
356
698
|
const [err, result] = await tryCatch(
|
|
357
|
-
config.
|
|
699
|
+
config._data.query(api.externalAccounts.queries.listPersonal, {
|
|
358
700
|
limit: input.limit,
|
|
359
701
|
cursor: input.cursor
|
|
360
702
|
})
|
|
@@ -377,13 +719,13 @@ function createAccountExternalAccountsClient(config) {
|
|
|
377
719
|
];
|
|
378
720
|
},
|
|
379
721
|
retrieve: async (externalAccountId) => {
|
|
380
|
-
if (!config.
|
|
722
|
+
if (!config._data) {
|
|
381
723
|
return stub(
|
|
382
724
|
"accounts.externalAccounts.retrieve"
|
|
383
725
|
);
|
|
384
726
|
}
|
|
385
727
|
const [err, raw] = await tryCatch(
|
|
386
|
-
config.
|
|
728
|
+
config._data.query(api.externalAccounts.queries.retrievePersonal, {
|
|
387
729
|
externalAccountId
|
|
388
730
|
})
|
|
389
731
|
);
|
|
@@ -410,11 +752,11 @@ function createAccountExternalAccountsClient(config) {
|
|
|
410
752
|
];
|
|
411
753
|
},
|
|
412
754
|
remove: async (externalAccountId) => {
|
|
413
|
-
if (!config.
|
|
755
|
+
if (!config._data) {
|
|
414
756
|
return stub("accounts.externalAccounts.remove");
|
|
415
757
|
}
|
|
416
758
|
const [err] = await tryCatch(
|
|
417
|
-
config.
|
|
759
|
+
config._data.mutation(api.externalAccounts.mutations.removePersonal, {
|
|
418
760
|
externalAccountId
|
|
419
761
|
})
|
|
420
762
|
);
|
|
@@ -428,43 +770,191 @@ function createAccountExternalAccountsClient(config) {
|
|
|
428
770
|
}
|
|
429
771
|
};
|
|
430
772
|
}
|
|
431
|
-
function
|
|
773
|
+
function createAccountSubAccountsClient(config) {
|
|
432
774
|
return {
|
|
433
|
-
|
|
434
|
-
if (!config.
|
|
435
|
-
return stub(
|
|
436
|
-
|
|
437
|
-
try {
|
|
438
|
-
const account = await config.data.query(
|
|
439
|
-
api.openfort.queries.getMyAccount,
|
|
440
|
-
{}
|
|
775
|
+
create: async (input) => {
|
|
776
|
+
if (!config._data) {
|
|
777
|
+
return stub(
|
|
778
|
+
"accounts.subAccounts.create"
|
|
441
779
|
);
|
|
442
|
-
if (account.id !== accountId) {
|
|
443
|
-
return [
|
|
444
|
-
new CapxulError({
|
|
445
|
-
code: "PERMISSION_DENIED",
|
|
446
|
-
message: "accounts.retrieve currently supports the authenticated caller's own account only.",
|
|
447
|
-
details: {
|
|
448
|
-
requestedAccountId: accountId,
|
|
449
|
-
authenticatedAccountId: account.id
|
|
450
|
-
}
|
|
451
|
-
}),
|
|
452
|
-
null
|
|
453
|
-
];
|
|
454
|
-
}
|
|
455
|
-
return [null, account];
|
|
456
|
-
} catch (cause) {
|
|
457
|
-
return [fromConvexError(cause), null];
|
|
458
780
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
781
|
+
const [err, raw] = await tryCatch(
|
|
782
|
+
config._data.mutation(api.subAccounts.mutations.create, {
|
|
783
|
+
parent: { kind: "account", id: input.accountId },
|
|
784
|
+
name: input.name,
|
|
785
|
+
purpose: input.purpose
|
|
786
|
+
})
|
|
787
|
+
);
|
|
788
|
+
if (err) {
|
|
789
|
+
return [
|
|
790
|
+
fromConvexError(err),
|
|
791
|
+
null
|
|
792
|
+
];
|
|
793
|
+
}
|
|
794
|
+
if (!raw) {
|
|
795
|
+
return [
|
|
796
|
+
new CapxulError({
|
|
797
|
+
code: "NOT_FOUND",
|
|
798
|
+
message: "sub_account creation returned no resource"
|
|
799
|
+
}),
|
|
800
|
+
null
|
|
801
|
+
];
|
|
802
|
+
}
|
|
803
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
804
|
+
if (brandErr) {
|
|
805
|
+
return [
|
|
806
|
+
brandErr,
|
|
807
|
+
null
|
|
808
|
+
];
|
|
809
|
+
}
|
|
810
|
+
return [null, branded];
|
|
811
|
+
},
|
|
812
|
+
list: async (input) => {
|
|
813
|
+
if (!config._data) {
|
|
814
|
+
return stub(
|
|
815
|
+
"accounts.subAccounts.list"
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
const [err, rows] = await tryCatch(
|
|
819
|
+
config._data.query(api.subAccounts.queries.listByAccount, {
|
|
820
|
+
accountId: input.accountId
|
|
821
|
+
})
|
|
822
|
+
);
|
|
823
|
+
if (err) {
|
|
824
|
+
return [
|
|
825
|
+
fromConvexError(err),
|
|
826
|
+
null
|
|
827
|
+
];
|
|
828
|
+
}
|
|
829
|
+
const branded = [];
|
|
830
|
+
for (const row of rows) {
|
|
831
|
+
const [brandErr, value] = tryBrandSubAccount(row);
|
|
832
|
+
if (brandErr) {
|
|
833
|
+
return [
|
|
834
|
+
brandErr,
|
|
835
|
+
null
|
|
836
|
+
];
|
|
837
|
+
}
|
|
838
|
+
branded.push(value);
|
|
839
|
+
}
|
|
840
|
+
return [
|
|
841
|
+
null,
|
|
842
|
+
{
|
|
843
|
+
object: "list",
|
|
844
|
+
data: branded,
|
|
845
|
+
page: { hasMore: false }
|
|
846
|
+
}
|
|
847
|
+
];
|
|
848
|
+
},
|
|
849
|
+
retrieve: async (subAccountId) => {
|
|
850
|
+
if (!config._data) {
|
|
851
|
+
return stub(
|
|
852
|
+
"accounts.subAccounts.retrieve"
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
const [err, raw] = await tryCatch(
|
|
856
|
+
config._data.query(api.subAccounts.queries.retrieve, {
|
|
857
|
+
subAccountId
|
|
858
|
+
})
|
|
859
|
+
);
|
|
860
|
+
if (err) {
|
|
861
|
+
return [
|
|
862
|
+
fromConvexError(err),
|
|
863
|
+
null
|
|
864
|
+
];
|
|
865
|
+
}
|
|
866
|
+
if (!raw) {
|
|
867
|
+
return [
|
|
868
|
+
new CapxulError({
|
|
869
|
+
code: "NOT_FOUND",
|
|
870
|
+
message: `sub_account ${subAccountId} not found`
|
|
871
|
+
}),
|
|
872
|
+
null
|
|
873
|
+
];
|
|
874
|
+
}
|
|
875
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
876
|
+
if (brandErr) {
|
|
877
|
+
return [
|
|
878
|
+
brandErr,
|
|
879
|
+
null
|
|
880
|
+
];
|
|
881
|
+
}
|
|
882
|
+
return [null, branded];
|
|
883
|
+
},
|
|
884
|
+
remove: async (subAccountId) => {
|
|
885
|
+
if (!config._data) {
|
|
886
|
+
return stub(
|
|
887
|
+
"accounts.subAccounts.remove"
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
const [err, raw] = await tryCatch(
|
|
891
|
+
config._data.mutation(api.subAccounts.mutations.archive, {
|
|
892
|
+
subAccountId
|
|
893
|
+
})
|
|
894
|
+
);
|
|
895
|
+
if (err) {
|
|
896
|
+
return [
|
|
897
|
+
fromConvexError(err),
|
|
898
|
+
null
|
|
899
|
+
];
|
|
900
|
+
}
|
|
901
|
+
if (!raw) {
|
|
902
|
+
return [
|
|
903
|
+
new CapxulError({
|
|
904
|
+
code: "NOT_FOUND",
|
|
905
|
+
message: `sub_account ${subAccountId} not found`
|
|
906
|
+
}),
|
|
907
|
+
null
|
|
908
|
+
];
|
|
909
|
+
}
|
|
910
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
911
|
+
if (brandErr) {
|
|
912
|
+
return [
|
|
913
|
+
brandErr,
|
|
914
|
+
null
|
|
915
|
+
];
|
|
916
|
+
}
|
|
917
|
+
return [null, branded];
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
function createAccountsClient(config = {}) {
|
|
922
|
+
return {
|
|
923
|
+
retrieve: async (accountId) => {
|
|
924
|
+
if (!config._data) {
|
|
925
|
+
return stub("accounts.retrieve");
|
|
926
|
+
}
|
|
927
|
+
try {
|
|
928
|
+
const account = await config._data.query(
|
|
929
|
+
api.openfort.queries.getMyAccount,
|
|
930
|
+
{}
|
|
931
|
+
);
|
|
932
|
+
if (account.id !== accountId) {
|
|
933
|
+
return [
|
|
934
|
+
new CapxulError({
|
|
935
|
+
code: "PERMISSION_DENIED",
|
|
936
|
+
message: "accounts.retrieve currently supports the authenticated caller's own account only.",
|
|
937
|
+
details: {
|
|
938
|
+
requestedAccountId: accountId,
|
|
939
|
+
authenticatedAccountId: account.id
|
|
940
|
+
}
|
|
941
|
+
}),
|
|
942
|
+
null
|
|
943
|
+
];
|
|
944
|
+
}
|
|
945
|
+
return [null, account];
|
|
946
|
+
} catch (cause) {
|
|
947
|
+
return [fromConvexError(cause), null];
|
|
948
|
+
}
|
|
949
|
+
},
|
|
950
|
+
lookup: async () => stub("accounts.lookup"),
|
|
951
|
+
update: async (input) => {
|
|
952
|
+
if (!config._data) {
|
|
953
|
+
return stub("accounts.update");
|
|
954
|
+
}
|
|
955
|
+
if (input.countryCode !== void 0) {
|
|
956
|
+
return [
|
|
957
|
+
new CapxulError({
|
|
468
958
|
code: "INVALID_INPUT",
|
|
469
959
|
message: "accounts.update does not support countryCode yet \u2014 backend mutation only patches displayName and username.",
|
|
470
960
|
details: { field: "countryCode" }
|
|
@@ -473,7 +963,7 @@ function createAccountsClient(config = {}) {
|
|
|
473
963
|
];
|
|
474
964
|
}
|
|
475
965
|
try {
|
|
476
|
-
const current = await config.
|
|
966
|
+
const current = await config._data.query(
|
|
477
967
|
api.openfort.queries.getMyAccount,
|
|
478
968
|
{}
|
|
479
969
|
);
|
|
@@ -490,11 +980,11 @@ function createAccountsClient(config = {}) {
|
|
|
490
980
|
null
|
|
491
981
|
];
|
|
492
982
|
}
|
|
493
|
-
await config.
|
|
983
|
+
await config._data.mutation(api.openfort.mutations.updateProfile, {
|
|
494
984
|
displayName: input.name,
|
|
495
985
|
username: input.username
|
|
496
986
|
});
|
|
497
|
-
const updated = await config.
|
|
987
|
+
const updated = await config._data.query(
|
|
498
988
|
api.openfort.queries.getMyAccount,
|
|
499
989
|
{}
|
|
500
990
|
);
|
|
@@ -504,7 +994,7 @@ function createAccountsClient(config = {}) {
|
|
|
504
994
|
}
|
|
505
995
|
},
|
|
506
996
|
provisionPersonal: async (input) => {
|
|
507
|
-
if (!config.
|
|
997
|
+
if (!config._data) {
|
|
508
998
|
return stub(
|
|
509
999
|
"accounts.provisionPersonal"
|
|
510
1000
|
);
|
|
@@ -519,17 +1009,17 @@ function createAccountsClient(config = {}) {
|
|
|
519
1009
|
];
|
|
520
1010
|
}
|
|
521
1011
|
try {
|
|
522
|
-
await config.
|
|
1012
|
+
await config._data.mutation(
|
|
523
1013
|
api.safe.mutations.provisionLocalPersonalAccount,
|
|
524
1014
|
{
|
|
525
1015
|
displayName: input.displayName,
|
|
526
1016
|
username: input.username,
|
|
527
1017
|
countryCode: input.countryCode,
|
|
528
1018
|
eoaAddress: input.signerProvider.signerAddress,
|
|
529
|
-
safeAddress: input.signerProvider.
|
|
1019
|
+
safeAddress: deriveSafeAddress(input.signerProvider.signerAddress)
|
|
530
1020
|
}
|
|
531
1021
|
);
|
|
532
|
-
const account = await config.
|
|
1022
|
+
const account = await config._data.query(
|
|
533
1023
|
api.openfort.queries.getMyAccount,
|
|
534
1024
|
{}
|
|
535
1025
|
);
|
|
@@ -552,11 +1042,11 @@ function createAccountsClient(config = {}) {
|
|
|
552
1042
|
},
|
|
553
1043
|
safes: {
|
|
554
1044
|
retrieve: async (safeId) => {
|
|
555
|
-
if (!config.
|
|
1045
|
+
if (!config._data) {
|
|
556
1046
|
return stub("accounts.safes.retrieve");
|
|
557
1047
|
}
|
|
558
1048
|
try {
|
|
559
|
-
const safe = await config.
|
|
1049
|
+
const safe = await config._data.query(
|
|
560
1050
|
api.safe.queries.retrieveAccountSafe,
|
|
561
1051
|
{ safeId }
|
|
562
1052
|
);
|
|
@@ -583,19 +1073,50 @@ function createAccountsClient(config = {}) {
|
|
|
583
1073
|
retrieve: async () => stub("accounts.kycProfiles.retrieve")
|
|
584
1074
|
},
|
|
585
1075
|
externalAccounts: createAccountExternalAccountsClient(config),
|
|
586
|
-
subAccounts:
|
|
587
|
-
create: async () => stub("accounts.subAccounts.create"),
|
|
588
|
-
list: async () => stub("accounts.subAccounts.list"),
|
|
589
|
-
retrieve: async () => stub("accounts.subAccounts.retrieve"),
|
|
590
|
-
remove: async () => stub("accounts.subAccounts.remove")
|
|
591
|
-
},
|
|
1076
|
+
subAccounts: createAccountSubAccountsClient(config),
|
|
592
1077
|
balanceLedger: {
|
|
593
|
-
list: async () =>
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
1078
|
+
list: async (input) => {
|
|
1079
|
+
if (!config._data) {
|
|
1080
|
+
return stub(
|
|
1081
|
+
"accounts.balanceLedger.list"
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
try {
|
|
1085
|
+
const accountId = input.accountId.replace(/^acct_/, "");
|
|
1086
|
+
const page = await config._data.query(
|
|
1087
|
+
api.balanceLedger.queries.listForAccount,
|
|
1088
|
+
{ accountId, limit: input.limit, cursor: input.cursor }
|
|
1089
|
+
);
|
|
1090
|
+
return [null, page];
|
|
1091
|
+
} catch (cause) {
|
|
1092
|
+
return [fromConvexError(cause), null];
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
retrieve: async (entryId) => {
|
|
1096
|
+
if (!config._data) {
|
|
1097
|
+
return stub(
|
|
1098
|
+
"accounts.balanceLedger.retrieve"
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
try {
|
|
1102
|
+
const entry = await config._data.query(
|
|
1103
|
+
api.balanceLedger.queries.retrieve,
|
|
1104
|
+
{ entryId }
|
|
1105
|
+
);
|
|
1106
|
+
if (!entry) {
|
|
1107
|
+
return [
|
|
1108
|
+
new CapxulError({
|
|
1109
|
+
code: "NOT_FOUND",
|
|
1110
|
+
message: `balance_ledger_entry ${entryId} not found`
|
|
1111
|
+
}),
|
|
1112
|
+
null
|
|
1113
|
+
];
|
|
1114
|
+
}
|
|
1115
|
+
return [null, entry];
|
|
1116
|
+
} catch (cause) {
|
|
1117
|
+
return [fromConvexError(cause), null];
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
599
1120
|
}
|
|
600
1121
|
};
|
|
601
1122
|
}
|
|
@@ -609,130 +1130,21 @@ function createApiKeysClient() {
|
|
|
609
1130
|
revoke: async () => stub("apiKeys.revoke")
|
|
610
1131
|
};
|
|
611
1132
|
}
|
|
1133
|
+
function createDefaultDataClient(convexUrl, jwt) {
|
|
1134
|
+
const client = new ConvexHttpClient(convexUrl);
|
|
1135
|
+
client.setAuth(jwt);
|
|
1136
|
+
return client;
|
|
1137
|
+
}
|
|
612
1138
|
|
|
613
|
-
//
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
// ../config/src/errors.ts
|
|
623
|
-
var CapxulError2 = class extends Error {
|
|
624
|
-
code;
|
|
625
|
-
details;
|
|
626
|
-
correlationId;
|
|
627
|
-
layer;
|
|
628
|
-
constructor(code, message, options) {
|
|
629
|
-
super(message, options?.cause ? { cause: options.cause } : void 0);
|
|
630
|
-
this.code = code;
|
|
631
|
-
this.details = options?.details;
|
|
632
|
-
this.correlationId = options?.correlationId;
|
|
633
|
-
this.layer = options?.layer;
|
|
634
|
-
}
|
|
635
|
-
};
|
|
636
|
-
var Errors = {
|
|
637
|
-
notAuthenticated: () => new CapxulError2("NOT_AUTHENTICATED", "Not authenticated"),
|
|
638
|
-
profileNotFound: (authUserId) => new CapxulError2("PROFILE_NOT_FOUND", `Profile not found for user ${authUserId}`),
|
|
639
|
-
smartAccountMissing: (authUserId) => new CapxulError2("SMART_ACCOUNT_MISSING", `Smart account not provisioned for user ${authUserId}`),
|
|
640
|
-
envMissing: (name) => new CapxulError2("ENV_MISSING", `Environment variable ${name} not configured`),
|
|
641
|
-
openfortApi: (operation, cause) => new CapxulError2(
|
|
642
|
-
"PROVIDER_ERROR",
|
|
643
|
-
`Openfort ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
644
|
-
{ cause, details: { provider: "openfort", operation } }
|
|
645
|
-
),
|
|
646
|
-
shieldApi: (status, detail) => new CapxulError2(
|
|
647
|
-
"PROVIDER_ERROR",
|
|
648
|
-
`Shield API error (${status}): ${detail}`,
|
|
649
|
-
{ details: { provider: "shield", status } }
|
|
650
|
-
),
|
|
651
|
-
providerError: (provider, operation, cause) => new CapxulError2(
|
|
652
|
-
"PROVIDER_ERROR",
|
|
653
|
-
`${provider} ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
654
|
-
{ cause, details: { provider, operation } }
|
|
655
|
-
),
|
|
656
|
-
invalidInput: (field, reason) => new CapxulError2(
|
|
657
|
-
"INVALID_INPUT",
|
|
658
|
-
`Invalid ${field}: ${reason}`,
|
|
659
|
-
{ details: { field, reason } }
|
|
660
|
-
),
|
|
661
|
-
playerNotFound: (playerId) => new CapxulError2(
|
|
662
|
-
"PLAYER_NOT_FOUND",
|
|
663
|
-
playerId ? `Openfort player ${playerId} not found` : "Openfort player not found"
|
|
664
|
-
),
|
|
665
|
-
accountNotFound: (accountId) => new CapxulError2(
|
|
666
|
-
"ACCOUNT_NOT_FOUND",
|
|
667
|
-
accountId ? `Openfort account ${accountId} not found` : "Openfort smart account not found"
|
|
668
|
-
),
|
|
669
|
-
invalidRecipient: (reason) => new CapxulError2("INVALID_RECIPIENT", reason),
|
|
670
|
-
permissionDenied: (reason = "Permission denied") => new CapxulError2("PERMISSION_DENIED", reason),
|
|
671
|
-
notFound: (resource, id) => new CapxulError2(
|
|
672
|
-
"NOT_FOUND",
|
|
673
|
-
id ? `${resource} ${id} not found` : `${resource} not found`
|
|
674
|
-
),
|
|
675
|
-
idempotencyConflict: (details) => new CapxulError2(
|
|
676
|
-
"IDEMPOTENCY_CONFLICT",
|
|
677
|
-
"Idempotency key was already used for a different request",
|
|
678
|
-
{ details }
|
|
679
|
-
),
|
|
680
|
-
emailDeliveryFailed: (detail, details) => new CapxulError2("EMAIL_DELIVERY_FAILED", `Failed to send email: ${detail}`, {
|
|
681
|
-
details
|
|
682
|
-
}),
|
|
683
|
-
rateLimited: (details) => new CapxulError2("RATE_LIMITED", "Request was rate limited", {
|
|
684
|
-
details: { ...details }
|
|
685
|
-
}),
|
|
686
|
-
internalError: (reason) => new CapxulError2("INTERNAL_ERROR", `Internal error: ${reason}`),
|
|
687
|
-
/**
|
|
688
|
-
* Verification gate. Surfaced when a request hits a verification
|
|
689
|
-
* boundary the actor cannot cross under their current state. Two
|
|
690
|
-
* variants share this code:
|
|
691
|
-
*
|
|
692
|
-
* - Rail gate (Withdrawals v1 W2, #465): the resolved
|
|
693
|
-
* `external_account.kind` routes to a withdrawal rail (e.g.
|
|
694
|
-
* `fiat_offramp`, `card_payout`) that is not yet supported. Carries
|
|
695
|
-
* `details.rail` + `details.currentKind`.
|
|
696
|
-
* - KYC tier gate (legacy / future): the actor's KYC tier is below
|
|
697
|
-
* the required tier. Carries `details.requiredTier`.
|
|
698
|
-
*
|
|
699
|
-
* Code is shared because both expose the same UX shape ("you cannot
|
|
700
|
-
* proceed until verification advances"); the `details.*` keys
|
|
701
|
-
* differentiate the route.
|
|
702
|
-
*/
|
|
703
|
-
verificationRequired: (details) => {
|
|
704
|
-
const message = "rail" in details ? `Withdrawal rail "${details.rail}" (kind=${details.currentKind}) is not yet supported.` : `Verification tier ${details.requiredTier} is required.`;
|
|
705
|
-
return new CapxulError2("VERIFICATION_REQUIRED", message, {
|
|
706
|
-
details: { ...details }
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
};
|
|
710
|
-
|
|
711
|
-
// ../config/src/safe.ts
|
|
712
|
-
var SAFE_PROXY_FACTORY = "0x4e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67";
|
|
713
|
-
var SAFE_L2_SINGLETON = "0x29fcb43b46531bca003ddc8fcb67ffe91900c762";
|
|
714
|
-
var SAFE_MODULE_SETUP = "0x2dd68b007b46fbe91b9a7c3eda5a7a1063cb5b47";
|
|
715
|
-
var SAFE_4337_MODULE = "0x75cf11467937ce3f2f357ce24ffc3dbf8fd5c226";
|
|
716
|
-
|
|
717
|
-
// ../config/src/org-roles.ts
|
|
718
|
-
function roleKeyFromLabel(label) {
|
|
719
|
-
const bytes = new TextEncoder().encode(label);
|
|
720
|
-
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
721
|
-
return "0x" + hex.padEnd(64, "0");
|
|
722
|
-
}
|
|
723
|
-
roleKeyFromLabel("OWNER");
|
|
724
|
-
roleKeyFromLabel("FINANCE_MANAGER");
|
|
725
|
-
roleKeyFromLabel("TEAM_LEAD");
|
|
726
|
-
|
|
727
|
-
// src/transport.ts
|
|
728
|
-
function makeHttpTransport(config) {
|
|
729
|
-
switch (config.mode) {
|
|
730
|
-
case "build-time-urls":
|
|
731
|
-
return makeBuildTimeUrlsTransport(config);
|
|
732
|
-
case "publishable-key":
|
|
733
|
-
return makePublishableKeyTransport(config);
|
|
734
|
-
default:
|
|
735
|
-
return assertNever(config);
|
|
1139
|
+
// src/transport.ts
|
|
1140
|
+
function makeHttpTransport(config) {
|
|
1141
|
+
switch (config.mode) {
|
|
1142
|
+
case "build-time-urls":
|
|
1143
|
+
return makeBuildTimeUrlsTransport(config);
|
|
1144
|
+
case "publishable-key":
|
|
1145
|
+
return makePublishableKeyTransport(config);
|
|
1146
|
+
default:
|
|
1147
|
+
return assertNever(config);
|
|
736
1148
|
}
|
|
737
1149
|
}
|
|
738
1150
|
function createLifecycle(initial) {
|
|
@@ -1053,7 +1465,7 @@ function readNonEmptyString(value) {
|
|
|
1053
1465
|
|
|
1054
1466
|
// src/core/auth.ts
|
|
1055
1467
|
function createAuthClient(config = {}) {
|
|
1056
|
-
let dataClient = config.
|
|
1468
|
+
let dataClient = config._data ?? null;
|
|
1057
1469
|
const sessionStore = config.auth?.sessionStore ?? createMemorySessionStore();
|
|
1058
1470
|
const getTransport = createTransportProvider(config);
|
|
1059
1471
|
return {
|
|
@@ -1109,11 +1521,20 @@ function createAuthClient(config = {}) {
|
|
|
1109
1521
|
).toISOString()
|
|
1110
1522
|
};
|
|
1111
1523
|
sessionStore.set(session);
|
|
1112
|
-
if (
|
|
1524
|
+
if (!dataClient) {
|
|
1113
1525
|
try {
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1526
|
+
const convexUrl = transport.convexUrl;
|
|
1527
|
+
if (!convexUrl || !session.convexJwt) {
|
|
1528
|
+
return [
|
|
1529
|
+
new CapxulError({
|
|
1530
|
+
code: "NETWORK_ERROR",
|
|
1531
|
+
message: "Cannot create data client: missing convex URL or JWT."
|
|
1532
|
+
}),
|
|
1533
|
+
null
|
|
1534
|
+
];
|
|
1535
|
+
}
|
|
1536
|
+
dataClient = createDefaultDataClient(convexUrl, session.convexJwt);
|
|
1537
|
+
mutableConfig(config)._data = dataClient;
|
|
1117
1538
|
} catch (cause) {
|
|
1118
1539
|
return [
|
|
1119
1540
|
new CapxulError({
|
|
@@ -1124,14 +1545,89 @@ function createAuthClient(config = {}) {
|
|
|
1124
1545
|
null
|
|
1125
1546
|
];
|
|
1126
1547
|
}
|
|
1548
|
+
} else {
|
|
1549
|
+
const injected = dataClient;
|
|
1550
|
+
if (typeof injected.refreshAuth === "function") {
|
|
1551
|
+
injected.refreshAuth();
|
|
1552
|
+
} else if (typeof injected.setAuth === "function" && session.convexJwt) {
|
|
1553
|
+
injected.setAuth(session.convexJwt);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
transport.markAuthenticated({ dataClient });
|
|
1557
|
+
if (!dataClient) {
|
|
1558
|
+
return [
|
|
1559
|
+
new CapxulError({
|
|
1560
|
+
code: "NOT_AUTHENTICATED",
|
|
1561
|
+
message: "Auth bootstrap requires an authenticated Convex data client."
|
|
1562
|
+
}),
|
|
1563
|
+
null
|
|
1564
|
+
];
|
|
1565
|
+
}
|
|
1566
|
+
try {
|
|
1567
|
+
const resolution = await dataClient.mutation(
|
|
1568
|
+
api.authBootstrap.resolveAfterOtp,
|
|
1569
|
+
{
|
|
1570
|
+
email: session.email,
|
|
1571
|
+
sessionToken: session.token
|
|
1572
|
+
}
|
|
1573
|
+
);
|
|
1574
|
+
if (resolution.kind === "existing_member") {
|
|
1575
|
+
return [null, { ...resolution, session }];
|
|
1576
|
+
}
|
|
1577
|
+
return [null, { ...resolution, session }];
|
|
1578
|
+
} catch (cause) {
|
|
1579
|
+
return [fromConvexError(cause), null];
|
|
1580
|
+
}
|
|
1581
|
+
},
|
|
1582
|
+
completeBootstrap: async (input) => {
|
|
1583
|
+
const session = sessionStore.get();
|
|
1584
|
+
const data = dataClient ?? config._data;
|
|
1585
|
+
if (!session || !data) {
|
|
1586
|
+
return [
|
|
1587
|
+
new CapxulError({
|
|
1588
|
+
code: "INVALID_INPUT",
|
|
1589
|
+
message: "completeBootstrap requires the OTP-verified session that issued the bootstrap token."
|
|
1590
|
+
}),
|
|
1591
|
+
null
|
|
1592
|
+
];
|
|
1593
|
+
}
|
|
1594
|
+
const signerAddress = config.signer?.address;
|
|
1595
|
+
if (!signerAddress) {
|
|
1596
|
+
return [
|
|
1597
|
+
new CapxulError({
|
|
1598
|
+
code: "INVALID_INPUT",
|
|
1599
|
+
message: "completeBootstrap requires a signer to be configured on the client."
|
|
1600
|
+
}),
|
|
1601
|
+
null
|
|
1602
|
+
];
|
|
1603
|
+
}
|
|
1604
|
+
try {
|
|
1605
|
+
const safeAddress = deriveSafeAddress(signerAddress);
|
|
1606
|
+
const result = await data.mutation(api.authBootstrap.completeBootstrap, {
|
|
1607
|
+
bootstrapToken: input.bootstrapToken,
|
|
1608
|
+
sessionToken: session.token,
|
|
1609
|
+
username: input.username,
|
|
1610
|
+
displayName: input.displayName,
|
|
1611
|
+
countryCode: input.countryCode,
|
|
1612
|
+
signerProvider: {
|
|
1613
|
+
kind: "local-private-key",
|
|
1614
|
+
signerAddress,
|
|
1615
|
+
safeAddress
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
return [null, { kind: "authenticated", session, ...result }];
|
|
1619
|
+
} catch (cause) {
|
|
1620
|
+
return [
|
|
1621
|
+
fromConvexError(cause),
|
|
1622
|
+
null
|
|
1623
|
+
];
|
|
1127
1624
|
}
|
|
1128
|
-
return [null, session];
|
|
1129
1625
|
},
|
|
1130
1626
|
getSession: async () => [null, sessionStore.get()],
|
|
1131
1627
|
signOut: async () => {
|
|
1132
1628
|
sessionStore.clear();
|
|
1133
1629
|
dataClient = null;
|
|
1134
|
-
mutableConfig(config).
|
|
1630
|
+
mutableConfig(config)._data = void 0;
|
|
1135
1631
|
const transport = getTransport();
|
|
1136
1632
|
transport?.clearAuth();
|
|
1137
1633
|
return [null, void 0];
|
|
@@ -1202,6 +1698,9 @@ async function postBetterAuth(transport, path, body, code, signal) {
|
|
|
1202
1698
|
}
|
|
1203
1699
|
return [null, text ? JSON.parse(text) : void 0];
|
|
1204
1700
|
} catch (cause) {
|
|
1701
|
+
if (cause instanceof CapxulError) {
|
|
1702
|
+
return [cause, null];
|
|
1703
|
+
}
|
|
1205
1704
|
return [
|
|
1206
1705
|
new CapxulError({
|
|
1207
1706
|
code: "NETWORK_ERROR",
|
|
@@ -1240,7 +1739,7 @@ function parseBetterAuthError(text) {
|
|
|
1240
1739
|
}
|
|
1241
1740
|
}
|
|
1242
1741
|
function isCapxulErrorCode2(code) {
|
|
1243
|
-
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";
|
|
1742
|
+
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" || code === "INTERNAL_ERROR" || code === "ENV_MISSING" || code === "UNKNOWN" || code === "PROVIDER_ERROR";
|
|
1244
1743
|
}
|
|
1245
1744
|
async function exchangeConvexToken(transport, config, token, signal) {
|
|
1246
1745
|
const path = config.auth?.convexTokenUrl ?? "/convex/token";
|
|
@@ -1270,6 +1769,9 @@ async function exchangeConvexToken(transport, config, token, signal) {
|
|
|
1270
1769
|
}
|
|
1271
1770
|
return [null, body.token];
|
|
1272
1771
|
} catch (cause) {
|
|
1772
|
+
if (cause instanceof CapxulError) {
|
|
1773
|
+
return [cause, null];
|
|
1774
|
+
}
|
|
1273
1775
|
return [
|
|
1274
1776
|
new CapxulError({
|
|
1275
1777
|
code: "NETWORK_ERROR",
|
|
@@ -1306,11 +1808,11 @@ function createOrgDocumentsClient() {
|
|
|
1306
1808
|
function createMeClient(config = {}) {
|
|
1307
1809
|
return {
|
|
1308
1810
|
get: async () => {
|
|
1309
|
-
if (!config.
|
|
1811
|
+
if (!config._data) {
|
|
1310
1812
|
return stub("me.get");
|
|
1311
1813
|
}
|
|
1312
1814
|
try {
|
|
1313
|
-
const account = await config.
|
|
1815
|
+
const account = await config._data.query(
|
|
1314
1816
|
api.openfort.queries.getMyAccount,
|
|
1315
1817
|
{}
|
|
1316
1818
|
);
|
|
@@ -1320,7 +1822,7 @@ function createMeClient(config = {}) {
|
|
|
1320
1822
|
}
|
|
1321
1823
|
},
|
|
1322
1824
|
update: async (input) => {
|
|
1323
|
-
if (!config.
|
|
1825
|
+
if (!config._data) {
|
|
1324
1826
|
return stub("me.update");
|
|
1325
1827
|
}
|
|
1326
1828
|
if (input.countryCode !== void 0) {
|
|
@@ -1334,11 +1836,11 @@ function createMeClient(config = {}) {
|
|
|
1334
1836
|
];
|
|
1335
1837
|
}
|
|
1336
1838
|
try {
|
|
1337
|
-
await config.
|
|
1839
|
+
await config._data.mutation(api.openfort.mutations.updateProfile, {
|
|
1338
1840
|
displayName: input.name,
|
|
1339
1841
|
username: input.username
|
|
1340
1842
|
});
|
|
1341
|
-
const account = await config.
|
|
1843
|
+
const account = await config._data.query(
|
|
1342
1844
|
api.openfort.queries.getMyAccount,
|
|
1343
1845
|
{}
|
|
1344
1846
|
);
|
|
@@ -1353,11 +1855,11 @@ function createMeClient(config = {}) {
|
|
|
1353
1855
|
// src/core/operations.ts
|
|
1354
1856
|
function createOperationsClient(config = {}) {
|
|
1355
1857
|
const retrieve = async (operationId) => {
|
|
1356
|
-
if (!config.
|
|
1858
|
+
if (!config._data) {
|
|
1357
1859
|
return stub("operations.retrieve");
|
|
1358
1860
|
}
|
|
1359
1861
|
try {
|
|
1360
|
-
const operation = await config.
|
|
1862
|
+
const operation = await config._data.query(api.operations.queries.retrieve, {
|
|
1361
1863
|
operationId
|
|
1362
1864
|
});
|
|
1363
1865
|
if (!operation) {
|
|
@@ -1374,7 +1876,7 @@ function createOperationsClient(config = {}) {
|
|
|
1374
1876
|
return {
|
|
1375
1877
|
retrieve,
|
|
1376
1878
|
wait: async (operationId, input = {}) => {
|
|
1377
|
-
if (!config.
|
|
1879
|
+
if (!config._data) {
|
|
1378
1880
|
return stub("operations.wait");
|
|
1379
1881
|
}
|
|
1380
1882
|
const until = new Set(
|
|
@@ -1409,49 +1911,22 @@ function toTokenUnits(value, decimals = 6) {
|
|
|
1409
1911
|
return parseUnits(value, decimals);
|
|
1410
1912
|
}
|
|
1411
1913
|
|
|
1412
|
-
// src/
|
|
1413
|
-
function
|
|
1914
|
+
// src/core/token-registry.ts
|
|
1915
|
+
function resolvePaymentToken(currency) {
|
|
1414
1916
|
const normalized = currency.trim().toUpperCase();
|
|
1415
1917
|
if (normalized === "USD" || normalized === "USDC") {
|
|
1416
|
-
return
|
|
1918
|
+
return {
|
|
1919
|
+
address: TEST_USDC_ADDRESS.toLowerCase(),
|
|
1920
|
+
decimals: 6,
|
|
1921
|
+
symbol: "USDC"
|
|
1922
|
+
};
|
|
1417
1923
|
}
|
|
1418
1924
|
throw new CapxulError({
|
|
1419
|
-
code: "
|
|
1420
|
-
message: `Currency ${currency} is not
|
|
1925
|
+
code: "NOT_IMPLEMENTED",
|
|
1926
|
+
message: `Currency ${currency} is not yet supported by the token registry.`,
|
|
1421
1927
|
details: { currency: normalized }
|
|
1422
1928
|
});
|
|
1423
1929
|
}
|
|
1424
|
-
async function buildSafeAccount(signer, chain) {
|
|
1425
|
-
try {
|
|
1426
|
-
const publicClient = createPublicClient({
|
|
1427
|
-
chain: baseSepolia,
|
|
1428
|
-
transport: http(chain.rpcUrl)
|
|
1429
|
-
});
|
|
1430
|
-
return await toSafeSmartAccount({
|
|
1431
|
-
client: publicClient,
|
|
1432
|
-
entryPoint: { address: entryPoint07Address, version: "0.7" },
|
|
1433
|
-
version: "1.4.1",
|
|
1434
|
-
owners: [signer],
|
|
1435
|
-
saltNonce: computeSaltNonce(signer.address),
|
|
1436
|
-
safeSingletonAddress: SAFE_L2_SINGLETON,
|
|
1437
|
-
safeProxyFactoryAddress: SAFE_PROXY_FACTORY,
|
|
1438
|
-
safeModuleSetupAddress: SAFE_MODULE_SETUP,
|
|
1439
|
-
safe4337ModuleAddress: SAFE_4337_MODULE,
|
|
1440
|
-
safeModules: [],
|
|
1441
|
-
setupTransactions: []
|
|
1442
|
-
});
|
|
1443
|
-
} catch (cause) {
|
|
1444
|
-
throw new CapxulError({
|
|
1445
|
-
code: "NETWORK_ERROR",
|
|
1446
|
-
message: cause instanceof Error ? cause.message : String(cause),
|
|
1447
|
-
cause,
|
|
1448
|
-
details: { chainId: chain.chainId }
|
|
1449
|
-
});
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
function computeSaltNonce(ownerAddress) {
|
|
1453
|
-
return BigInt(`0x${ownerAddress.toLowerCase().slice(2).padEnd(64, "0")}`);
|
|
1454
|
-
}
|
|
1455
1930
|
function createCapxulBundler(config) {
|
|
1456
1931
|
const paymaster = createPaymasterClient({
|
|
1457
1932
|
transport: http(config.rpcUrl)
|
|
@@ -1558,13 +2033,13 @@ async function transferAsOwner(config, params) {
|
|
|
1558
2033
|
function createPaymentsClient(config = {}) {
|
|
1559
2034
|
return {
|
|
1560
2035
|
create: async (input) => {
|
|
1561
|
-
if (!config.
|
|
2036
|
+
if (!config._data || !config.signer || !config.signing) {
|
|
1562
2037
|
return stub("payments.create");
|
|
1563
2038
|
}
|
|
1564
2039
|
let created = null;
|
|
1565
2040
|
let submitted = null;
|
|
1566
2041
|
try {
|
|
1567
|
-
created = await config.
|
|
2042
|
+
created = await config._data.mutation(api.payments.mutations.create, {
|
|
1568
2043
|
to: input.to,
|
|
1569
2044
|
amount: input.amount,
|
|
1570
2045
|
reference: input.reference,
|
|
@@ -1572,15 +2047,21 @@ function createPaymentsClient(config = {}) {
|
|
|
1572
2047
|
source: input.source
|
|
1573
2048
|
});
|
|
1574
2049
|
if (!created) {
|
|
1575
|
-
return [
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
2050
|
+
return [
|
|
2051
|
+
new CapxulError({
|
|
2052
|
+
code: "NETWORK_ERROR",
|
|
2053
|
+
message: "payments.create returned no payment resource"
|
|
2054
|
+
}),
|
|
2055
|
+
null
|
|
2056
|
+
];
|
|
1579
2057
|
}
|
|
1580
2058
|
if (created.status !== "processing" || created.operation.status !== "processing") {
|
|
1581
2059
|
return [null, created];
|
|
1582
2060
|
}
|
|
1583
|
-
const currentSigner = await config.
|
|
2061
|
+
const currentSigner = await config._data.query(
|
|
2062
|
+
api.safe.queries.getMySignerAddress,
|
|
2063
|
+
{}
|
|
2064
|
+
);
|
|
1584
2065
|
if (!currentSigner?.address) {
|
|
1585
2066
|
throw new CapxulError({
|
|
1586
2067
|
code: "PERMISSION_DENIED",
|
|
@@ -1599,9 +2080,12 @@ function createPaymentsClient(config = {}) {
|
|
|
1599
2080
|
}
|
|
1600
2081
|
});
|
|
1601
2082
|
}
|
|
1602
|
-
const submission = await config.
|
|
1603
|
-
|
|
1604
|
-
|
|
2083
|
+
const submission = await config._data.query(
|
|
2084
|
+
api.payments.queries.prepareSubmission,
|
|
2085
|
+
{
|
|
2086
|
+
paymentId: created.id
|
|
2087
|
+
}
|
|
2088
|
+
);
|
|
1605
2089
|
if (!submission?.recipientAddress) {
|
|
1606
2090
|
throw new CapxulError({
|
|
1607
2091
|
code: "NETWORK_ERROR",
|
|
@@ -1609,15 +2093,16 @@ function createPaymentsClient(config = {}) {
|
|
|
1609
2093
|
details: { paymentId: created.id }
|
|
1610
2094
|
});
|
|
1611
2095
|
}
|
|
2096
|
+
const token = resolvePaymentToken(submission.amount.currency);
|
|
1612
2097
|
const transfer = await transferAsOwner(
|
|
1613
2098
|
{
|
|
1614
2099
|
signer: config.signer,
|
|
1615
2100
|
signing: config.signing
|
|
1616
2101
|
},
|
|
1617
2102
|
{
|
|
1618
|
-
tokenAddress:
|
|
2103
|
+
tokenAddress: token.address,
|
|
1619
2104
|
recipientAddress: submission.recipientAddress,
|
|
1620
|
-
amount: toTokenUnits(submission.amount.value,
|
|
2105
|
+
amount: toTokenUnits(submission.amount.value, token.decimals)
|
|
1621
2106
|
}
|
|
1622
2107
|
);
|
|
1623
2108
|
if (!transfer.success) {
|
|
@@ -1635,7 +2120,7 @@ function createPaymentsClient(config = {}) {
|
|
|
1635
2120
|
txHash: transfer.txHash,
|
|
1636
2121
|
userOpHash: transfer.userOpHash
|
|
1637
2122
|
};
|
|
1638
|
-
await config.
|
|
2123
|
+
await config._data.mutation(api.payments.mutations.recordSubmitted, {
|
|
1639
2124
|
paymentId: created.id,
|
|
1640
2125
|
txHash: transfer.txHash,
|
|
1641
2126
|
userOpHash: transfer.userOpHash,
|
|
@@ -1645,43 +2130,65 @@ function createPaymentsClient(config = {}) {
|
|
|
1645
2130
|
} catch (cause) {
|
|
1646
2131
|
const error = mapCreateError(fromConvexError(cause));
|
|
1647
2132
|
if (created?.id && created.status === "processing" && !submitted) {
|
|
1648
|
-
await bestEffortMarkFailed({
|
|
2133
|
+
await bestEffortMarkFailed({ _data: config._data }, created.id, error);
|
|
1649
2134
|
}
|
|
1650
2135
|
if (submitted && created?.id) {
|
|
1651
|
-
return [
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
2136
|
+
return [
|
|
2137
|
+
new CapxulError({
|
|
2138
|
+
code: "NETWORK_ERROR",
|
|
2139
|
+
message: "Payment was submitted on-chain, but backend submission tracking failed.",
|
|
2140
|
+
cause,
|
|
2141
|
+
details: {
|
|
2142
|
+
paymentId: created.id,
|
|
2143
|
+
txHash: submitted.txHash,
|
|
2144
|
+
userOpHash: submitted.userOpHash
|
|
2145
|
+
}
|
|
2146
|
+
}),
|
|
2147
|
+
null
|
|
2148
|
+
];
|
|
1661
2149
|
}
|
|
1662
2150
|
return [error, null];
|
|
1663
2151
|
}
|
|
1664
2152
|
},
|
|
1665
2153
|
retrieve: async (paymentId) => {
|
|
1666
|
-
if (!config.
|
|
2154
|
+
if (!config._data) {
|
|
1667
2155
|
return stub("payments.retrieve");
|
|
1668
2156
|
}
|
|
1669
2157
|
try {
|
|
1670
|
-
const payment = await config.
|
|
1671
|
-
|
|
1672
|
-
|
|
2158
|
+
const payment = await config._data.query(
|
|
2159
|
+
api.payments.queries.retrieve,
|
|
2160
|
+
{
|
|
2161
|
+
paymentId
|
|
2162
|
+
}
|
|
2163
|
+
);
|
|
1673
2164
|
if (!payment) {
|
|
1674
|
-
return [
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2165
|
+
return [
|
|
2166
|
+
new CapxulError({
|
|
2167
|
+
code: "NOT_FOUND",
|
|
2168
|
+
message: `payment ${paymentId} not found`
|
|
2169
|
+
}),
|
|
2170
|
+
null
|
|
2171
|
+
];
|
|
1678
2172
|
}
|
|
1679
2173
|
return [null, payment];
|
|
1680
2174
|
} catch (cause) {
|
|
1681
2175
|
return [fromConvexError(cause), null];
|
|
1682
2176
|
}
|
|
1683
2177
|
},
|
|
1684
|
-
list: async () =>
|
|
2178
|
+
list: async (input) => {
|
|
2179
|
+
if (!config._data) {
|
|
2180
|
+
return stub("payments.list");
|
|
2181
|
+
}
|
|
2182
|
+
try {
|
|
2183
|
+
const page = await config._data.query(api.payments.queries.list, {
|
|
2184
|
+
limit: input?.limit,
|
|
2185
|
+
cursor: input?.cursor
|
|
2186
|
+
});
|
|
2187
|
+
return [null, page];
|
|
2188
|
+
} catch (cause) {
|
|
2189
|
+
return [fromConvexError(cause), null];
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
1685
2192
|
};
|
|
1686
2193
|
}
|
|
1687
2194
|
function createOrgPaymentsClient() {
|
|
@@ -1695,7 +2202,7 @@ function createOrgPaymentsClient() {
|
|
|
1695
2202
|
}
|
|
1696
2203
|
async function bestEffortMarkFailed(config, paymentId, error) {
|
|
1697
2204
|
try {
|
|
1698
|
-
await config.
|
|
2205
|
+
await config._data.mutation(api.payments.mutations.markFailed, {
|
|
1699
2206
|
paymentId,
|
|
1700
2207
|
errorCode: error.code,
|
|
1701
2208
|
errorMessage: error.message,
|
|
@@ -1752,11 +2259,11 @@ function createOrgTransfersClient() {
|
|
|
1752
2259
|
function createWithdrawalsClient(config = {}) {
|
|
1753
2260
|
return {
|
|
1754
2261
|
create: async (input) => {
|
|
1755
|
-
if (!config.
|
|
2262
|
+
if (!config._data) {
|
|
1756
2263
|
return stub("withdrawals.create");
|
|
1757
2264
|
}
|
|
1758
2265
|
const [createErr, createdRaw] = await tryCatch(
|
|
1759
|
-
config.
|
|
2266
|
+
config._data.mutation(api.withdrawals.mutations.create, {
|
|
1760
2267
|
amount: input.amount,
|
|
1761
2268
|
destination: {
|
|
1762
2269
|
externalAccountId: input.destination.externalAccountId
|
|
@@ -1786,18 +2293,18 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1786
2293
|
return [null, created];
|
|
1787
2294
|
}
|
|
1788
2295
|
const [signerErr, currentSigner] = await tryCatch(
|
|
1789
|
-
config.
|
|
2296
|
+
config._data.query(api.safe.queries.getMySignerAddress, {})
|
|
1790
2297
|
);
|
|
1791
2298
|
if (signerErr) {
|
|
1792
2299
|
return await handleSubmissionFailure(
|
|
1793
|
-
{
|
|
2300
|
+
{ _data: config._data },
|
|
1794
2301
|
created.id,
|
|
1795
2302
|
mapCreateError2(fromConvexError(signerErr))
|
|
1796
2303
|
);
|
|
1797
2304
|
}
|
|
1798
2305
|
if (!currentSigner?.address) {
|
|
1799
2306
|
return await handleSubmissionFailure(
|
|
1800
|
-
{
|
|
2307
|
+
{ _data: config._data },
|
|
1801
2308
|
created.id,
|
|
1802
2309
|
new CapxulError({
|
|
1803
2310
|
code: "PERMISSION_DENIED",
|
|
@@ -1808,7 +2315,7 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1808
2315
|
}
|
|
1809
2316
|
if (getAddress(currentSigner.address) !== getAddress(config.signer.address)) {
|
|
1810
2317
|
return await handleSubmissionFailure(
|
|
1811
|
-
{
|
|
2318
|
+
{ _data: config._data },
|
|
1812
2319
|
created.id,
|
|
1813
2320
|
new CapxulError({
|
|
1814
2321
|
code: "PERMISSION_DENIED",
|
|
@@ -1822,13 +2329,13 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1822
2329
|
);
|
|
1823
2330
|
}
|
|
1824
2331
|
const [prepErr, submission] = await tryCatch(
|
|
1825
|
-
config.
|
|
2332
|
+
config._data.query(api.withdrawals.queries.prepareSubmission, {
|
|
1826
2333
|
withdrawalId: created.id
|
|
1827
2334
|
})
|
|
1828
2335
|
);
|
|
1829
2336
|
if (prepErr) {
|
|
1830
2337
|
return await handleSubmissionFailure(
|
|
1831
|
-
{
|
|
2338
|
+
{ _data: config._data },
|
|
1832
2339
|
created.id,
|
|
1833
2340
|
mapCreateError2(fromConvexError(prepErr))
|
|
1834
2341
|
);
|
|
@@ -1836,7 +2343,7 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1836
2343
|
const destinationAddress = submission?.destinationAddress;
|
|
1837
2344
|
if (!submission || !destinationAddress) {
|
|
1838
2345
|
return await handleSubmissionFailure(
|
|
1839
|
-
{
|
|
2346
|
+
{ _data: config._data },
|
|
1840
2347
|
created.id,
|
|
1841
2348
|
new CapxulError({
|
|
1842
2349
|
code: "NETWORK_ERROR",
|
|
@@ -1845,6 +2352,7 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1845
2352
|
})
|
|
1846
2353
|
);
|
|
1847
2354
|
}
|
|
2355
|
+
const token = resolvePaymentToken(submission.amount.currency);
|
|
1848
2356
|
const [transferErr, transferOk] = await tryCatch(
|
|
1849
2357
|
transferAsOwner(
|
|
1850
2358
|
{
|
|
@@ -1852,22 +2360,22 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1852
2360
|
signing: config.signing
|
|
1853
2361
|
},
|
|
1854
2362
|
{
|
|
1855
|
-
tokenAddress:
|
|
2363
|
+
tokenAddress: token.address,
|
|
1856
2364
|
recipientAddress: destinationAddress,
|
|
1857
|
-
amount: toTokenUnits(submission.amount.value,
|
|
2365
|
+
amount: toTokenUnits(submission.amount.value, token.decimals)
|
|
1858
2366
|
}
|
|
1859
2367
|
)
|
|
1860
2368
|
);
|
|
1861
2369
|
if (transferErr) {
|
|
1862
2370
|
return await handleSubmissionFailure(
|
|
1863
|
-
{
|
|
2371
|
+
{ _data: config._data },
|
|
1864
2372
|
created.id,
|
|
1865
2373
|
mapCreateError2(fromConvexError(transferErr))
|
|
1866
2374
|
);
|
|
1867
2375
|
}
|
|
1868
2376
|
if (!transferOk.success) {
|
|
1869
2377
|
return await handleSubmissionFailure(
|
|
1870
|
-
{
|
|
2378
|
+
{ _data: config._data },
|
|
1871
2379
|
created.id,
|
|
1872
2380
|
new CapxulError({
|
|
1873
2381
|
code: "NETWORK_ERROR",
|
|
@@ -1881,7 +2389,7 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1881
2389
|
);
|
|
1882
2390
|
}
|
|
1883
2391
|
const [recordErr] = await tryCatch(
|
|
1884
|
-
config.
|
|
2392
|
+
config._data.mutation(api.withdrawals.mutations.recordSubmitted, {
|
|
1885
2393
|
withdrawalId: created.id,
|
|
1886
2394
|
txHash: transferOk.txHash,
|
|
1887
2395
|
userOpHash: transferOk.userOpHash
|
|
@@ -1905,11 +2413,11 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1905
2413
|
return [null, created];
|
|
1906
2414
|
},
|
|
1907
2415
|
retrieve: async (withdrawalId) => {
|
|
1908
|
-
if (!config.
|
|
2416
|
+
if (!config._data) {
|
|
1909
2417
|
return stub("withdrawals.retrieve");
|
|
1910
2418
|
}
|
|
1911
2419
|
const [err, raw] = await tryCatch(
|
|
1912
|
-
config.
|
|
2420
|
+
config._data.query(api.withdrawals.queries.retrieve, { withdrawalId })
|
|
1913
2421
|
);
|
|
1914
2422
|
if (err) {
|
|
1915
2423
|
return [fromConvexError(err), null];
|
|
@@ -1927,11 +2435,11 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1927
2435
|
return [null, withdrawal];
|
|
1928
2436
|
},
|
|
1929
2437
|
list: async (input) => {
|
|
1930
|
-
if (!config.
|
|
2438
|
+
if (!config._data) {
|
|
1931
2439
|
return stub("withdrawals.list");
|
|
1932
2440
|
}
|
|
1933
2441
|
const [err, raw] = await tryCatch(
|
|
1934
|
-
config.
|
|
2442
|
+
config._data.query(api.withdrawals.queries.list, {
|
|
1935
2443
|
limit: input?.limit,
|
|
1936
2444
|
cursor: input?.cursor
|
|
1937
2445
|
})
|
|
@@ -1942,13 +2450,13 @@ function createWithdrawalsClient(config = {}) {
|
|
|
1942
2450
|
return [null, raw];
|
|
1943
2451
|
},
|
|
1944
2452
|
recordCompleted: async (input) => {
|
|
1945
|
-
if (!config.
|
|
2453
|
+
if (!config._data) {
|
|
1946
2454
|
return stub(
|
|
1947
2455
|
"withdrawals.recordCompleted"
|
|
1948
2456
|
);
|
|
1949
2457
|
}
|
|
1950
2458
|
const [err] = await tryCatch(
|
|
1951
|
-
config.
|
|
2459
|
+
config._data.mutation(api.withdrawals.mutations.recordCompleted, {
|
|
1952
2460
|
withdrawalId: input.withdrawalId,
|
|
1953
2461
|
txHash: input.txHash
|
|
1954
2462
|
})
|
|
@@ -1973,13 +2481,13 @@ function createOrgWithdrawalsClient(config = {}) {
|
|
|
1973
2481
|
* orchestration ships in W3+.
|
|
1974
2482
|
*/
|
|
1975
2483
|
create: async (input) => {
|
|
1976
|
-
if (!config.
|
|
2484
|
+
if (!config._data) {
|
|
1977
2485
|
return stub(
|
|
1978
2486
|
"organizations.withdrawals.create"
|
|
1979
2487
|
);
|
|
1980
2488
|
}
|
|
1981
2489
|
const [err, raw] = await tryCatch(
|
|
1982
|
-
config.
|
|
2490
|
+
config._data.mutation(api.withdrawals.mutations.createOrg, {
|
|
1983
2491
|
organizationId: input.organizationId,
|
|
1984
2492
|
amount: input.amount,
|
|
1985
2493
|
destination: {
|
|
@@ -2006,13 +2514,13 @@ function createOrgWithdrawalsClient(config = {}) {
|
|
|
2006
2514
|
return [null, created];
|
|
2007
2515
|
},
|
|
2008
2516
|
retrieve: async (input) => {
|
|
2009
|
-
if (!config.
|
|
2517
|
+
if (!config._data) {
|
|
2010
2518
|
return stub(
|
|
2011
2519
|
"organizations.withdrawals.retrieve"
|
|
2012
2520
|
);
|
|
2013
2521
|
}
|
|
2014
2522
|
const [err, raw] = await tryCatch(
|
|
2015
|
-
config.
|
|
2523
|
+
config._data.query(api.withdrawals.queries.retrieve, {
|
|
2016
2524
|
withdrawalId: input.withdrawalId
|
|
2017
2525
|
})
|
|
2018
2526
|
);
|
|
@@ -2042,13 +2550,13 @@ function createOrgWithdrawalsClient(config = {}) {
|
|
|
2042
2550
|
return [null, withdrawal];
|
|
2043
2551
|
},
|
|
2044
2552
|
list: async (input) => {
|
|
2045
|
-
if (!config.
|
|
2553
|
+
if (!config._data) {
|
|
2046
2554
|
return stub(
|
|
2047
2555
|
"organizations.withdrawals.list"
|
|
2048
2556
|
);
|
|
2049
2557
|
}
|
|
2050
2558
|
const [err, raw] = await tryCatch(
|
|
2051
|
-
config.
|
|
2559
|
+
config._data.query(api.withdrawals.queries.listOrg, {
|
|
2052
2560
|
organizationId: input.organizationId,
|
|
2053
2561
|
limit: input.limit,
|
|
2054
2562
|
cursor: input.cursor
|
|
@@ -2067,7 +2575,7 @@ async function handleSubmissionFailure(config, withdrawalId, error) {
|
|
|
2067
2575
|
}
|
|
2068
2576
|
async function bestEffortMarkFailed2(config, withdrawalId, error) {
|
|
2069
2577
|
await tryCatch(
|
|
2070
|
-
config.
|
|
2578
|
+
config._data.mutation(api.withdrawals.mutations.markFailed, {
|
|
2071
2579
|
withdrawalId,
|
|
2072
2580
|
errorCode: error.code,
|
|
2073
2581
|
errorMessage: error.message
|
|
@@ -2146,13 +2654,13 @@ function createWebhookEventsClient() {
|
|
|
2146
2654
|
function createOrgExternalAccountsClient(config) {
|
|
2147
2655
|
return {
|
|
2148
2656
|
create: async (input) => {
|
|
2149
|
-
if (!config.
|
|
2657
|
+
if (!config._data) {
|
|
2150
2658
|
return stub(
|
|
2151
2659
|
"organizations.externalAccounts.create"
|
|
2152
2660
|
);
|
|
2153
2661
|
}
|
|
2154
2662
|
const [err, raw] = await tryCatch(
|
|
2155
|
-
config.
|
|
2663
|
+
config._data.mutation(api.externalAccounts.mutations.createOrg, {
|
|
2156
2664
|
organizationId: input.organizationId,
|
|
2157
2665
|
kind: input.kind,
|
|
2158
2666
|
label: input.label,
|
|
@@ -2166,10 +2674,7 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2166
2674
|
})
|
|
2167
2675
|
);
|
|
2168
2676
|
if (err) {
|
|
2169
|
-
return [
|
|
2170
|
-
fromConvexError(err),
|
|
2171
|
-
null
|
|
2172
|
-
];
|
|
2677
|
+
return [fromConvexError(err), null];
|
|
2173
2678
|
}
|
|
2174
2679
|
if (!raw) {
|
|
2175
2680
|
return [
|
|
@@ -2180,21 +2685,16 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2180
2685
|
null
|
|
2181
2686
|
];
|
|
2182
2687
|
}
|
|
2183
|
-
return [
|
|
2184
|
-
null,
|
|
2185
|
-
brandExternalAccount(
|
|
2186
|
-
raw
|
|
2187
|
-
)
|
|
2188
|
-
];
|
|
2688
|
+
return [null, brandExternalAccount(raw)];
|
|
2189
2689
|
},
|
|
2190
2690
|
list: async (input) => {
|
|
2191
|
-
if (!config.
|
|
2691
|
+
if (!config._data) {
|
|
2192
2692
|
return stub(
|
|
2193
2693
|
"organizations.externalAccounts.list"
|
|
2194
2694
|
);
|
|
2195
2695
|
}
|
|
2196
2696
|
const [err, result] = await tryCatch(
|
|
2197
|
-
config.
|
|
2697
|
+
config._data.query(api.externalAccounts.queries.listOrg, {
|
|
2198
2698
|
organizationId: input.organizationId,
|
|
2199
2699
|
limit: input.limit,
|
|
2200
2700
|
cursor: input.cursor
|
|
@@ -2204,9 +2704,7 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2204
2704
|
return [fromConvexError(err), null];
|
|
2205
2705
|
}
|
|
2206
2706
|
const branded = result.data.map(
|
|
2207
|
-
(row) => brandExternalAccount(
|
|
2208
|
-
row
|
|
2209
|
-
)
|
|
2707
|
+
(row) => brandExternalAccount(row)
|
|
2210
2708
|
);
|
|
2211
2709
|
return [
|
|
2212
2710
|
null,
|
|
@@ -2218,17 +2716,66 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2218
2716
|
];
|
|
2219
2717
|
},
|
|
2220
2718
|
retrieve: async (input) => {
|
|
2221
|
-
if (!config.
|
|
2719
|
+
if (!config._data) {
|
|
2222
2720
|
return stub(
|
|
2223
2721
|
"organizations.externalAccounts.retrieve"
|
|
2224
2722
|
);
|
|
2225
2723
|
}
|
|
2226
2724
|
const [err, raw] = await tryCatch(
|
|
2227
|
-
config.
|
|
2725
|
+
config._data.query(api.externalAccounts.queries.retrieveOrg, {
|
|
2726
|
+
organizationId: input.organizationId,
|
|
2727
|
+
externalAccountId: input.externalAccountId
|
|
2728
|
+
})
|
|
2729
|
+
);
|
|
2730
|
+
if (err) {
|
|
2731
|
+
return [fromConvexError(err), null];
|
|
2732
|
+
}
|
|
2733
|
+
if (!raw) {
|
|
2734
|
+
return [
|
|
2735
|
+
new CapxulError({
|
|
2736
|
+
code: "NOT_FOUND",
|
|
2737
|
+
message: `external_account ${input.externalAccountId} not found`
|
|
2738
|
+
}),
|
|
2739
|
+
null
|
|
2740
|
+
];
|
|
2741
|
+
}
|
|
2742
|
+
return [null, brandExternalAccount(raw)];
|
|
2743
|
+
},
|
|
2744
|
+
remove: async (input) => {
|
|
2745
|
+
if (!config._data) {
|
|
2746
|
+
return stub("organizations.externalAccounts.remove");
|
|
2747
|
+
}
|
|
2748
|
+
const [err] = await tryCatch(
|
|
2749
|
+
config._data.mutation(api.externalAccounts.mutations.removeOrg, {
|
|
2228
2750
|
organizationId: input.organizationId,
|
|
2229
2751
|
externalAccountId: input.externalAccountId
|
|
2230
2752
|
})
|
|
2231
2753
|
);
|
|
2754
|
+
if (err) {
|
|
2755
|
+
return [fromConvexError(err), null];
|
|
2756
|
+
}
|
|
2757
|
+
return [null, void 0];
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
function createOrgSubAccountsClient(config) {
|
|
2762
|
+
return {
|
|
2763
|
+
create: async (input) => {
|
|
2764
|
+
if (!config._data) {
|
|
2765
|
+
return stub(
|
|
2766
|
+
"organizations.subAccounts.create"
|
|
2767
|
+
);
|
|
2768
|
+
}
|
|
2769
|
+
const [err, raw] = await tryCatch(
|
|
2770
|
+
config._data.mutation(api.subAccounts.mutations.create, {
|
|
2771
|
+
parent: {
|
|
2772
|
+
kind: "organization",
|
|
2773
|
+
id: input.organizationId
|
|
2774
|
+
},
|
|
2775
|
+
name: input.name,
|
|
2776
|
+
purpose: input.purpose
|
|
2777
|
+
})
|
|
2778
|
+
);
|
|
2232
2779
|
if (err) {
|
|
2233
2780
|
return [
|
|
2234
2781
|
fromConvexError(err),
|
|
@@ -2239,28 +2786,95 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2239
2786
|
return [
|
|
2240
2787
|
new CapxulError({
|
|
2241
2788
|
code: "NOT_FOUND",
|
|
2242
|
-
message:
|
|
2789
|
+
message: "sub_account creation returned no resource"
|
|
2243
2790
|
}),
|
|
2244
2791
|
null
|
|
2245
2792
|
];
|
|
2246
2793
|
}
|
|
2794
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
2795
|
+
if (brandErr) {
|
|
2796
|
+
return [brandErr, null];
|
|
2797
|
+
}
|
|
2798
|
+
return [null, branded];
|
|
2799
|
+
},
|
|
2800
|
+
list: async (input) => {
|
|
2801
|
+
if (!config._data) {
|
|
2802
|
+
return stub(
|
|
2803
|
+
"organizations.subAccounts.list"
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2806
|
+
const [err, rows] = await tryCatch(
|
|
2807
|
+
config._data.query(api.subAccounts.queries.listByOrganization, {
|
|
2808
|
+
organizationId: input.organizationId
|
|
2809
|
+
})
|
|
2810
|
+
);
|
|
2811
|
+
if (err) {
|
|
2812
|
+
return [
|
|
2813
|
+
fromConvexError(err),
|
|
2814
|
+
null
|
|
2815
|
+
];
|
|
2816
|
+
}
|
|
2817
|
+
const branded = [];
|
|
2818
|
+
for (const row of rows) {
|
|
2819
|
+
const [brandErr, value] = tryBrandSubAccount(row);
|
|
2820
|
+
if (brandErr) {
|
|
2821
|
+
return [brandErr, null];
|
|
2822
|
+
}
|
|
2823
|
+
branded.push(value);
|
|
2824
|
+
}
|
|
2247
2825
|
return [
|
|
2248
2826
|
null,
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2827
|
+
{
|
|
2828
|
+
object: "list",
|
|
2829
|
+
data: branded,
|
|
2830
|
+
page: { hasMore: false }
|
|
2831
|
+
}
|
|
2252
2832
|
];
|
|
2253
2833
|
},
|
|
2834
|
+
retrieve: async (input) => {
|
|
2835
|
+
if (!config._data) {
|
|
2836
|
+
return stub(
|
|
2837
|
+
"organizations.subAccounts.retrieve"
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2840
|
+
const [err, raw] = await tryCatch(
|
|
2841
|
+
config._data.query(api.subAccounts.queries.retrieve, {
|
|
2842
|
+
subAccountId: input.subAccountId
|
|
2843
|
+
})
|
|
2844
|
+
);
|
|
2845
|
+
if (err) {
|
|
2846
|
+
return [
|
|
2847
|
+
fromConvexError(err),
|
|
2848
|
+
null
|
|
2849
|
+
];
|
|
2850
|
+
}
|
|
2851
|
+
if (!raw) {
|
|
2852
|
+
return [
|
|
2853
|
+
new CapxulError({
|
|
2854
|
+
code: "NOT_FOUND",
|
|
2855
|
+
message: `sub_account ${input.subAccountId} not found`
|
|
2856
|
+
}),
|
|
2857
|
+
null
|
|
2858
|
+
];
|
|
2859
|
+
}
|
|
2860
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
2861
|
+
if (brandErr) {
|
|
2862
|
+
return [
|
|
2863
|
+
brandErr,
|
|
2864
|
+
null
|
|
2865
|
+
];
|
|
2866
|
+
}
|
|
2867
|
+
return [null, branded];
|
|
2868
|
+
},
|
|
2254
2869
|
remove: async (input) => {
|
|
2255
|
-
if (!config.
|
|
2870
|
+
if (!config._data) {
|
|
2256
2871
|
return stub(
|
|
2257
|
-
"organizations.
|
|
2872
|
+
"organizations.subAccounts.remove"
|
|
2258
2873
|
);
|
|
2259
2874
|
}
|
|
2260
|
-
const [err] = await tryCatch(
|
|
2261
|
-
config.
|
|
2262
|
-
|
|
2263
|
-
externalAccountId: input.externalAccountId
|
|
2875
|
+
const [err, raw] = await tryCatch(
|
|
2876
|
+
config._data.mutation(api.subAccounts.mutations.archive, {
|
|
2877
|
+
subAccountId: input.subAccountId
|
|
2264
2878
|
})
|
|
2265
2879
|
);
|
|
2266
2880
|
if (err) {
|
|
@@ -2269,23 +2883,139 @@ function createOrgExternalAccountsClient(config) {
|
|
|
2269
2883
|
null
|
|
2270
2884
|
];
|
|
2271
2885
|
}
|
|
2272
|
-
|
|
2886
|
+
if (!raw) {
|
|
2887
|
+
return [
|
|
2888
|
+
new CapxulError({
|
|
2889
|
+
code: "NOT_FOUND",
|
|
2890
|
+
message: `sub_account ${input.subAccountId} not found`
|
|
2891
|
+
}),
|
|
2892
|
+
null
|
|
2893
|
+
];
|
|
2894
|
+
}
|
|
2895
|
+
const [brandErr, branded] = tryBrandSubAccount(raw);
|
|
2896
|
+
if (brandErr) {
|
|
2897
|
+
return [
|
|
2898
|
+
brandErr,
|
|
2899
|
+
null
|
|
2900
|
+
];
|
|
2901
|
+
}
|
|
2902
|
+
return [null, branded];
|
|
2273
2903
|
}
|
|
2274
2904
|
};
|
|
2275
2905
|
}
|
|
2276
2906
|
function createOrganizationsClient(config = {}) {
|
|
2277
2907
|
return {
|
|
2278
|
-
create: async () =>
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2908
|
+
create: async (input) => {
|
|
2909
|
+
if (!config._data) {
|
|
2910
|
+
return stub("organizations.create");
|
|
2911
|
+
}
|
|
2912
|
+
if (input.country !== void 0) {
|
|
2913
|
+
return [
|
|
2914
|
+
new CapxulError({
|
|
2915
|
+
code: "INVALID_INPUT",
|
|
2916
|
+
message: "organizations.create does not support country yet \u2014 backend mutation only accepts name.",
|
|
2917
|
+
details: { field: "country" }
|
|
2918
|
+
}),
|
|
2919
|
+
null
|
|
2920
|
+
];
|
|
2921
|
+
}
|
|
2922
|
+
try {
|
|
2923
|
+
const orgId = await config._data.mutation(api.org.mutations.create, {
|
|
2924
|
+
name: input.name
|
|
2925
|
+
});
|
|
2926
|
+
const org = await config._data.query(api.org.queries.retrieve, {
|
|
2927
|
+
orgId
|
|
2928
|
+
});
|
|
2929
|
+
if (!org) {
|
|
2930
|
+
return [
|
|
2931
|
+
new CapxulError({
|
|
2932
|
+
code: "NETWORK_ERROR",
|
|
2933
|
+
message: "organization created but could not be retrieved"
|
|
2934
|
+
}),
|
|
2935
|
+
null
|
|
2936
|
+
];
|
|
2937
|
+
}
|
|
2938
|
+
return [null, org];
|
|
2939
|
+
} catch (cause) {
|
|
2940
|
+
return [fromConvexError(cause), null];
|
|
2941
|
+
}
|
|
2942
|
+
},
|
|
2943
|
+
retrieve: async (organizationId) => {
|
|
2944
|
+
if (!config._data) {
|
|
2945
|
+
return stub("organizations.retrieve");
|
|
2946
|
+
}
|
|
2947
|
+
try {
|
|
2948
|
+
const orgId = organizationId.replace(/^org_/, "");
|
|
2949
|
+
const org = await config._data.query(api.org.queries.retrieve, {
|
|
2950
|
+
orgId
|
|
2951
|
+
});
|
|
2952
|
+
if (!org) {
|
|
2953
|
+
return [
|
|
2954
|
+
new CapxulError({
|
|
2955
|
+
code: "NOT_FOUND",
|
|
2956
|
+
message: `organization ${organizationId} not found`
|
|
2957
|
+
}),
|
|
2958
|
+
null
|
|
2959
|
+
];
|
|
2960
|
+
}
|
|
2961
|
+
return [null, org];
|
|
2962
|
+
} catch (cause) {
|
|
2963
|
+
return [fromConvexError(cause), null];
|
|
2964
|
+
}
|
|
2965
|
+
},
|
|
2966
|
+
list: async (input) => {
|
|
2967
|
+
if (!config._data) {
|
|
2968
|
+
return stub("organizations.list");
|
|
2969
|
+
}
|
|
2970
|
+
try {
|
|
2971
|
+
const page = await config._data.query(api.org.queries.list, {
|
|
2972
|
+
limit: input?.limit,
|
|
2973
|
+
cursor: input?.cursor
|
|
2974
|
+
});
|
|
2975
|
+
const result = {
|
|
2976
|
+
object: "list",
|
|
2977
|
+
data: page.data,
|
|
2978
|
+
page: {
|
|
2979
|
+
hasMore: page.hasMore,
|
|
2980
|
+
cursor: page.nextCursor
|
|
2981
|
+
}
|
|
2982
|
+
};
|
|
2983
|
+
return [null, result];
|
|
2984
|
+
} catch (cause) {
|
|
2985
|
+
return [fromConvexError(cause), null];
|
|
2986
|
+
}
|
|
2987
|
+
},
|
|
2988
|
+
update: async (input) => {
|
|
2989
|
+
if (!config._data) {
|
|
2990
|
+
return stub("organizations.update");
|
|
2991
|
+
}
|
|
2992
|
+
try {
|
|
2993
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
2994
|
+
const org = await config._data.mutation(api.org.mutations.update, {
|
|
2995
|
+
orgId,
|
|
2996
|
+
name: input.name
|
|
2997
|
+
});
|
|
2998
|
+
if (!org) {
|
|
2999
|
+
return [
|
|
3000
|
+
new CapxulError({
|
|
3001
|
+
code: "NOT_FOUND",
|
|
3002
|
+
message: `organization ${input.organizationId} not found`
|
|
3003
|
+
}),
|
|
3004
|
+
null
|
|
3005
|
+
];
|
|
3006
|
+
}
|
|
3007
|
+
return [null, org];
|
|
3008
|
+
} catch (cause) {
|
|
3009
|
+
return [fromConvexError(cause), null];
|
|
3010
|
+
}
|
|
3011
|
+
},
|
|
2282
3012
|
safes: {
|
|
2283
3013
|
retrieve: async (input) => {
|
|
2284
|
-
if (!config.
|
|
3014
|
+
if (!config._data) {
|
|
2285
3015
|
return stub("organizations.safes.retrieve");
|
|
2286
3016
|
}
|
|
2287
3017
|
try {
|
|
2288
|
-
const safe = await config.
|
|
3018
|
+
const safe = await config._data.query(
|
|
2289
3019
|
api.safe.queries.retrieveOrganizationSafe,
|
|
2290
3020
|
input
|
|
2291
3021
|
);
|
|
@@ -2307,36 +3037,245 @@ function createOrganizationsClient(config = {}) {
|
|
|
2307
3037
|
}
|
|
2308
3038
|
}
|
|
2309
3039
|
},
|
|
2310
|
-
treasury: {
|
|
2311
|
-
retrieve: async () =>
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
3040
|
+
treasury: {
|
|
3041
|
+
retrieve: async (organizationId) => {
|
|
3042
|
+
if (!config._data) {
|
|
3043
|
+
return stub(
|
|
3044
|
+
"organizations.treasury.retrieve"
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
try {
|
|
3048
|
+
const orgId = organizationId.replace(/^org_/, "");
|
|
3049
|
+
const raw = await config._data.query(
|
|
3050
|
+
api.safe.queries.getOrgTreasuryBalance,
|
|
3051
|
+
{ orgId }
|
|
3052
|
+
);
|
|
3053
|
+
if (!raw) {
|
|
3054
|
+
return [
|
|
3055
|
+
new CapxulError({
|
|
3056
|
+
code: "NOT_FOUND",
|
|
3057
|
+
message: `treasury for organization ${organizationId} not found`
|
|
3058
|
+
}),
|
|
3059
|
+
null
|
|
3060
|
+
];
|
|
3061
|
+
}
|
|
3062
|
+
const treasury = {
|
|
3063
|
+
object: "treasury",
|
|
3064
|
+
id: toTreasuryId(`try_${orgId}`),
|
|
3065
|
+
organizationId,
|
|
3066
|
+
status: "active",
|
|
3067
|
+
safeId: toSafeId(
|
|
3068
|
+
`safe_${raw.safeAddress.replace(/^0x/, "").toLowerCase()}`
|
|
3069
|
+
),
|
|
3070
|
+
totalBalance: { value: "0", currency: "USD" },
|
|
3071
|
+
positions: raw.tokens.map((t) => ({
|
|
3072
|
+
symbol: t.symbol,
|
|
3073
|
+
contractAddress: t.tokenAddress,
|
|
3074
|
+
amount: t.balance
|
|
3075
|
+
})),
|
|
3076
|
+
asOf: raw.lastUpdatedAt ? new Date(raw.lastUpdatedAt).toISOString() : (/* @__PURE__ */ new Date()).toISOString()
|
|
3077
|
+
};
|
|
3078
|
+
return [null, treasury];
|
|
3079
|
+
} catch (cause) {
|
|
3080
|
+
return [
|
|
3081
|
+
fromConvexError(cause),
|
|
3082
|
+
null
|
|
3083
|
+
];
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
},
|
|
3087
|
+
members: {
|
|
3088
|
+
list: async (input) => {
|
|
3089
|
+
if (!config._data?.action) {
|
|
3090
|
+
return stub("organizations.members.list");
|
|
3091
|
+
}
|
|
3092
|
+
try {
|
|
3093
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3094
|
+
const page = await config._data.action(api.org.actions.membersList, {
|
|
3095
|
+
organizationId: orgId,
|
|
3096
|
+
status: input.status,
|
|
3097
|
+
limit: input.limit,
|
|
3098
|
+
cursor: input.cursor
|
|
3099
|
+
});
|
|
3100
|
+
return [null, page];
|
|
3101
|
+
} catch (cause) {
|
|
3102
|
+
return [fromConvexError(cause), null];
|
|
3103
|
+
}
|
|
3104
|
+
},
|
|
3105
|
+
retrieve: async (input) => {
|
|
3106
|
+
if (!config._data?.action) {
|
|
3107
|
+
return stub("organizations.members.retrieve");
|
|
3108
|
+
}
|
|
3109
|
+
try {
|
|
3110
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3111
|
+
const memberId = input.memberId.replace(/^mb_/, "");
|
|
3112
|
+
const member = await config._data.action(
|
|
3113
|
+
api.org.actions.retrieveMember,
|
|
3114
|
+
{
|
|
3115
|
+
organizationId: orgId,
|
|
3116
|
+
memberId
|
|
3117
|
+
}
|
|
3118
|
+
);
|
|
3119
|
+
return [null, member];
|
|
3120
|
+
} catch (cause) {
|
|
3121
|
+
return [fromConvexError(cause), null];
|
|
3122
|
+
}
|
|
3123
|
+
},
|
|
3124
|
+
invite: async (input) => {
|
|
3125
|
+
if (!config._data?.action) {
|
|
3126
|
+
return stub("organizations.members.invite");
|
|
3127
|
+
}
|
|
3128
|
+
try {
|
|
3129
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3130
|
+
const result = await config._data.action(
|
|
3131
|
+
api.org.actions.inviteMember,
|
|
3132
|
+
{
|
|
3133
|
+
organizationId: orgId,
|
|
3134
|
+
email: input.email,
|
|
3135
|
+
role: input.role
|
|
3136
|
+
}
|
|
3137
|
+
);
|
|
3138
|
+
return [null, result];
|
|
3139
|
+
} catch (cause) {
|
|
3140
|
+
return [fromConvexError(cause), null];
|
|
3141
|
+
}
|
|
3142
|
+
},
|
|
3143
|
+
accept: async (input) => {
|
|
3144
|
+
if (!config._data?.action) {
|
|
3145
|
+
return stub("organizations.members.accept");
|
|
3146
|
+
}
|
|
3147
|
+
try {
|
|
3148
|
+
const member = await config._data.action(
|
|
3149
|
+
api.org.actions.acceptInvitation,
|
|
3150
|
+
{ token: input.token }
|
|
3151
|
+
);
|
|
3152
|
+
return [null, member];
|
|
3153
|
+
} catch (cause) {
|
|
3154
|
+
return [fromConvexError(cause), null];
|
|
3155
|
+
}
|
|
3156
|
+
},
|
|
3157
|
+
updateRole: async (input) => {
|
|
3158
|
+
if (!config._data?.action) {
|
|
3159
|
+
return stub("organizations.members.updateRole");
|
|
3160
|
+
}
|
|
3161
|
+
try {
|
|
3162
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3163
|
+
const memberId = input.memberId.replace(/^mb_/, "");
|
|
3164
|
+
const member = await config._data.action(
|
|
3165
|
+
api.org.actions.updateMemberRole,
|
|
3166
|
+
{
|
|
3167
|
+
organizationId: orgId,
|
|
3168
|
+
memberId,
|
|
3169
|
+
role: input.role
|
|
3170
|
+
}
|
|
3171
|
+
);
|
|
3172
|
+
return [null, member];
|
|
3173
|
+
} catch (cause) {
|
|
3174
|
+
return [fromConvexError(cause), null];
|
|
3175
|
+
}
|
|
3176
|
+
},
|
|
3177
|
+
revoke: async (input) => {
|
|
3178
|
+
if (!config._data?.action) {
|
|
3179
|
+
return stub("organizations.members.revoke");
|
|
3180
|
+
}
|
|
3181
|
+
try {
|
|
3182
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3183
|
+
const memberId = input.memberId.replace(/^mb_/, "");
|
|
3184
|
+
const member = await config._data.action(
|
|
3185
|
+
api.org.actions.revokeMember,
|
|
3186
|
+
{
|
|
3187
|
+
organizationId: orgId,
|
|
3188
|
+
memberId
|
|
3189
|
+
}
|
|
3190
|
+
);
|
|
3191
|
+
return [null, member];
|
|
3192
|
+
} catch (cause) {
|
|
3193
|
+
return [fromConvexError(cause), null];
|
|
3194
|
+
}
|
|
3195
|
+
},
|
|
3196
|
+
remove: async (input) => {
|
|
3197
|
+
if (!config._data?.action) {
|
|
3198
|
+
return stub("organizations.members.remove");
|
|
3199
|
+
}
|
|
3200
|
+
try {
|
|
3201
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3202
|
+
const memberId = input.memberId.replace(/^mb_/, "");
|
|
3203
|
+
await config._data.action(api.org.actions.removeMember, {
|
|
3204
|
+
organizationId: orgId,
|
|
3205
|
+
memberId
|
|
3206
|
+
});
|
|
3207
|
+
return [null, void 0];
|
|
3208
|
+
} catch (cause) {
|
|
3209
|
+
return [fromConvexError(cause), null];
|
|
3210
|
+
}
|
|
3211
|
+
},
|
|
3212
|
+
resend: async (input) => {
|
|
3213
|
+
if (!config._data?.action) {
|
|
3214
|
+
return stub("organizations.members.resend");
|
|
3215
|
+
}
|
|
3216
|
+
try {
|
|
3217
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3218
|
+
const memberId = input.memberId.replace(/^mb_/, "");
|
|
3219
|
+
const result = await config._data.action(
|
|
3220
|
+
api.org.actions.resendInvitation,
|
|
3221
|
+
{
|
|
3222
|
+
organizationId: orgId,
|
|
3223
|
+
memberId
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
return [null, result];
|
|
3227
|
+
} catch (cause) {
|
|
3228
|
+
return [fromConvexError(cause), null];
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
},
|
|
3232
|
+
apiKeys: createApiKeysClient(),
|
|
3233
|
+
subAccounts: createOrgSubAccountsClient(config),
|
|
3234
|
+
externalAccounts: createOrgExternalAccountsClient(config),
|
|
3235
|
+
balanceLedger: {
|
|
3236
|
+
list: async (input) => {
|
|
3237
|
+
if (!config._data) {
|
|
3238
|
+
return stub(
|
|
3239
|
+
"organizations.balanceLedger.list"
|
|
3240
|
+
);
|
|
3241
|
+
}
|
|
3242
|
+
try {
|
|
3243
|
+
const orgId = input.organizationId.replace(/^org_/, "");
|
|
3244
|
+
const page = await config._data.query(
|
|
3245
|
+
api.balanceLedger.queries.listForOrg,
|
|
3246
|
+
{ orgId, limit: input.limit, cursor: input.cursor }
|
|
3247
|
+
);
|
|
3248
|
+
return [null, page];
|
|
3249
|
+
} catch (cause) {
|
|
3250
|
+
return [fromConvexError(cause), null];
|
|
3251
|
+
}
|
|
3252
|
+
},
|
|
3253
|
+
retrieve: async (input) => {
|
|
3254
|
+
if (!config._data) {
|
|
3255
|
+
return stub(
|
|
3256
|
+
"organizations.balanceLedger.retrieve"
|
|
3257
|
+
);
|
|
3258
|
+
}
|
|
3259
|
+
try {
|
|
3260
|
+
const entry = await config._data.query(
|
|
3261
|
+
api.balanceLedger.queries.retrieve,
|
|
3262
|
+
{ entryId: input.entryId }
|
|
3263
|
+
);
|
|
3264
|
+
if (!entry) {
|
|
3265
|
+
return [
|
|
3266
|
+
new CapxulError({
|
|
3267
|
+
code: "NOT_FOUND",
|
|
3268
|
+
message: `balance_ledger_entry ${input.entryId} not found`
|
|
3269
|
+
}),
|
|
3270
|
+
null
|
|
3271
|
+
];
|
|
3272
|
+
}
|
|
3273
|
+
return [null, entry];
|
|
3274
|
+
} catch (cause) {
|
|
3275
|
+
return [fromConvexError(cause), null];
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
},
|
|
2340
3279
|
payments: createOrgPaymentsClient(),
|
|
2341
3280
|
transfers: createOrgTransfersClient(),
|
|
2342
3281
|
withdrawals: createOrgWithdrawalsClient(config),
|
|
@@ -2346,14 +3285,6 @@ function createOrganizationsClient(config = {}) {
|
|
|
2346
3285
|
};
|
|
2347
3286
|
}
|
|
2348
3287
|
|
|
2349
|
-
// src/core/sub-accounts.ts
|
|
2350
|
-
function createSubAccountsClient() {
|
|
2351
|
-
return {
|
|
2352
|
-
retrieve: async () => stub("subAccounts.retrieve"),
|
|
2353
|
-
remove: async () => stub("subAccounts.remove")
|
|
2354
|
-
};
|
|
2355
|
-
}
|
|
2356
|
-
|
|
2357
3288
|
// src/core/token-transfers.ts
|
|
2358
3289
|
var toTokenTransferId = (raw) => {
|
|
2359
3290
|
if (typeof raw !== "string" || raw.length === 0) {
|
|
@@ -2372,11 +3303,11 @@ function brandRow(row) {
|
|
|
2372
3303
|
function createTokenTransfersClient(config = {}) {
|
|
2373
3304
|
return {
|
|
2374
3305
|
list: async (input) => {
|
|
2375
|
-
if (!config.
|
|
3306
|
+
if (!config._data) {
|
|
2376
3307
|
return stub("tokenTransfers.list");
|
|
2377
3308
|
}
|
|
2378
3309
|
try {
|
|
2379
|
-
const raw = await config.
|
|
3310
|
+
const raw = await config._data.query(
|
|
2380
3311
|
api.tokenTransfers.queries.list,
|
|
2381
3312
|
{
|
|
2382
3313
|
limit: input?.limit,
|
|
@@ -2410,11 +3341,11 @@ function createTokenTransfersClient(config = {}) {
|
|
|
2410
3341
|
}
|
|
2411
3342
|
},
|
|
2412
3343
|
retrieve: async (input) => {
|
|
2413
|
-
if (!config.
|
|
3344
|
+
if (!config._data) {
|
|
2414
3345
|
return stub("tokenTransfers.retrieve");
|
|
2415
3346
|
}
|
|
2416
3347
|
try {
|
|
2417
|
-
const raw = await config.
|
|
3348
|
+
const raw = await config._data.query(
|
|
2418
3349
|
api.tokenTransfers.queries.getByTxLogIndex,
|
|
2419
3350
|
{
|
|
2420
3351
|
txHash: input.txHash,
|
|
@@ -2484,7 +3415,7 @@ function createAuthFlowMachine(client) {
|
|
|
2484
3415
|
}),
|
|
2485
3416
|
verifyOtp: fromPromise(
|
|
2486
3417
|
async ({ input, signal }) => {
|
|
2487
|
-
const [error,
|
|
3418
|
+
const [error, result] = await client.auth.verifyOtp(
|
|
2488
3419
|
{
|
|
2489
3420
|
email: input.email,
|
|
2490
3421
|
otp: input.code
|
|
@@ -2492,7 +3423,14 @@ function createAuthFlowMachine(client) {
|
|
|
2492
3423
|
{ signal }
|
|
2493
3424
|
);
|
|
2494
3425
|
if (error) throw error;
|
|
2495
|
-
|
|
3426
|
+
if (result.kind === "bootstrap_required") {
|
|
3427
|
+
throw new CapxulError({
|
|
3428
|
+
code: "ACTION_REQUIRED",
|
|
3429
|
+
message: "OTP verified but auth bootstrap is required. Use createAuthBootstrapFlowMachine for product sign-up.",
|
|
3430
|
+
details: { reason: result.reason }
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
return result.session;
|
|
2496
3434
|
}
|
|
2497
3435
|
),
|
|
2498
3436
|
signOut: fromPromise(async () => {
|
|
@@ -2740,6 +3678,327 @@ function emailDomain(email) {
|
|
|
2740
3678
|
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
2741
3679
|
return domain || "unknown";
|
|
2742
3680
|
}
|
|
3681
|
+
var initialContext = {
|
|
3682
|
+
email: null,
|
|
3683
|
+
code: null,
|
|
3684
|
+
username: null,
|
|
3685
|
+
bootstrapToken: null,
|
|
3686
|
+
bootstrapReason: null,
|
|
3687
|
+
session: null,
|
|
3688
|
+
account: null,
|
|
3689
|
+
safe: null,
|
|
3690
|
+
error: null
|
|
3691
|
+
};
|
|
3692
|
+
function createAuthBootstrapFlowMachine(client) {
|
|
3693
|
+
return setup({
|
|
3694
|
+
types: {},
|
|
3695
|
+
actors: {
|
|
3696
|
+
sendOtp: fromPromise(async ({ input, signal }) => {
|
|
3697
|
+
const [error] = await client.auth.sendOtp(
|
|
3698
|
+
{ email: input.email },
|
|
3699
|
+
{ signal }
|
|
3700
|
+
);
|
|
3701
|
+
if (error) throw error;
|
|
3702
|
+
}),
|
|
3703
|
+
verifyOtp: fromPromise(
|
|
3704
|
+
async ({ input, signal }) => {
|
|
3705
|
+
const [error, result] = await client.auth.verifyOtp(
|
|
3706
|
+
{ email: input.email, otp: input.code },
|
|
3707
|
+
{ signal }
|
|
3708
|
+
);
|
|
3709
|
+
if (error) throw error;
|
|
3710
|
+
return result;
|
|
3711
|
+
}
|
|
3712
|
+
),
|
|
3713
|
+
completeBootstrap: fromPromise(async ({ input }) => {
|
|
3714
|
+
const [error, result] = await client.auth.completeBootstrap(input);
|
|
3715
|
+
if (error) throw error;
|
|
3716
|
+
return result;
|
|
3717
|
+
}),
|
|
3718
|
+
signOut: fromPromise(async () => {
|
|
3719
|
+
const [error] = await client.auth.signOut();
|
|
3720
|
+
if (error) throw error;
|
|
3721
|
+
})
|
|
3722
|
+
},
|
|
3723
|
+
actions: {
|
|
3724
|
+
trackOtpRequested: ({ context }) => {
|
|
3725
|
+
if (!context.email) return;
|
|
3726
|
+
track("auth_otp_requested", {
|
|
3727
|
+
email_domain: emailDomain2(context.email)
|
|
3728
|
+
});
|
|
3729
|
+
},
|
|
3730
|
+
trackFailed: ({ event }) => {
|
|
3731
|
+
track("auth_failed", {
|
|
3732
|
+
auth_type: "email_otp",
|
|
3733
|
+
reason: errorFromEvent2(event).code
|
|
3734
|
+
});
|
|
3735
|
+
},
|
|
3736
|
+
trackTimeoutFailed: () => {
|
|
3737
|
+
track("auth_failed", {
|
|
3738
|
+
auth_type: "email_otp",
|
|
3739
|
+
reason: "timeout"
|
|
3740
|
+
});
|
|
3741
|
+
},
|
|
3742
|
+
trackVerified: () => {
|
|
3743
|
+
track("auth_verified", { auth_type: "email_otp" });
|
|
3744
|
+
},
|
|
3745
|
+
trackBootstrapRequired: ({ context }) => {
|
|
3746
|
+
track("auth_verified", {
|
|
3747
|
+
auth_type: "email_otp",
|
|
3748
|
+
auth_mode: context.bootstrapReason ?? "bootstrap_required"
|
|
3749
|
+
});
|
|
3750
|
+
},
|
|
3751
|
+
identifyAndTrack: ({ context }) => {
|
|
3752
|
+
if (!context.session) return;
|
|
3753
|
+
identify(context.session.authUserId, {
|
|
3754
|
+
email_domain: emailDomain2(context.session.email)
|
|
3755
|
+
});
|
|
3756
|
+
track("auth_identified", {
|
|
3757
|
+
email_domain: emailDomain2(context.session.email)
|
|
3758
|
+
});
|
|
3759
|
+
},
|
|
3760
|
+
trackSignedOut: () => {
|
|
3761
|
+
track("auth_signed_out");
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
}).createMachine({
|
|
3765
|
+
id: "authBootstrap",
|
|
3766
|
+
initial: "email",
|
|
3767
|
+
context: initialContext,
|
|
3768
|
+
states: {
|
|
3769
|
+
email: {
|
|
3770
|
+
on: {
|
|
3771
|
+
ENTER_EMAIL: {
|
|
3772
|
+
actions: assign({
|
|
3773
|
+
email: ({ event }) => event.email,
|
|
3774
|
+
error: () => null
|
|
3775
|
+
})
|
|
3776
|
+
},
|
|
3777
|
+
REQUEST_OTP: { target: "sending_otp" }
|
|
3778
|
+
}
|
|
3779
|
+
},
|
|
3780
|
+
sending_otp: {
|
|
3781
|
+
invoke: {
|
|
3782
|
+
src: "sendOtp",
|
|
3783
|
+
input: ({ context }) => ({ email: requireEmail2(context) }),
|
|
3784
|
+
onDone: { target: "otp_requested", actions: "trackOtpRequested" },
|
|
3785
|
+
onError: {
|
|
3786
|
+
target: "otp_requested",
|
|
3787
|
+
actions: [
|
|
3788
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
3789
|
+
"trackFailed"
|
|
3790
|
+
]
|
|
3791
|
+
}
|
|
3792
|
+
},
|
|
3793
|
+
after: {
|
|
3794
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
3795
|
+
target: "otp_requested",
|
|
3796
|
+
actions: [
|
|
3797
|
+
assign({ error: () => timeoutError2("sending_otp") }),
|
|
3798
|
+
"trackTimeoutFailed"
|
|
3799
|
+
]
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
},
|
|
3803
|
+
otp_requested: {
|
|
3804
|
+
on: {
|
|
3805
|
+
ENTER_OTP: {
|
|
3806
|
+
actions: assign({
|
|
3807
|
+
code: ({ event }) => event.code,
|
|
3808
|
+
error: () => null
|
|
3809
|
+
})
|
|
3810
|
+
},
|
|
3811
|
+
VERIFY_OTP: { target: "verifying_otp" },
|
|
3812
|
+
BACK: { target: "email" },
|
|
3813
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
3814
|
+
}
|
|
3815
|
+
},
|
|
3816
|
+
verifying_otp: {
|
|
3817
|
+
invoke: {
|
|
3818
|
+
src: "verifyOtp",
|
|
3819
|
+
input: ({ context }) => ({
|
|
3820
|
+
email: requireEmail2(context),
|
|
3821
|
+
code: requireCode(context)
|
|
3822
|
+
}),
|
|
3823
|
+
onDone: [
|
|
3824
|
+
{
|
|
3825
|
+
guard: ({ event }) => event.output.kind === "existing_member",
|
|
3826
|
+
target: "authenticated",
|
|
3827
|
+
actions: [
|
|
3828
|
+
assign({
|
|
3829
|
+
session: ({ event }) => event.output.session,
|
|
3830
|
+
account: ({ event }) => event.output.kind === "existing_member" ? event.output.account : null,
|
|
3831
|
+
username: ({ event }) => event.output.kind === "existing_member" ? event.output.username : null,
|
|
3832
|
+
safe: ({ event }) => event.output.kind === "existing_member" ? event.output.safe : null,
|
|
3833
|
+
email: () => null,
|
|
3834
|
+
error: () => null
|
|
3835
|
+
}),
|
|
3836
|
+
"trackVerified",
|
|
3837
|
+
"identifyAndTrack"
|
|
3838
|
+
]
|
|
3839
|
+
},
|
|
3840
|
+
{
|
|
3841
|
+
target: "bootstrap_required",
|
|
3842
|
+
actions: [
|
|
3843
|
+
assign({
|
|
3844
|
+
session: ({ event }) => event.output.session,
|
|
3845
|
+
bootstrapToken: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.bootstrapToken : null,
|
|
3846
|
+
bootstrapReason: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.reason : null,
|
|
3847
|
+
username: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.username ?? null : null,
|
|
3848
|
+
email: ({ event }) => event.output.kind === "bootstrap_required" ? event.output.email : null,
|
|
3849
|
+
error: () => null
|
|
3850
|
+
}),
|
|
3851
|
+
"trackVerified",
|
|
3852
|
+
"trackBootstrapRequired"
|
|
3853
|
+
]
|
|
3854
|
+
}
|
|
3855
|
+
],
|
|
3856
|
+
onError: {
|
|
3857
|
+
target: "otp_requested",
|
|
3858
|
+
actions: [
|
|
3859
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
3860
|
+
"trackFailed"
|
|
3861
|
+
]
|
|
3862
|
+
}
|
|
3863
|
+
},
|
|
3864
|
+
after: {
|
|
3865
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
3866
|
+
target: "otp_requested",
|
|
3867
|
+
actions: [
|
|
3868
|
+
assign({ error: () => timeoutError2("verifying_otp") }),
|
|
3869
|
+
"trackTimeoutFailed"
|
|
3870
|
+
]
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
},
|
|
3874
|
+
bootstrap_required: {
|
|
3875
|
+
on: {
|
|
3876
|
+
ENTER_USERNAME: {
|
|
3877
|
+
actions: assign({
|
|
3878
|
+
username: ({ event }) => event.username,
|
|
3879
|
+
error: () => null
|
|
3880
|
+
})
|
|
3881
|
+
},
|
|
3882
|
+
COMPLETE_BOOTSTRAP: { target: "completing_bootstrap" },
|
|
3883
|
+
BACK: { target: "otp_requested" },
|
|
3884
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
3885
|
+
}
|
|
3886
|
+
},
|
|
3887
|
+
completing_bootstrap: {
|
|
3888
|
+
invoke: {
|
|
3889
|
+
src: "completeBootstrap",
|
|
3890
|
+
input: ({ context }) => ({
|
|
3891
|
+
bootstrapToken: requireBootstrapToken(context),
|
|
3892
|
+
username: requireUsername(context)
|
|
3893
|
+
}),
|
|
3894
|
+
onDone: {
|
|
3895
|
+
target: "authenticated",
|
|
3896
|
+
actions: [
|
|
3897
|
+
assign({
|
|
3898
|
+
session: ({ event }) => event.output.session,
|
|
3899
|
+
account: ({ event }) => event.output.account,
|
|
3900
|
+
username: ({ event }) => event.output.username,
|
|
3901
|
+
safe: ({ event }) => event.output.safe,
|
|
3902
|
+
bootstrapToken: () => null,
|
|
3903
|
+
bootstrapReason: () => null,
|
|
3904
|
+
email: () => null,
|
|
3905
|
+
error: () => null
|
|
3906
|
+
}),
|
|
3907
|
+
"identifyAndTrack"
|
|
3908
|
+
]
|
|
3909
|
+
},
|
|
3910
|
+
onError: {
|
|
3911
|
+
target: "bootstrap_required",
|
|
3912
|
+
actions: [
|
|
3913
|
+
assign({ error: ({ event }) => errorFromEvent2(event) }),
|
|
3914
|
+
"trackFailed"
|
|
3915
|
+
]
|
|
3916
|
+
}
|
|
3917
|
+
},
|
|
3918
|
+
after: {
|
|
3919
|
+
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
3920
|
+
target: "bootstrap_required",
|
|
3921
|
+
actions: [
|
|
3922
|
+
assign({ error: () => timeoutError2("completing_bootstrap") }),
|
|
3923
|
+
"trackTimeoutFailed"
|
|
3924
|
+
]
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
},
|
|
3928
|
+
authenticated: {
|
|
3929
|
+
on: {
|
|
3930
|
+
SIGN_OUT: { target: "signing_out" }
|
|
3931
|
+
}
|
|
3932
|
+
},
|
|
3933
|
+
signing_out: {
|
|
3934
|
+
invoke: {
|
|
3935
|
+
src: "signOut",
|
|
3936
|
+
onDone: {
|
|
3937
|
+
target: "email",
|
|
3938
|
+
actions: [
|
|
3939
|
+
assign(() => initialContext),
|
|
3940
|
+
"trackSignedOut"
|
|
3941
|
+
]
|
|
3942
|
+
},
|
|
3943
|
+
onError: {
|
|
3944
|
+
target: "error",
|
|
3945
|
+
actions: assign({ error: ({ event }) => errorFromEvent2(event) })
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
},
|
|
3949
|
+
error: {
|
|
3950
|
+
on: {
|
|
3951
|
+
RESET: { target: "email", actions: assign(() => initialContext) }
|
|
3952
|
+
}
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
});
|
|
3956
|
+
}
|
|
3957
|
+
function requireEmail2(context) {
|
|
3958
|
+
if (!context.email) {
|
|
3959
|
+
throw Errors.invalidInput("email", "Auth bootstrap requires an email.");
|
|
3960
|
+
}
|
|
3961
|
+
return context.email;
|
|
3962
|
+
}
|
|
3963
|
+
function requireCode(context) {
|
|
3964
|
+
if (!context.code) {
|
|
3965
|
+
throw Errors.invalidInput("code", "Auth bootstrap requires an OTP code.");
|
|
3966
|
+
}
|
|
3967
|
+
return context.code;
|
|
3968
|
+
}
|
|
3969
|
+
function requireBootstrapToken(context) {
|
|
3970
|
+
if (!context.bootstrapToken) {
|
|
3971
|
+
throw Errors.invalidInput(
|
|
3972
|
+
"bootstrapToken",
|
|
3973
|
+
"Auth bootstrap requires a continuation token."
|
|
3974
|
+
);
|
|
3975
|
+
}
|
|
3976
|
+
return context.bootstrapToken;
|
|
3977
|
+
}
|
|
3978
|
+
function requireUsername(context) {
|
|
3979
|
+
if (!context.username) {
|
|
3980
|
+
throw Errors.invalidInput("username", "Auth bootstrap requires a username.");
|
|
3981
|
+
}
|
|
3982
|
+
return context.username;
|
|
3983
|
+
}
|
|
3984
|
+
function errorFromEvent2(event) {
|
|
3985
|
+
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
3986
|
+
if (cause instanceof CapxulError || cause instanceof CapxulError2) {
|
|
3987
|
+
return cause;
|
|
3988
|
+
}
|
|
3989
|
+
return Errors.providerError("auth", "bootstrap", cause);
|
|
3990
|
+
}
|
|
3991
|
+
function timeoutError2(state) {
|
|
3992
|
+
return Errors.providerError(
|
|
3993
|
+
"auth",
|
|
3994
|
+
"bootstrap",
|
|
3995
|
+
new Error(`timeout: ${state} exceeded ${FLOW_INVOKE_TIMEOUT_MS}ms`)
|
|
3996
|
+
);
|
|
3997
|
+
}
|
|
3998
|
+
function emailDomain2(email) {
|
|
3999
|
+
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
4000
|
+
return domain || "unknown";
|
|
4001
|
+
}
|
|
2743
4002
|
function createProvisioningMachine(client) {
|
|
2744
4003
|
return setup({
|
|
2745
4004
|
types: {},
|
|
@@ -2767,7 +4026,7 @@ function createProvisioningMachine(client) {
|
|
|
2767
4026
|
const provider = context.input?.signerProvider;
|
|
2768
4027
|
if (!provider) return;
|
|
2769
4028
|
track("provisioning_safe_created", {
|
|
2770
|
-
safe_address: provider.
|
|
4029
|
+
safe_address: deriveSafeAddress(provider.signerAddress)
|
|
2771
4030
|
});
|
|
2772
4031
|
}
|
|
2773
4032
|
}
|
|
@@ -2812,13 +4071,13 @@ function createProvisioningMachine(client) {
|
|
|
2812
4071
|
},
|
|
2813
4072
|
onError: {
|
|
2814
4073
|
target: "error",
|
|
2815
|
-
actions: assign({ error: ({ event }) =>
|
|
4074
|
+
actions: assign({ error: ({ event }) => errorFromEvent3(event) })
|
|
2816
4075
|
}
|
|
2817
4076
|
},
|
|
2818
4077
|
after: {
|
|
2819
4078
|
[FLOW_INVOKE_TIMEOUT_MS]: {
|
|
2820
4079
|
target: "error",
|
|
2821
|
-
actions: assign({ error: () =>
|
|
4080
|
+
actions: assign({ error: () => timeoutError3() })
|
|
2822
4081
|
}
|
|
2823
4082
|
}
|
|
2824
4083
|
},
|
|
@@ -2836,7 +4095,7 @@ function createProvisioningMachine(client) {
|
|
|
2836
4095
|
* this payload on its `onDone` transition and branches via guards
|
|
2837
4096
|
* on `event.output.error`.
|
|
2838
4097
|
*/
|
|
2839
|
-
output: ({ context }) => context.error ? { error: context.error } : context.account ? { account: context.account } : { error:
|
|
4098
|
+
output: ({ context }) => context.error ? { error: context.error } : context.account ? { account: context.account } : { error: timeoutError3() }
|
|
2840
4099
|
});
|
|
2841
4100
|
}
|
|
2842
4101
|
function requireProvisionInput(context) {
|
|
@@ -2848,13 +4107,13 @@ function requireProvisionInput(context) {
|
|
|
2848
4107
|
}
|
|
2849
4108
|
return context.input;
|
|
2850
4109
|
}
|
|
2851
|
-
function
|
|
4110
|
+
function errorFromEvent3(event) {
|
|
2852
4111
|
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
2853
4112
|
if (cause instanceof CapxulError) return cause;
|
|
2854
4113
|
if (cause instanceof CapxulError2) return cause;
|
|
2855
4114
|
return Errors.providerError("provisioning", "flow", cause);
|
|
2856
4115
|
}
|
|
2857
|
-
function
|
|
4116
|
+
function timeoutError3() {
|
|
2858
4117
|
return Errors.providerError(
|
|
2859
4118
|
"provisioning",
|
|
2860
4119
|
"flow",
|
|
@@ -2947,7 +4206,7 @@ function createOnboardingFlowMachine(client) {
|
|
|
2947
4206
|
error: ({ event }) => extractChildErrorOrFallback(event)
|
|
2948
4207
|
}),
|
|
2949
4208
|
assignChildThrown: assign({
|
|
2950
|
-
error: ({ event }) =>
|
|
4209
|
+
error: ({ event }) => errorFromEvent4(event)
|
|
2951
4210
|
}),
|
|
2952
4211
|
assignAccountFromChild: assign({
|
|
2953
4212
|
account: ({ event }) => extractChildAccountOrNull(event)
|
|
@@ -3109,7 +4368,7 @@ function extractChildAccountOrNull(event) {
|
|
|
3109
4368
|
if (output && "account" in output && output.account) return output.account;
|
|
3110
4369
|
return null;
|
|
3111
4370
|
}
|
|
3112
|
-
function
|
|
4371
|
+
function errorFromEvent4(event) {
|
|
3113
4372
|
const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
|
|
3114
4373
|
if (cause instanceof CapxulError) return cause;
|
|
3115
4374
|
if (cause instanceof CapxulError2) return cause;
|
|
@@ -3129,7 +4388,7 @@ function createCapxulClient(config = {}) {
|
|
|
3129
4388
|
tokenTransfers: createTokenTransfersClient(config),
|
|
3130
4389
|
withdrawals: createWithdrawalsClient(config),
|
|
3131
4390
|
documents: createDocumentsClient(),
|
|
3132
|
-
subAccounts: createSubAccountsClient(),
|
|
4391
|
+
subAccounts: createSubAccountsClient(config),
|
|
3133
4392
|
virtualAccounts: createVirtualAccountsClient(),
|
|
3134
4393
|
virtualCards: createVirtualCardsClient(),
|
|
3135
4394
|
externalAccounts: createExternalAccountsClient(config),
|
|
@@ -3141,6 +4400,7 @@ function createCapxulClient(config = {}) {
|
|
|
3141
4400
|
const client = clientWithoutFlows;
|
|
3142
4401
|
client.flows = {
|
|
3143
4402
|
auth: () => createAuthFlowMachine(client),
|
|
4403
|
+
authBootstrap: () => createAuthBootstrapFlowMachine(client),
|
|
3144
4404
|
onboarding: () => createOnboardingFlowMachine(client),
|
|
3145
4405
|
provisioning: () => createProvisioningMachine(client)
|
|
3146
4406
|
};
|
|
@@ -3245,4 +4505,81 @@ function isWebhookEvent(value) {
|
|
|
3245
4505
|
return typeof candidate.id === "string" && typeof candidate.type === "string" && typeof candidate.createdAt === "string" && (candidate.operationId === void 0 || typeof candidate.operationId === "string") && (candidate.correlationId === void 0 || typeof candidate.correlationId === "string") && !!candidate.data && typeof candidate.data === "object" && !Array.isArray(candidate.data);
|
|
3246
4506
|
}
|
|
3247
4507
|
|
|
3248
|
-
|
|
4508
|
+
// src/core/auth-service.ts
|
|
4509
|
+
var AuthService = class {
|
|
4510
|
+
authClient;
|
|
4511
|
+
sessionStore;
|
|
4512
|
+
config;
|
|
4513
|
+
constructor(config = {}) {
|
|
4514
|
+
this.config = config;
|
|
4515
|
+
this.sessionStore = config.auth?.sessionStore ?? createMemorySessionStore2();
|
|
4516
|
+
this.authClient = createAuthClient({
|
|
4517
|
+
...config,
|
|
4518
|
+
auth: { ...config.auth, sessionStore: this.sessionStore }
|
|
4519
|
+
});
|
|
4520
|
+
}
|
|
4521
|
+
async sendOtp(email) {
|
|
4522
|
+
const [err] = await this.authClient.sendOtp({ email });
|
|
4523
|
+
if (err) throw err;
|
|
4524
|
+
}
|
|
4525
|
+
async verifyOtp(email, otp) {
|
|
4526
|
+
const [err, result] = await this.authClient.verifyOtp({ email, otp });
|
|
4527
|
+
if (err) throw err;
|
|
4528
|
+
return result;
|
|
4529
|
+
}
|
|
4530
|
+
async completeBootstrap(params, signer) {
|
|
4531
|
+
if (signer) {
|
|
4532
|
+
const tempClient = createAuthClient({
|
|
4533
|
+
...this.config,
|
|
4534
|
+
signer
|
|
4535
|
+
});
|
|
4536
|
+
const [err2, result2] = await tempClient.completeBootstrap(params);
|
|
4537
|
+
if (err2) throw err2;
|
|
4538
|
+
return result2;
|
|
4539
|
+
}
|
|
4540
|
+
const [err, result] = await this.authClient.completeBootstrap(params);
|
|
4541
|
+
if (err) throw err;
|
|
4542
|
+
return result;
|
|
4543
|
+
}
|
|
4544
|
+
/**
|
|
4545
|
+
* Clears the persisted session and, when a transport was pre-injected,
|
|
4546
|
+
* drops the cached auth header.
|
|
4547
|
+
*
|
|
4548
|
+
* **Transport safety note:** `clearAuth()` is only invoked when
|
|
4549
|
+
* `config._transport` was supplied at construction (e.g. by the React
|
|
4550
|
+
* provider). If `AuthService` is instantiated directly in a Node/CLI
|
|
4551
|
+
* context without an injected transport, the transport-side auth cache
|
|
4552
|
+
* is the caller's responsibility.
|
|
4553
|
+
*/
|
|
4554
|
+
async signOut() {
|
|
4555
|
+
this.sessionStore.clear();
|
|
4556
|
+
this.config._transport?.clearAuth();
|
|
4557
|
+
}
|
|
4558
|
+
async getSession() {
|
|
4559
|
+
const [err, session] = await this.authClient.getSession();
|
|
4560
|
+
if (err) throw err;
|
|
4561
|
+
return session;
|
|
4562
|
+
}
|
|
4563
|
+
};
|
|
4564
|
+
function createMemorySessionStore2() {
|
|
4565
|
+
let current = null;
|
|
4566
|
+
return {
|
|
4567
|
+
get: () => current,
|
|
4568
|
+
set: (session) => {
|
|
4569
|
+
current = session;
|
|
4570
|
+
},
|
|
4571
|
+
clear: () => {
|
|
4572
|
+
current = null;
|
|
4573
|
+
}
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
var SignerProvisioner = class {
|
|
4577
|
+
provision() {
|
|
4578
|
+
const privateKey = generatePrivateKey();
|
|
4579
|
+
const signer = privateKeyToAccount(privateKey);
|
|
4580
|
+
const safeAddress = deriveSafeAddress(signer.address);
|
|
4581
|
+
return { signer, safeAddress };
|
|
4582
|
+
}
|
|
4583
|
+
};
|
|
4584
|
+
|
|
4585
|
+
export { AuthService, CapxulError, SignerProvisioner, createAuthBootstrapFlowMachine, createAuthFlowMachine, createCapxulClient, createLocalSigner, createOnboardingFlowMachine, createProvisioningMachine as createProvisioningFlowMachine, makeHttpTransport, matchAction, matchError, matchStatus, resolvePaymentToken, toAccountId, toApiKeyId, toBalanceLedgerEntryId, toDocumentId, toEmail, toExternalAccountId, toKybProfileId, toKycProfileId, toMemberId, toOperationId, toOrganizationId, toPaymentId, toPhoneNumber, toSafeId, toSubAccountId, toTokenTransferId, toTransferId, toTreasuryId, toUsername, toVirtualAccountId, toVirtualCardId, toWebhookEndpointId, toWebhookEventId, toWithdrawalId, tryCatch, verifyWebhook };
|