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