@capxul/sdk 0.1.0-alpha.9 → 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/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
- "mem",
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.data) {
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.data.query(api.externalAccounts.queries.retrievePersonal, {
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.data) {
442
+ if (!config._data) {
287
443
  return stub("externalAccounts.remove");
288
444
  }
289
445
  const [err] = await tryCatch(
290
- config.data.mutation(api.externalAccounts.mutations.removePersonal, {
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.data) {
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.data.mutation(
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.data) {
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.data.query(api.externalAccounts.queries.listPersonal, {
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.data) {
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.data.query(api.externalAccounts.queries.retrievePersonal, {
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.data) {
757
+ if (!config._data) {
416
758
  return stub("accounts.externalAccounts.remove");
417
759
  }
418
760
  const [err] = await tryCatch(
419
- config.data.mutation(api.externalAccounts.mutations.removePersonal, {
761
+ config._data.mutation(api.externalAccounts.mutations.removePersonal, {
420
762
  externalAccountId
421
763
  })
422
764
  );
@@ -430,14 +772,162 @@ function createAccountExternalAccountsClient(config) {
430
772
  }
431
773
  };
432
774
  }
775
+ function createAccountSubAccountsClient(config) {
776
+ return {
777
+ create: async (input) => {
778
+ if (!config._data) {
779
+ return stub(
780
+ "accounts.subAccounts.create"
781
+ );
782
+ }
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
+ }
433
923
  function createAccountsClient(config = {}) {
434
924
  return {
435
925
  retrieve: async (accountId) => {
436
- if (!config.data) {
926
+ if (!config._data) {
437
927
  return stub("accounts.retrieve");
438
928
  }
439
929
  try {
440
- const account = await config.data.query(
930
+ const account = await config._data.query(
441
931
  api.openfort.queries.getMyAccount,
442
932
  {}
443
933
  );
@@ -461,7 +951,7 @@ function createAccountsClient(config = {}) {
461
951
  },
462
952
  lookup: async () => stub("accounts.lookup"),
463
953
  update: async (input) => {
464
- if (!config.data) {
954
+ if (!config._data) {
465
955
  return stub("accounts.update");
466
956
  }
467
957
  if (input.countryCode !== void 0) {
@@ -475,7 +965,7 @@ function createAccountsClient(config = {}) {
475
965
  ];
476
966
  }
477
967
  try {
478
- const current = await config.data.query(
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.data.mutation(api.openfort.mutations.updateProfile, {
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.data.query(
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.data) {
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.data.mutation(
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.safeAddress
1021
+ safeAddress: deriveSafeAddress(input.signerProvider.signerAddress)
532
1022
  }
533
1023
  );
534
- const account = await config.data.query(
1024
+ const account = await config._data.query(
535
1025
  api.openfort.queries.getMyAccount,
536
1026
  {}
537
1027
  );
@@ -554,177 +1044,99 @@ function createAccountsClient(config = {}) {
554
1044
  },
555
1045
  safes: {
556
1046
  retrieve: async (safeId) => {
557
- if (!config.data) {
558
- return stub("accounts.safes.retrieve");
559
- }
560
- try {
561
- const safe = await config.data.query(
562
- api.safe.queries.retrieveAccountSafe,
563
- { safeId }
564
- );
565
- if (!safe) {
566
- return [
567
- new CapxulError({
568
- code: "NOT_FOUND",
569
- message: `safe ${safeId} not found`
570
- }),
571
- null
572
- ];
573
- }
574
- return [null, safe];
575
- } catch (cause) {
576
- return [
577
- fromConvexError(cause),
578
- null
579
- ];
580
- }
581
- }
582
- },
583
- kycProfiles: {
584
- create: async () => stub("accounts.kycProfiles.create"),
585
- retrieve: async () => stub("accounts.kycProfiles.retrieve")
586
- },
587
- 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
- },
594
- balanceLedger: {
595
- list: async () => stub(
596
- "accounts.balanceLedger.list"
597
- ),
598
- retrieve: async () => stub(
599
- "accounts.balanceLedger.retrieve"
600
- )
601
- }
602
- };
603
- }
604
-
605
- // src/core/api-keys.ts
606
- function createApiKeysClient() {
607
- return {
608
- create: async () => stub("apiKeys.create"),
609
- retrieve: async () => stub("apiKeys.retrieve"),
610
- list: async () => stub("apiKeys.list"),
611
- revoke: async () => stub("apiKeys.revoke")
612
- };
613
- }
614
-
615
- // ../config/src/chain.ts
616
- var CAPXUL_PAYMENTS_ADDRESS = "0xe740ea65521edc9bef0ea75d30b5334711db99f4";
617
- var TEST_USDC_ADDRESS = "0xf09fcbb6df9f8f918e58f9c8ab15a76ade862b77";
618
- var CAPXUL_API_BASE_URL = "https://elated-oyster-269.convex.site";
619
-
620
- // ../config/src/timing.ts
621
- var FLOW_INVOKE_TIMEOUT_MS = 3e4;
622
- var WEBHOOK_FRESHNESS_WINDOW_MS = 5 * 60 * 1e3;
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";
1047
+ if (!config._data) {
1048
+ return stub("accounts.safes.retrieve");
1049
+ }
1050
+ try {
1051
+ const safe = await config._data.query(
1052
+ api.safe.queries.retrieveAccountSafe,
1053
+ { safeId }
1054
+ );
1055
+ if (!safe) {
1056
+ return [
1057
+ new CapxulError({
1058
+ code: "NOT_FOUND",
1059
+ message: `safe ${safeId} not found`
1060
+ }),
1061
+ null
1062
+ ];
1063
+ }
1064
+ return [null, safe];
1065
+ } catch (cause) {
1066
+ return [
1067
+ fromConvexError(cause),
1068
+ null
1069
+ ];
1070
+ }
1071
+ }
1072
+ },
1073
+ kycProfiles: {
1074
+ create: async () => stub("accounts.kycProfiles.create"),
1075
+ retrieve: async () => stub("accounts.kycProfiles.retrieve")
1076
+ },
1077
+ externalAccounts: createAccountExternalAccountsClient(config),
1078
+ subAccounts: createAccountSubAccountsClient(config),
1079
+ balanceLedger: {
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
+ }
1122
+ }
1123
+ };
1124
+ }
718
1125
 
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");
1126
+ // src/core/api-keys.ts
1127
+ function createApiKeysClient() {
1128
+ return {
1129
+ create: async () => stub("apiKeys.create"),
1130
+ retrieve: async () => stub("apiKeys.retrieve"),
1131
+ list: async () => stub("apiKeys.list"),
1132
+ revoke: async () => stub("apiKeys.revoke")
1133
+ };
1134
+ }
1135
+ function createDefaultDataClient(convexUrl, jwt) {
1136
+ const client = new browser.ConvexHttpClient(convexUrl);
1137
+ client.setAuth(jwt);
1138
+ return client;
724
1139
  }
725
- roleKeyFromLabel("OWNER");
726
- roleKeyFromLabel("FINANCE_MANAGER");
727
- roleKeyFromLabel("TEAM_LEAD");
728
1140
 
729
1141
  // src/transport.ts
730
1142
  function makeHttpTransport(config) {
@@ -1055,7 +1467,7 @@ function readNonEmptyString(value) {
1055
1467
 
1056
1468
  // src/core/auth.ts
1057
1469
  function createAuthClient(config = {}) {
1058
- let dataClient = config.data ?? null;
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 (config.auth?.createDataClient) {
1526
+ if (!dataClient) {
1115
1527
  try {
1116
- dataClient = await config.auth.createDataClient(session);
1117
- mutableConfig(config).data = dataClient;
1118
- transport.markAuthenticated({ dataClient });
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,7 +1547,15 @@ 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
+ }
1129
1557
  }
1558
+ transport.markAuthenticated({ dataClient });
1130
1559
  if (!dataClient) {
1131
1560
  return [
1132
1561
  new CapxulError({
@@ -1154,7 +1583,7 @@ function createAuthClient(config = {}) {
1154
1583
  },
1155
1584
  completeBootstrap: async (input) => {
1156
1585
  const session = sessionStore.get();
1157
- const data = dataClient ?? config.data;
1586
+ const data = dataClient ?? config._data;
1158
1587
  if (!session || !data) {
1159
1588
  return [
1160
1589
  new CapxulError({
@@ -1164,23 +1593,29 @@ function createAuthClient(config = {}) {
1164
1593
  null
1165
1594
  ];
1166
1595
  }
1167
- if (input.signerProvider.kind !== "local-private-key") {
1596
+ const signerAddress = config.signer?.address;
1597
+ if (!signerAddress) {
1168
1598
  return [
1169
1599
  new CapxulError({
1170
1600
  code: "INVALID_INPUT",
1171
- message: "completeBootstrap currently supports local-private-key signer providers only."
1601
+ message: "completeBootstrap requires a signer to be configured on the client."
1172
1602
  }),
1173
1603
  null
1174
1604
  ];
1175
1605
  }
1176
1606
  try {
1607
+ const safeAddress = deriveSafeAddress(signerAddress);
1177
1608
  const result = await data.mutation(api.authBootstrap.completeBootstrap, {
1178
1609
  bootstrapToken: input.bootstrapToken,
1179
1610
  sessionToken: session.token,
1180
1611
  username: input.username,
1181
1612
  displayName: input.displayName,
1182
1613
  countryCode: input.countryCode,
1183
- signerProvider: input.signerProvider
1614
+ signerProvider: {
1615
+ kind: "local-private-key",
1616
+ signerAddress,
1617
+ safeAddress
1618
+ }
1184
1619
  });
1185
1620
  return [null, { kind: "authenticated", session, ...result }];
1186
1621
  } catch (cause) {
@@ -1194,7 +1629,7 @@ function createAuthClient(config = {}) {
1194
1629
  signOut: async () => {
1195
1630
  sessionStore.clear();
1196
1631
  dataClient = null;
1197
- mutableConfig(config).data = void 0;
1632
+ mutableConfig(config)._data = void 0;
1198
1633
  const transport = getTransport();
1199
1634
  transport?.clearAuth();
1200
1635
  return [null, void 0];
@@ -1265,6 +1700,9 @@ async function postBetterAuth(transport, path, body, code, signal) {
1265
1700
  }
1266
1701
  return [null, text ? JSON.parse(text) : void 0];
1267
1702
  } catch (cause) {
1703
+ if (cause instanceof CapxulError) {
1704
+ return [cause, null];
1705
+ }
1268
1706
  return [
1269
1707
  new CapxulError({
1270
1708
  code: "NETWORK_ERROR",
@@ -1303,7 +1741,7 @@ function parseBetterAuthError(text) {
1303
1741
  }
1304
1742
  }
1305
1743
  function isCapxulErrorCode2(code) {
1306
- 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";
1307
1745
  }
1308
1746
  async function exchangeConvexToken(transport, config, token, signal) {
1309
1747
  const path = config.auth?.convexTokenUrl ?? "/convex/token";
@@ -1333,6 +1771,9 @@ async function exchangeConvexToken(transport, config, token, signal) {
1333
1771
  }
1334
1772
  return [null, body.token];
1335
1773
  } catch (cause) {
1774
+ if (cause instanceof CapxulError) {
1775
+ return [cause, null];
1776
+ }
1336
1777
  return [
1337
1778
  new CapxulError({
1338
1779
  code: "NETWORK_ERROR",
@@ -1369,11 +1810,11 @@ function createOrgDocumentsClient() {
1369
1810
  function createMeClient(config = {}) {
1370
1811
  return {
1371
1812
  get: async () => {
1372
- if (!config.data) {
1813
+ if (!config._data) {
1373
1814
  return stub("me.get");
1374
1815
  }
1375
1816
  try {
1376
- const account = await config.data.query(
1817
+ const account = await config._data.query(
1377
1818
  api.openfort.queries.getMyAccount,
1378
1819
  {}
1379
1820
  );
@@ -1383,7 +1824,7 @@ function createMeClient(config = {}) {
1383
1824
  }
1384
1825
  },
1385
1826
  update: async (input) => {
1386
- if (!config.data) {
1827
+ if (!config._data) {
1387
1828
  return stub("me.update");
1388
1829
  }
1389
1830
  if (input.countryCode !== void 0) {
@@ -1397,11 +1838,11 @@ function createMeClient(config = {}) {
1397
1838
  ];
1398
1839
  }
1399
1840
  try {
1400
- await config.data.mutation(api.openfort.mutations.updateProfile, {
1841
+ await config._data.mutation(api.openfort.mutations.updateProfile, {
1401
1842
  displayName: input.name,
1402
1843
  username: input.username
1403
1844
  });
1404
- const account = await config.data.query(
1845
+ const account = await config._data.query(
1405
1846
  api.openfort.queries.getMyAccount,
1406
1847
  {}
1407
1848
  );
@@ -1416,11 +1857,11 @@ function createMeClient(config = {}) {
1416
1857
  // src/core/operations.ts
1417
1858
  function createOperationsClient(config = {}) {
1418
1859
  const retrieve = async (operationId) => {
1419
- if (!config.data) {
1860
+ if (!config._data) {
1420
1861
  return stub("operations.retrieve");
1421
1862
  }
1422
1863
  try {
1423
- const operation = await config.data.query(api.operations.queries.retrieve, {
1864
+ const operation = await config._data.query(api.operations.queries.retrieve, {
1424
1865
  operationId
1425
1866
  });
1426
1867
  if (!operation) {
@@ -1437,7 +1878,7 @@ function createOperationsClient(config = {}) {
1437
1878
  return {
1438
1879
  retrieve,
1439
1880
  wait: async (operationId, input = {}) => {
1440
- if (!config.data) {
1881
+ if (!config._data) {
1441
1882
  return stub("operations.wait");
1442
1883
  }
1443
1884
  const until = new Set(
@@ -1472,49 +1913,22 @@ function toTokenUnits(value, decimals = 6) {
1472
1913
  return viem.parseUnits(value, decimals);
1473
1914
  }
1474
1915
 
1475
- // src/internal/payment-token.ts
1476
- function resolvePaymentTokenAddress(currency) {
1916
+ // src/core/token-registry.ts
1917
+ function resolvePaymentToken(currency) {
1477
1918
  const normalized = currency.trim().toUpperCase();
1478
1919
  if (normalized === "USD" || normalized === "USDC") {
1479
- return TEST_USDC_ADDRESS.toLowerCase();
1920
+ return {
1921
+ address: TEST_USDC_ADDRESS.toLowerCase(),
1922
+ decimals: 6,
1923
+ symbol: "USDC"
1924
+ };
1480
1925
  }
1481
1926
  throw new CapxulError({
1482
- code: "NETWORK_ERROR",
1483
- message: `Currency ${currency} is not configured for on-chain payment submission.`,
1927
+ code: "NOT_IMPLEMENTED",
1928
+ message: `Currency ${currency} is not yet supported by the token registry.`,
1484
1929
  details: { currency: normalized }
1485
1930
  });
1486
1931
  }
1487
- async function buildSafeAccount(signer, chain) {
1488
- try {
1489
- const publicClient = viem.createPublicClient({
1490
- chain: chains.baseSepolia,
1491
- transport: viem.http(chain.rpcUrl)
1492
- });
1493
- return await accounts$1.toSafeSmartAccount({
1494
- client: publicClient,
1495
- entryPoint: { address: accountAbstraction.entryPoint07Address, version: "0.7" },
1496
- version: "1.4.1",
1497
- owners: [signer],
1498
- saltNonce: computeSaltNonce(signer.address),
1499
- safeSingletonAddress: SAFE_L2_SINGLETON,
1500
- safeProxyFactoryAddress: SAFE_PROXY_FACTORY,
1501
- safeModuleSetupAddress: SAFE_MODULE_SETUP,
1502
- safe4337ModuleAddress: SAFE_4337_MODULE,
1503
- safeModules: [],
1504
- setupTransactions: []
1505
- });
1506
- } catch (cause) {
1507
- throw new CapxulError({
1508
- code: "NETWORK_ERROR",
1509
- message: cause instanceof Error ? cause.message : String(cause),
1510
- cause,
1511
- details: { chainId: chain.chainId }
1512
- });
1513
- }
1514
- }
1515
- function computeSaltNonce(ownerAddress) {
1516
- return BigInt(`0x${ownerAddress.toLowerCase().slice(2).padEnd(64, "0")}`);
1517
- }
1518
1932
  function createCapxulBundler(config) {
1519
1933
  const paymaster = accountAbstraction.createPaymasterClient({
1520
1934
  transport: viem.http(config.rpcUrl)
@@ -1621,13 +2035,13 @@ async function transferAsOwner(config, params) {
1621
2035
  function createPaymentsClient(config = {}) {
1622
2036
  return {
1623
2037
  create: async (input) => {
1624
- if (!config.data || !config.signer || !config.signing) {
2038
+ if (!config._data || !config.signer || !config.signing) {
1625
2039
  return stub("payments.create");
1626
2040
  }
1627
2041
  let created = null;
1628
2042
  let submitted = null;
1629
2043
  try {
1630
- created = await config.data.mutation(api.payments.mutations.create, {
2044
+ created = await config._data.mutation(api.payments.mutations.create, {
1631
2045
  to: input.to,
1632
2046
  amount: input.amount,
1633
2047
  reference: input.reference,
@@ -1635,15 +2049,21 @@ function createPaymentsClient(config = {}) {
1635
2049
  source: input.source
1636
2050
  });
1637
2051
  if (!created) {
1638
- return [new CapxulError({
1639
- code: "NETWORK_ERROR",
1640
- message: "payments.create returned no payment resource"
1641
- }), null];
2052
+ return [
2053
+ new CapxulError({
2054
+ code: "NETWORK_ERROR",
2055
+ message: "payments.create returned no payment resource"
2056
+ }),
2057
+ null
2058
+ ];
1642
2059
  }
1643
2060
  if (created.status !== "processing" || created.operation.status !== "processing") {
1644
2061
  return [null, created];
1645
2062
  }
1646
- const currentSigner = await config.data.query(api.safe.queries.getMySignerAddress, {});
2063
+ const currentSigner = await config._data.query(
2064
+ api.safe.queries.getMySignerAddress,
2065
+ {}
2066
+ );
1647
2067
  if (!currentSigner?.address) {
1648
2068
  throw new CapxulError({
1649
2069
  code: "PERMISSION_DENIED",
@@ -1662,9 +2082,12 @@ function createPaymentsClient(config = {}) {
1662
2082
  }
1663
2083
  });
1664
2084
  }
1665
- const submission = await config.data.query(api.payments.queries.prepareSubmission, {
1666
- paymentId: created.id
1667
- });
2085
+ const submission = await config._data.query(
2086
+ api.payments.queries.prepareSubmission,
2087
+ {
2088
+ paymentId: created.id
2089
+ }
2090
+ );
1668
2091
  if (!submission?.recipientAddress) {
1669
2092
  throw new CapxulError({
1670
2093
  code: "NETWORK_ERROR",
@@ -1672,15 +2095,16 @@ function createPaymentsClient(config = {}) {
1672
2095
  details: { paymentId: created.id }
1673
2096
  });
1674
2097
  }
2098
+ const token = resolvePaymentToken(submission.amount.currency);
1675
2099
  const transfer = await transferAsOwner(
1676
2100
  {
1677
2101
  signer: config.signer,
1678
2102
  signing: config.signing
1679
2103
  },
1680
2104
  {
1681
- tokenAddress: resolvePaymentTokenAddress(submission.amount.currency),
2105
+ tokenAddress: token.address,
1682
2106
  recipientAddress: submission.recipientAddress,
1683
- amount: toTokenUnits(submission.amount.value, 6)
2107
+ amount: toTokenUnits(submission.amount.value, token.decimals)
1684
2108
  }
1685
2109
  );
1686
2110
  if (!transfer.success) {
@@ -1698,7 +2122,7 @@ function createPaymentsClient(config = {}) {
1698
2122
  txHash: transfer.txHash,
1699
2123
  userOpHash: transfer.userOpHash
1700
2124
  };
1701
- await config.data.mutation(api.payments.mutations.recordSubmitted, {
2125
+ await config._data.mutation(api.payments.mutations.recordSubmitted, {
1702
2126
  paymentId: created.id,
1703
2127
  txHash: transfer.txHash,
1704
2128
  userOpHash: transfer.userOpHash,
@@ -1708,43 +2132,65 @@ function createPaymentsClient(config = {}) {
1708
2132
  } catch (cause) {
1709
2133
  const error = mapCreateError(fromConvexError(cause));
1710
2134
  if (created?.id && created.status === "processing" && !submitted) {
1711
- await bestEffortMarkFailed({ data: config.data }, created.id, error);
2135
+ await bestEffortMarkFailed({ _data: config._data }, created.id, error);
1712
2136
  }
1713
2137
  if (submitted && created?.id) {
1714
- return [new CapxulError({
1715
- code: "NETWORK_ERROR",
1716
- message: "Payment was submitted on-chain, but backend submission tracking failed.",
1717
- cause,
1718
- details: {
1719
- paymentId: created.id,
1720
- txHash: submitted.txHash,
1721
- userOpHash: submitted.userOpHash
1722
- }
1723
- }), null];
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
+ ];
1724
2151
  }
1725
2152
  return [error, null];
1726
2153
  }
1727
2154
  },
1728
2155
  retrieve: async (paymentId) => {
1729
- if (!config.data) {
2156
+ if (!config._data) {
1730
2157
  return stub("payments.retrieve");
1731
2158
  }
1732
2159
  try {
1733
- const payment = await config.data.query(api.payments.queries.retrieve, {
1734
- paymentId
1735
- });
2160
+ const payment = await config._data.query(
2161
+ api.payments.queries.retrieve,
2162
+ {
2163
+ paymentId
2164
+ }
2165
+ );
1736
2166
  if (!payment) {
1737
- return [new CapxulError({
1738
- code: "NOT_FOUND",
1739
- message: `payment ${paymentId} not found`
1740
- }), null];
2167
+ return [
2168
+ new CapxulError({
2169
+ code: "NOT_FOUND",
2170
+ message: `payment ${paymentId} not found`
2171
+ }),
2172
+ null
2173
+ ];
1741
2174
  }
1742
2175
  return [null, payment];
1743
2176
  } catch (cause) {
1744
2177
  return [fromConvexError(cause), null];
1745
2178
  }
1746
2179
  },
1747
- list: async () => stub("payments.list")
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
+ }
1748
2194
  };
1749
2195
  }
1750
2196
  function createOrgPaymentsClient() {
@@ -1758,7 +2204,7 @@ function createOrgPaymentsClient() {
1758
2204
  }
1759
2205
  async function bestEffortMarkFailed(config, paymentId, error) {
1760
2206
  try {
1761
- await config.data.mutation(api.payments.mutations.markFailed, {
2207
+ await config._data.mutation(api.payments.mutations.markFailed, {
1762
2208
  paymentId,
1763
2209
  errorCode: error.code,
1764
2210
  errorMessage: error.message,
@@ -1815,11 +2261,11 @@ function createOrgTransfersClient() {
1815
2261
  function createWithdrawalsClient(config = {}) {
1816
2262
  return {
1817
2263
  create: async (input) => {
1818
- if (!config.data) {
2264
+ if (!config._data) {
1819
2265
  return stub("withdrawals.create");
1820
2266
  }
1821
2267
  const [createErr, createdRaw] = await tryCatch(
1822
- config.data.mutation(api.withdrawals.mutations.create, {
2268
+ config._data.mutation(api.withdrawals.mutations.create, {
1823
2269
  amount: input.amount,
1824
2270
  destination: {
1825
2271
  externalAccountId: input.destination.externalAccountId
@@ -1849,18 +2295,18 @@ function createWithdrawalsClient(config = {}) {
1849
2295
  return [null, created];
1850
2296
  }
1851
2297
  const [signerErr, currentSigner] = await tryCatch(
1852
- config.data.query(api.safe.queries.getMySignerAddress, {})
2298
+ config._data.query(api.safe.queries.getMySignerAddress, {})
1853
2299
  );
1854
2300
  if (signerErr) {
1855
2301
  return await handleSubmissionFailure(
1856
- { data: config.data },
2302
+ { _data: config._data },
1857
2303
  created.id,
1858
2304
  mapCreateError2(fromConvexError(signerErr))
1859
2305
  );
1860
2306
  }
1861
2307
  if (!currentSigner?.address) {
1862
2308
  return await handleSubmissionFailure(
1863
- { data: config.data },
2309
+ { _data: config._data },
1864
2310
  created.id,
1865
2311
  new CapxulError({
1866
2312
  code: "PERMISSION_DENIED",
@@ -1871,7 +2317,7 @@ function createWithdrawalsClient(config = {}) {
1871
2317
  }
1872
2318
  if (viem.getAddress(currentSigner.address) !== viem.getAddress(config.signer.address)) {
1873
2319
  return await handleSubmissionFailure(
1874
- { data: config.data },
2320
+ { _data: config._data },
1875
2321
  created.id,
1876
2322
  new CapxulError({
1877
2323
  code: "PERMISSION_DENIED",
@@ -1885,13 +2331,13 @@ function createWithdrawalsClient(config = {}) {
1885
2331
  );
1886
2332
  }
1887
2333
  const [prepErr, submission] = await tryCatch(
1888
- config.data.query(api.withdrawals.queries.prepareSubmission, {
2334
+ config._data.query(api.withdrawals.queries.prepareSubmission, {
1889
2335
  withdrawalId: created.id
1890
2336
  })
1891
2337
  );
1892
2338
  if (prepErr) {
1893
2339
  return await handleSubmissionFailure(
1894
- { data: config.data },
2340
+ { _data: config._data },
1895
2341
  created.id,
1896
2342
  mapCreateError2(fromConvexError(prepErr))
1897
2343
  );
@@ -1899,7 +2345,7 @@ function createWithdrawalsClient(config = {}) {
1899
2345
  const destinationAddress = submission?.destinationAddress;
1900
2346
  if (!submission || !destinationAddress) {
1901
2347
  return await handleSubmissionFailure(
1902
- { data: config.data },
2348
+ { _data: config._data },
1903
2349
  created.id,
1904
2350
  new CapxulError({
1905
2351
  code: "NETWORK_ERROR",
@@ -1908,6 +2354,7 @@ function createWithdrawalsClient(config = {}) {
1908
2354
  })
1909
2355
  );
1910
2356
  }
2357
+ const token = resolvePaymentToken(submission.amount.currency);
1911
2358
  const [transferErr, transferOk] = await tryCatch(
1912
2359
  transferAsOwner(
1913
2360
  {
@@ -1915,22 +2362,22 @@ function createWithdrawalsClient(config = {}) {
1915
2362
  signing: config.signing
1916
2363
  },
1917
2364
  {
1918
- tokenAddress: resolvePaymentTokenAddress(submission.amount.currency),
2365
+ tokenAddress: token.address,
1919
2366
  recipientAddress: destinationAddress,
1920
- amount: toTokenUnits(submission.amount.value, 6)
2367
+ amount: toTokenUnits(submission.amount.value, token.decimals)
1921
2368
  }
1922
2369
  )
1923
2370
  );
1924
2371
  if (transferErr) {
1925
2372
  return await handleSubmissionFailure(
1926
- { data: config.data },
2373
+ { _data: config._data },
1927
2374
  created.id,
1928
2375
  mapCreateError2(fromConvexError(transferErr))
1929
2376
  );
1930
2377
  }
1931
2378
  if (!transferOk.success) {
1932
2379
  return await handleSubmissionFailure(
1933
- { data: config.data },
2380
+ { _data: config._data },
1934
2381
  created.id,
1935
2382
  new CapxulError({
1936
2383
  code: "NETWORK_ERROR",
@@ -1944,7 +2391,7 @@ function createWithdrawalsClient(config = {}) {
1944
2391
  );
1945
2392
  }
1946
2393
  const [recordErr] = await tryCatch(
1947
- config.data.mutation(api.withdrawals.mutations.recordSubmitted, {
2394
+ config._data.mutation(api.withdrawals.mutations.recordSubmitted, {
1948
2395
  withdrawalId: created.id,
1949
2396
  txHash: transferOk.txHash,
1950
2397
  userOpHash: transferOk.userOpHash
@@ -1968,11 +2415,11 @@ function createWithdrawalsClient(config = {}) {
1968
2415
  return [null, created];
1969
2416
  },
1970
2417
  retrieve: async (withdrawalId) => {
1971
- if (!config.data) {
2418
+ if (!config._data) {
1972
2419
  return stub("withdrawals.retrieve");
1973
2420
  }
1974
2421
  const [err, raw] = await tryCatch(
1975
- config.data.query(api.withdrawals.queries.retrieve, { withdrawalId })
2422
+ config._data.query(api.withdrawals.queries.retrieve, { withdrawalId })
1976
2423
  );
1977
2424
  if (err) {
1978
2425
  return [fromConvexError(err), null];
@@ -1990,11 +2437,11 @@ function createWithdrawalsClient(config = {}) {
1990
2437
  return [null, withdrawal];
1991
2438
  },
1992
2439
  list: async (input) => {
1993
- if (!config.data) {
2440
+ if (!config._data) {
1994
2441
  return stub("withdrawals.list");
1995
2442
  }
1996
2443
  const [err, raw] = await tryCatch(
1997
- config.data.query(api.withdrawals.queries.list, {
2444
+ config._data.query(api.withdrawals.queries.list, {
1998
2445
  limit: input?.limit,
1999
2446
  cursor: input?.cursor
2000
2447
  })
@@ -2005,13 +2452,13 @@ function createWithdrawalsClient(config = {}) {
2005
2452
  return [null, raw];
2006
2453
  },
2007
2454
  recordCompleted: async (input) => {
2008
- if (!config.data) {
2455
+ if (!config._data) {
2009
2456
  return stub(
2010
2457
  "withdrawals.recordCompleted"
2011
2458
  );
2012
2459
  }
2013
2460
  const [err] = await tryCatch(
2014
- config.data.mutation(api.withdrawals.mutations.recordCompleted, {
2461
+ config._data.mutation(api.withdrawals.mutations.recordCompleted, {
2015
2462
  withdrawalId: input.withdrawalId,
2016
2463
  txHash: input.txHash
2017
2464
  })
@@ -2036,13 +2483,13 @@ function createOrgWithdrawalsClient(config = {}) {
2036
2483
  * orchestration ships in W3+.
2037
2484
  */
2038
2485
  create: async (input) => {
2039
- if (!config.data) {
2486
+ if (!config._data) {
2040
2487
  return stub(
2041
2488
  "organizations.withdrawals.create"
2042
2489
  );
2043
2490
  }
2044
2491
  const [err, raw] = await tryCatch(
2045
- config.data.mutation(api.withdrawals.mutations.createOrg, {
2492
+ config._data.mutation(api.withdrawals.mutations.createOrg, {
2046
2493
  organizationId: input.organizationId,
2047
2494
  amount: input.amount,
2048
2495
  destination: {
@@ -2069,13 +2516,13 @@ function createOrgWithdrawalsClient(config = {}) {
2069
2516
  return [null, created];
2070
2517
  },
2071
2518
  retrieve: async (input) => {
2072
- if (!config.data) {
2519
+ if (!config._data) {
2073
2520
  return stub(
2074
2521
  "organizations.withdrawals.retrieve"
2075
2522
  );
2076
2523
  }
2077
2524
  const [err, raw] = await tryCatch(
2078
- config.data.query(api.withdrawals.queries.retrieve, {
2525
+ config._data.query(api.withdrawals.queries.retrieve, {
2079
2526
  withdrawalId: input.withdrawalId
2080
2527
  })
2081
2528
  );
@@ -2105,13 +2552,13 @@ function createOrgWithdrawalsClient(config = {}) {
2105
2552
  return [null, withdrawal];
2106
2553
  },
2107
2554
  list: async (input) => {
2108
- if (!config.data) {
2555
+ if (!config._data) {
2109
2556
  return stub(
2110
2557
  "organizations.withdrawals.list"
2111
2558
  );
2112
2559
  }
2113
2560
  const [err, raw] = await tryCatch(
2114
- config.data.query(api.withdrawals.queries.listOrg, {
2561
+ config._data.query(api.withdrawals.queries.listOrg, {
2115
2562
  organizationId: input.organizationId,
2116
2563
  limit: input.limit,
2117
2564
  cursor: input.cursor
@@ -2130,7 +2577,7 @@ async function handleSubmissionFailure(config, withdrawalId, error) {
2130
2577
  }
2131
2578
  async function bestEffortMarkFailed2(config, withdrawalId, error) {
2132
2579
  await tryCatch(
2133
- config.data.mutation(api.withdrawals.mutations.markFailed, {
2580
+ config._data.mutation(api.withdrawals.mutations.markFailed, {
2134
2581
  withdrawalId,
2135
2582
  errorCode: error.code,
2136
2583
  errorMessage: error.message
@@ -2209,13 +2656,13 @@ function createWebhookEventsClient() {
2209
2656
  function createOrgExternalAccountsClient(config) {
2210
2657
  return {
2211
2658
  create: async (input) => {
2212
- if (!config.data) {
2659
+ if (!config._data) {
2213
2660
  return stub(
2214
2661
  "organizations.externalAccounts.create"
2215
2662
  );
2216
2663
  }
2217
2664
  const [err, raw] = await tryCatch(
2218
- config.data.mutation(api.externalAccounts.mutations.createOrg, {
2665
+ config._data.mutation(api.externalAccounts.mutations.createOrg, {
2219
2666
  organizationId: input.organizationId,
2220
2667
  kind: input.kind,
2221
2668
  label: input.label,
@@ -2229,10 +2676,7 @@ function createOrgExternalAccountsClient(config) {
2229
2676
  })
2230
2677
  );
2231
2678
  if (err) {
2232
- return [
2233
- fromConvexError(err),
2234
- null
2235
- ];
2679
+ return [fromConvexError(err), null];
2236
2680
  }
2237
2681
  if (!raw) {
2238
2682
  return [
@@ -2243,53 +2687,161 @@ function createOrgExternalAccountsClient(config) {
2243
2687
  null
2244
2688
  ];
2245
2689
  }
2246
- return [
2247
- null,
2248
- brandExternalAccount(
2249
- raw
2250
- )
2251
- ];
2690
+ return [null, brandExternalAccount(raw)];
2252
2691
  },
2253
2692
  list: async (input) => {
2254
- if (!config.data) {
2693
+ if (!config._data) {
2255
2694
  return stub(
2256
2695
  "organizations.externalAccounts.list"
2257
2696
  );
2258
2697
  }
2259
2698
  const [err, result] = await tryCatch(
2260
- config.data.query(api.externalAccounts.queries.listOrg, {
2699
+ config._data.query(api.externalAccounts.queries.listOrg, {
2261
2700
  organizationId: input.organizationId,
2262
2701
  limit: input.limit,
2263
2702
  cursor: input.cursor
2264
2703
  })
2265
2704
  );
2266
2705
  if (err) {
2267
- return [fromConvexError(err), null];
2706
+ return [fromConvexError(err), null];
2707
+ }
2708
+ const branded = result.data.map(
2709
+ (row) => brandExternalAccount(row)
2710
+ );
2711
+ return [
2712
+ null,
2713
+ {
2714
+ object: "list",
2715
+ data: branded,
2716
+ page: result.page
2717
+ }
2718
+ ];
2719
+ },
2720
+ retrieve: async (input) => {
2721
+ if (!config._data) {
2722
+ return stub(
2723
+ "organizations.externalAccounts.retrieve"
2724
+ );
2725
+ }
2726
+ const [err, raw] = await tryCatch(
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, {
2752
+ organizationId: input.organizationId,
2753
+ externalAccountId: input.externalAccountId
2754
+ })
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
+ );
2781
+ if (err) {
2782
+ return [
2783
+ fromConvexError(err),
2784
+ null
2785
+ ];
2786
+ }
2787
+ if (!raw) {
2788
+ return [
2789
+ new CapxulError({
2790
+ code: "NOT_FOUND",
2791
+ message: "sub_account creation returned no resource"
2792
+ }),
2793
+ null
2794
+ ];
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);
2268
2826
  }
2269
- const branded = result.data.map(
2270
- (row) => brandExternalAccount(
2271
- row
2272
- )
2273
- );
2274
2827
  return [
2275
2828
  null,
2276
2829
  {
2277
2830
  object: "list",
2278
2831
  data: branded,
2279
- page: result.page
2832
+ page: { hasMore: false }
2280
2833
  }
2281
2834
  ];
2282
2835
  },
2283
2836
  retrieve: async (input) => {
2284
- if (!config.data) {
2837
+ if (!config._data) {
2285
2838
  return stub(
2286
- "organizations.externalAccounts.retrieve"
2839
+ "organizations.subAccounts.retrieve"
2287
2840
  );
2288
2841
  }
2289
2842
  const [err, raw] = await tryCatch(
2290
- config.data.query(api.externalAccounts.queries.retrieveOrg, {
2291
- organizationId: input.organizationId,
2292
- externalAccountId: input.externalAccountId
2843
+ config._data.query(api.subAccounts.queries.retrieve, {
2844
+ subAccountId: input.subAccountId
2293
2845
  })
2294
2846
  );
2295
2847
  if (err) {
@@ -2302,28 +2854,29 @@ function createOrgExternalAccountsClient(config) {
2302
2854
  return [
2303
2855
  new CapxulError({
2304
2856
  code: "NOT_FOUND",
2305
- message: `external_account ${input.externalAccountId} not found`
2857
+ message: `sub_account ${input.subAccountId} not found`
2306
2858
  }),
2307
2859
  null
2308
2860
  ];
2309
2861
  }
2310
- return [
2311
- null,
2312
- brandExternalAccount(
2313
- raw
2314
- )
2315
- ];
2862
+ const [brandErr, branded] = tryBrandSubAccount(raw);
2863
+ if (brandErr) {
2864
+ return [
2865
+ brandErr,
2866
+ null
2867
+ ];
2868
+ }
2869
+ return [null, branded];
2316
2870
  },
2317
2871
  remove: async (input) => {
2318
- if (!config.data) {
2872
+ if (!config._data) {
2319
2873
  return stub(
2320
- "organizations.externalAccounts.remove"
2874
+ "organizations.subAccounts.remove"
2321
2875
  );
2322
2876
  }
2323
- const [err] = await tryCatch(
2324
- config.data.mutation(api.externalAccounts.mutations.removeOrg, {
2325
- organizationId: input.organizationId,
2326
- externalAccountId: input.externalAccountId
2877
+ const [err, raw] = await tryCatch(
2878
+ config._data.mutation(api.subAccounts.mutations.archive, {
2879
+ subAccountId: input.subAccountId
2327
2880
  })
2328
2881
  );
2329
2882
  if (err) {
@@ -2332,23 +2885,139 @@ function createOrgExternalAccountsClient(config) {
2332
2885
  null
2333
2886
  ];
2334
2887
  }
2335
- return [null, void 0];
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];
2336
2905
  }
2337
2906
  };
2338
2907
  }
2339
2908
  function createOrganizationsClient(config = {}) {
2340
2909
  return {
2341
- create: async () => stub("organizations.create"),
2342
- retrieve: async () => stub("organizations.retrieve"),
2343
- list: async () => stub("organizations.list"),
2344
- update: async () => stub("organizations.update"),
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
+ },
2345
3014
  safes: {
2346
3015
  retrieve: async (input) => {
2347
- if (!config.data) {
3016
+ if (!config._data) {
2348
3017
  return stub("organizations.safes.retrieve");
2349
3018
  }
2350
3019
  try {
2351
- const safe = await config.data.query(
3020
+ const safe = await config._data.query(
2352
3021
  api.safe.queries.retrieveOrganizationSafe,
2353
3022
  input
2354
3023
  );
@@ -2371,34 +3040,243 @@ function createOrganizationsClient(config = {}) {
2371
3040
  }
2372
3041
  },
2373
3042
  treasury: {
2374
- retrieve: async () => stub("organizations.treasury.retrieve")
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
+ }
2375
3088
  },
2376
3089
  members: {
2377
- list: async () => stub("organizations.members.list"),
2378
- retrieve: async () => stub("organizations.members.retrieve"),
2379
- invite: async () => stub("organizations.members.invite"),
2380
- updateRole: async () => stub("organizations.members.updateRole"),
2381
- remove: async () => stub("organizations.members.remove")
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
+ }
2382
3233
  },
2383
3234
  apiKeys: createApiKeysClient(),
2384
- kybProfile: {
2385
- start: async () => stub("organizations.kybProfile.start"),
2386
- retrieve: async () => stub("organizations.kybProfile.retrieve")
2387
- },
2388
- subAccounts: {
2389
- create: async () => stub("organizations.subAccounts.create"),
2390
- list: async () => stub("organizations.subAccounts.list"),
2391
- retrieve: async () => stub("organizations.subAccounts.retrieve"),
2392
- remove: async () => stub("organizations.subAccounts.remove")
2393
- },
3235
+ subAccounts: createOrgSubAccountsClient(config),
2394
3236
  externalAccounts: createOrgExternalAccountsClient(config),
2395
3237
  balanceLedger: {
2396
- list: async () => stub(
2397
- "organizations.balanceLedger.list"
2398
- ),
2399
- retrieve: async () => stub(
2400
- "organizations.balanceLedger.retrieve"
2401
- )
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
+ }
2402
3280
  },
2403
3281
  payments: createOrgPaymentsClient(),
2404
3282
  transfers: createOrgTransfersClient(),
@@ -2409,14 +3287,6 @@ function createOrganizationsClient(config = {}) {
2409
3287
  };
2410
3288
  }
2411
3289
 
2412
- // src/core/sub-accounts.ts
2413
- function createSubAccountsClient() {
2414
- return {
2415
- retrieve: async () => stub("subAccounts.retrieve"),
2416
- remove: async () => stub("subAccounts.remove")
2417
- };
2418
- }
2419
-
2420
3290
  // src/core/token-transfers.ts
2421
3291
  var toTokenTransferId = (raw) => {
2422
3292
  if (typeof raw !== "string" || raw.length === 0) {
@@ -2435,11 +3305,11 @@ function brandRow(row) {
2435
3305
  function createTokenTransfersClient(config = {}) {
2436
3306
  return {
2437
3307
  list: async (input) => {
2438
- if (!config.data) {
3308
+ if (!config._data) {
2439
3309
  return stub("tokenTransfers.list");
2440
3310
  }
2441
3311
  try {
2442
- const raw = await config.data.query(
3312
+ const raw = await config._data.query(
2443
3313
  api.tokenTransfers.queries.list,
2444
3314
  {
2445
3315
  limit: input?.limit,
@@ -2473,11 +3343,11 @@ function createTokenTransfersClient(config = {}) {
2473
3343
  }
2474
3344
  },
2475
3345
  retrieve: async (input) => {
2476
- if (!config.data) {
3346
+ if (!config._data) {
2477
3347
  return stub("tokenTransfers.retrieve");
2478
3348
  }
2479
3349
  try {
2480
- const raw = await config.data.query(
3350
+ const raw = await config._data.query(
2481
3351
  api.tokenTransfers.queries.getByTxLogIndex,
2482
3352
  {
2483
3353
  txHash: input.txHash,
@@ -2814,7 +3684,6 @@ var initialContext = {
2814
3684
  email: null,
2815
3685
  code: null,
2816
3686
  username: null,
2817
- signerProvider: null,
2818
3687
  bootstrapToken: null,
2819
3688
  bootstrapReason: null,
2820
3689
  session: null,
@@ -3012,12 +3881,6 @@ function createAuthBootstrapFlowMachine(client) {
3012
3881
  error: () => null
3013
3882
  })
3014
3883
  },
3015
- ENTER_SIGNER_PROVIDER: {
3016
- actions: xstate.assign({
3017
- signerProvider: ({ event }) => event.signerProvider,
3018
- error: () => null
3019
- })
3020
- },
3021
3884
  COMPLETE_BOOTSTRAP: { target: "completing_bootstrap" },
3022
3885
  BACK: { target: "otp_requested" },
3023
3886
  RESET: { target: "email", actions: xstate.assign(() => initialContext) }
@@ -3028,8 +3891,7 @@ function createAuthBootstrapFlowMachine(client) {
3028
3891
  src: "completeBootstrap",
3029
3892
  input: ({ context }) => ({
3030
3893
  bootstrapToken: requireBootstrapToken(context),
3031
- username: requireUsername(context),
3032
- signerProvider: requireSignerProvider(context)
3894
+ username: requireUsername(context)
3033
3895
  }),
3034
3896
  onDone: {
3035
3897
  target: "authenticated",
@@ -3041,7 +3903,6 @@ function createAuthBootstrapFlowMachine(client) {
3041
3903
  safe: ({ event }) => event.output.safe,
3042
3904
  bootstrapToken: () => null,
3043
3905
  bootstrapReason: () => null,
3044
- signerProvider: () => null,
3045
3906
  email: () => null,
3046
3907
  error: () => null
3047
3908
  }),
@@ -3122,15 +3983,6 @@ function requireUsername(context) {
3122
3983
  }
3123
3984
  return context.username;
3124
3985
  }
3125
- function requireSignerProvider(context) {
3126
- if (!context.signerProvider) {
3127
- throw Errors.invalidInput(
3128
- "signerProvider",
3129
- "Auth bootstrap requires a signer provider."
3130
- );
3131
- }
3132
- return context.signerProvider;
3133
- }
3134
3986
  function errorFromEvent2(event) {
3135
3987
  const cause = typeof event === "object" && event !== null && "error" in event ? event.error : event;
3136
3988
  if (cause instanceof CapxulError || cause instanceof CapxulError2) {
@@ -3176,7 +4028,7 @@ function createProvisioningMachine(client) {
3176
4028
  const provider = context.input?.signerProvider;
3177
4029
  if (!provider) return;
3178
4030
  track("provisioning_safe_created", {
3179
- safe_address: provider.safeAddress
4031
+ safe_address: deriveSafeAddress(provider.signerAddress)
3180
4032
  });
3181
4033
  }
3182
4034
  }
@@ -3538,7 +4390,7 @@ function createCapxulClient(config = {}) {
3538
4390
  tokenTransfers: createTokenTransfersClient(config),
3539
4391
  withdrawals: createWithdrawalsClient(config),
3540
4392
  documents: createDocumentsClient(),
3541
- subAccounts: createSubAccountsClient(),
4393
+ subAccounts: createSubAccountsClient(config),
3542
4394
  virtualAccounts: createVirtualAccountsClient(),
3543
4395
  virtualCards: createVirtualCardsClient(),
3544
4396
  externalAccounts: createExternalAccountsClient(config),
@@ -3655,7 +4507,86 @@ function isWebhookEvent(value) {
3655
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);
3656
4508
  }
3657
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;
3658
4588
  exports.CapxulError = CapxulError;
4589
+ exports.SignerProvisioner = SignerProvisioner;
3659
4590
  exports.createAuthBootstrapFlowMachine = createAuthBootstrapFlowMachine;
3660
4591
  exports.createAuthFlowMachine = createAuthFlowMachine;
3661
4592
  exports.createCapxulClient = createCapxulClient;
@@ -3666,6 +4597,7 @@ exports.makeHttpTransport = makeHttpTransport;
3666
4597
  exports.matchAction = matchAction;
3667
4598
  exports.matchError = matchError;
3668
4599
  exports.matchStatus = matchStatus;
4600
+ exports.resolvePaymentToken = resolvePaymentToken;
3669
4601
  exports.toAccountId = toAccountId;
3670
4602
  exports.toApiKeyId = toApiKeyId;
3671
4603
  exports.toBalanceLedgerEntryId = toBalanceLedgerEntryId;