@capxul/mcp 4.20.0-beta.3 → 4.20.0-beta.5

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.
Files changed (2) hide show
  1. package/dist/main.mjs +562 -103
  2. package/package.json +3 -3
package/dist/main.mjs CHANGED
@@ -1022,18 +1022,9 @@ const USDX_ASSET = {
1022
1022
  tokenAddress: USDX_ADDRESS_BASE_SEPOLIA,
1023
1023
  deploymentStartBlock: USDX_DEPLOYMENT_START_BLOCK,
1024
1024
  decimals: 6,
1025
- source: "settlement"
1025
+ source: "legacy"
1026
1026
  };
1027
- /**
1028
- * The settlement tier: rows the exact-transfer path and the Movement scanner
1029
- * admit, each carrying the legacy `currency` projection those readers expect.
1030
- * Adding an owned test asset here would put candidate liquidity on the
1031
- * money-write path, so M03's rows go to the candidate tier below instead.
1032
- */
1033
- const CONFIGURED_MONEY_ASSETS = [{
1034
- ...USDX_ASSET,
1035
- currency: USDX_ASSET.peg
1036
- }];
1027
+ ({ ...USDX_ASSET }), USDX_ASSET.peg;
1037
1028
  /**
1038
1029
  * The candidate tier: five owned test assets, every field read back from Base
1039
1030
  * Sepolia after the deployment that created it (chain 84532, blocks
@@ -1105,12 +1096,25 @@ const SYNTHETIC_TEST_ASSETS = [
1105
1096
  ];
1106
1097
  toChainId(84532);
1107
1098
  /**
1099
+ * The settlement tier: the owned test assets admitted to the exact-transfer
1100
+ * path and to the treasury reads. USDC, USDT and WETH are equal assets. There
1101
+ * is no default token and no successor to USDX; USDX survives only in
1102
+ * `LEGACY_MONEY_ASSETS` and is not a current treasury row.
1103
+ */
1104
+ const SETTLEMENT_ASSET_SYMBOLS = [
1105
+ "USDC",
1106
+ "USDT",
1107
+ "WETH"
1108
+ ];
1109
+ const CONFIGURED_MONEY_ASSETS = SYNTHETIC_TEST_ASSETS.filter((asset) => SETTLEMENT_ASSET_SYMBOLS.includes(asset.symbol));
1110
+ /**
1108
1111
  * Every known asset in ONE identity space. The tiers above declare admission;
1109
1112
  * this is the only list an identity resolves against, so an asset is never
1110
1113
  * two different things depending on which list a caller happened to read.
1111
1114
  */
1112
- const MONEY_ASSET_REGISTRY = [...CONFIGURED_MONEY_ASSETS, ...SYNTHETIC_TEST_ASSETS];
1115
+ const MONEY_ASSET_REGISTRY = [USDX_ASSET, ...SYNTHETIC_TEST_ASSETS];
1113
1116
  CONFIGURED_MONEY_ASSETS.map((asset) => asset.tokenAddress.toLowerCase());
1117
+ USDX_ADDRESS_BASE_SEPOLIA.toLowerCase();
1114
1118
  /** The registry row for `assetId` across every tier, or `null`. */
1115
1119
  function configuredMoneyAssetById(assetId) {
1116
1120
  const canonical = toAssetId(assetId);
@@ -6873,6 +6877,175 @@ function serializeSignature({ r, s, to = "hex", v, yParity }) {
6873
6877
  return hexToBytes(signature);
6874
6878
  }
6875
6879
  //#endregion
6880
+ //#region ../../packages/sdk/src/domain/money/asset-amount.ts
6881
+ /** Convert raw units without rounding or changing asset identity. */
6882
+ function assetAmountFromRaw(raw, asset) {
6883
+ validateMetadata(asset);
6884
+ return {
6885
+ asset: asset.assetId,
6886
+ value: formatUnits(decimalToRaw(toWeiAmount(raw), 0), asset.decimals)
6887
+ };
6888
+ }
6889
+ /** Exact scaling. This rejects excess precision instead of rounding it. */
6890
+ function toRaw(amount, asset) {
6891
+ validateMetadata(asset);
6892
+ if (amount.asset !== asset.assetId) throw Errors.invalidInput("amount.asset", "must match the selected asset on its chain");
6893
+ return decimalToRaw(amount.value, asset.decimals);
6894
+ }
6895
+ function requireAsset(id) {
6896
+ const asset = configuredMoneyAssetById(id);
6897
+ if (asset === null) throw Errors.invalidInput("amount.asset", "is not a registered asset");
6898
+ return asset;
6899
+ }
6900
+ function decimalToRaw(value, decimals) {
6901
+ validatePrecision(decimals);
6902
+ if (!/^\d+(?:\.\d+)?$/.test(value) || value.trim() !== value || value.length > 512) throw Errors.invalidInput("amount.value", "must be a non-negative decimal string of at most 512 characters");
6903
+ const [integer = "0", fraction = ""] = value.split(".");
6904
+ if (fraction.length > decimals) throw Errors.invalidInput("amount.value", "fraction exceeds asset precision");
6905
+ return BigInt(integer) * 10n ** BigInt(decimals) + BigInt(fraction.padEnd(decimals, "0") || "0");
6906
+ }
6907
+ function validatePrecision(decimals) {
6908
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) throw Errors.invalidInput("decimals", "must be an integer from 0 to 255");
6909
+ }
6910
+ function validateMetadata(asset) {
6911
+ validatePrecision(asset.decimals);
6912
+ if (asset.assetId !== assetIdFor(asset.chainId, asset.tokenAddress)) throw Errors.invalidInput("amount.asset", "metadata must match its chain and token");
6913
+ }
6914
+ //#endregion
6915
+ //#region ../../packages/sdk/src/domain/money/valuation.ts
6916
+ const PEG_RATES = (source, into) => (typeof source === "string" ? source : source.peg) === into ? {
6917
+ value: "1",
6918
+ decimals: 0
6919
+ } : null;
6920
+ /**
6921
+ * The oracle the money READS price with: the account headline, the org
6922
+ * treasury headline, and every later total over the same seam (D6).
6923
+ *
6924
+ * It is `PEG_RATES` today because no price feed exists yet, and a peg is a
6925
+ * relationship, not a market price — so an unpegged asset such as WETH reads
6926
+ * as unrated rather than as a fabricated number. This binding is the ONE place
6927
+ * a real feed arrives; no call site changes when it does.
6928
+ */
6929
+ const MONEY_READ_RATES = PEG_RATES;
6930
+ /** Sum exact fixed-point values. Missing rates never contribute zero. */
6931
+ function valueIn(amounts, displayCurrency, rates = PEG_RATES) {
6932
+ const currency = toCurrencyCode(displayCurrency);
6933
+ const counted = [];
6934
+ const unrated = [];
6935
+ let sum = 0n;
6936
+ let scale = 0;
6937
+ for (const amount of amounts) {
6938
+ let source;
6939
+ let raw;
6940
+ let decimals;
6941
+ if ("asset" in amount) {
6942
+ source = requireAsset(amount.asset);
6943
+ raw = toRaw(amount, source);
6944
+ decimals = source.decimals;
6945
+ } else {
6946
+ source = toCurrencyCode(amount.currency);
6947
+ raw = decimalToRaw(amount.value, amount.decimals);
6948
+ decimals = amount.decimals;
6949
+ }
6950
+ const rate = rates(source, currency);
6951
+ if (rate === null) {
6952
+ unrated.push(amount);
6953
+ continue;
6954
+ }
6955
+ validatePrecision(rate.decimals);
6956
+ if (!/^\d+$/.test(rate.value) || rate.value.trim() !== rate.value || rate.value.length > 256 || BigInt(rate.value) <= 0n) throw Errors.invalidInput("rate.value", "must be a positive fixed-point integer");
6957
+ const termScale = decimals + rate.decimals;
6958
+ const nextScale = Math.max(scale, termScale);
6959
+ sum = sum * 10n ** BigInt(nextScale - scale) + raw * BigInt(rate.value) * 10n ** BigInt(nextScale - termScale);
6960
+ scale = nextScale;
6961
+ counted.push(amount);
6962
+ }
6963
+ return {
6964
+ total: counted.length === 0 ? null : {
6965
+ currency,
6966
+ value: formatUnits(sum, scale),
6967
+ decimals: scale
6968
+ },
6969
+ counted,
6970
+ unrated
6971
+ };
6972
+ }
6973
+ //#endregion
6974
+ //#region ../../packages/sdk/src/domain/money/account-positions.ts
6975
+ /**
6976
+ * Lift an Account's raw per-asset positions to the SDK's `AccountPosition`.
6977
+ *
6978
+ * A position whose `assetId` is not a registered asset refuses. An unregistered
6979
+ * token has no identity this SDK can state, so it must never be relabelled as
6980
+ * one — the failure is the point, not a row to skip.
6981
+ */
6982
+ function accountPositionsFromWire(positions) {
6983
+ return positions.map((position) => {
6984
+ const asset = configuredMoneyAssetById(toAssetId(position.assetId));
6985
+ if (asset === null) throw Errors.invalidInput("assetId", "is not a registered asset");
6986
+ const raw = toWeiAmount(position.rawBalance);
6987
+ const rawAvailable = toWeiAmount(position.rawAvailableBalance ?? position.rawBalance);
6988
+ return {
6989
+ asset: asset.assetId,
6990
+ symbol: asset.symbol,
6991
+ decimals: asset.decimals,
6992
+ balance: assetAmountFromRaw(raw, asset).value,
6993
+ available: assetAmountFromRaw(rawAvailable, asset).value
6994
+ };
6995
+ });
6996
+ }
6997
+ /**
6998
+ * The fiat headline of a set of positions: the sum of the positions the given
6999
+ * oracle can rate into the display currency (ADR-0028 R6, D6). It never picks
7000
+ * a token and never labels one as fiat.
7001
+ *
7002
+ * The oracle is a PARAMETER (D6 obligation 4). It defaults to `PEG_RATES`, which
7003
+ * only rates an asset whose peg equals the display currency, so an unpegged
7004
+ * asset such as WETH stays out of the total and out of `counted`:
7005
+ * a WETH-only Account reads a `$0.00` headline under that default. Hand it a
7006
+ * real oracle and the same Account prices (WETH at `$2000` under
7007
+ * `createMockRates`, a live feed later).
7008
+ *
7009
+ * Either way the unrated position is never zeroed and never dropped: it stays
7010
+ * in `Account.balances`, and `valueIn` reports it in its own `unrated` list so
7011
+ * a caller can say how complete the total is.
7012
+ */
7013
+ function headlineValuation(balances, displayCurrency, rates = PEG_RATES) {
7014
+ const total = (pick) => valueIn(balances.map((position) => ({
7015
+ asset: position.asset,
7016
+ value: pick(position)
7017
+ })), displayCurrency, rates).total ?? {
7018
+ currency: displayCurrency,
7019
+ value: "0",
7020
+ decimals: 0
7021
+ };
7022
+ return {
7023
+ balance: total((position) => position.balance),
7024
+ available: total((p) => p.available)
7025
+ };
7026
+ }
7027
+ /**
7028
+ * The Account: its per-asset truth plus the fiat headline valuation. The oracle
7029
+ * is threaded from the read that built it, never defaulted past this point
7030
+ * (D6): the account read passes the configured one.
7031
+ */
7032
+ function accountFromPositions(id, positions, displayCurrency = toCurrencyCode("USD"), rates = PEG_RATES) {
7033
+ const balances = accountPositionsFromWire(positions);
7034
+ return {
7035
+ id,
7036
+ balances,
7037
+ ...headlineValuation(balances, displayCurrency, rates)
7038
+ };
7039
+ }
7040
+ /** The same lift for positions a caller already holds as `AccountPosition`. */
7041
+ function accountFromAccountPositions(id, balances, displayCurrency = toCurrencyCode("USD"), rates = PEG_RATES) {
7042
+ return {
7043
+ id,
7044
+ balances,
7045
+ ...headlineValuation(balances, displayCurrency, rates)
7046
+ };
7047
+ }
7048
+ //#endregion
6876
7049
  //#region ../../packages/observability/src/operations.ts
6877
7050
  const CAPXUL_OPERATIONS = {
6878
7051
  account: {
@@ -6941,6 +7114,26 @@ const CAPXUL_OPERATIONS = {
6941
7114
  createOrg: "createOrg",
6942
7115
  orgs: "orgs"
6943
7116
  },
7117
+ /** AUTH A3 (#2073): the SDK facade over the native continuation endpoints. */
7118
+ clientRequests: {
7119
+ decide: "clientRequests.decide",
7120
+ read: "clientRequests.read"
7121
+ },
7122
+ /** AUTH A2 (#2072): the native client authorization issuer and its browser
7123
+ * continuation. One name per durable transition the endpoints can fail on. */
7124
+ clientAuthorization: {
7125
+ acceptRequest: "clientAuthorization.acceptRequest",
7126
+ cancelRequest: "clientAuthorization.cancelRequest",
7127
+ consumeRequest: "clientAuthorization.consumeRequest",
7128
+ denyRequest: "clientAuthorization.denyRequest",
7129
+ invalidateContext: "clientAuthorization.invalidateContext",
7130
+ markConsented: "clientAuthorization.markConsented",
7131
+ readMetadata: "clientAuthorization.readMetadata",
7132
+ revokeGrant: "clientAuthorization.revokeGrant",
7133
+ rotateGrant: "clientAuthorization.rotateGrant",
7134
+ startRequest: "clientAuthorization.startRequest",
7135
+ sweepExpired: "clientAuthorization.sweepExpired"
7136
+ },
6944
7137
  credentials: {
6945
7138
  bootstrapClient: "credentials.bootstrapClient",
6946
7139
  mintQuickstartKey: "credentials.mintQuickstartKey"
@@ -7424,6 +7617,44 @@ const IdentityRefusedProps = Schema.Struct({
7424
7617
  state: OptionalString
7425
7618
  });
7426
7619
  const AuthSignedOutProps = Schema.Struct(TelemetryEnvelopeProps);
7620
+ const NativeAuthorizationMode = Schema.Literals(["login", "signup"]);
7621
+ const NativeAuthorizationStartedProps = Schema.Struct({
7622
+ ...TelemetryEnvelopeProps,
7623
+ mode: NativeAuthorizationMode
7624
+ });
7625
+ const NativeAuthorizationReviewedProps = Schema.Struct({
7626
+ ...TelemetryEnvelopeProps,
7627
+ mode: NativeAuthorizationMode
7628
+ });
7629
+ const NativeAuthorizationAcceptedProps = Schema.Struct({
7630
+ ...TelemetryEnvelopeProps,
7631
+ mode: NativeAuthorizationMode,
7632
+ /** Whether consent also had to finish account setup first. */
7633
+ setup_state: Schema.optional(Schema.Literals([
7634
+ "not_required",
7635
+ "new",
7636
+ "resumable"
7637
+ ]))
7638
+ });
7639
+ const NativeAuthorizationDeniedProps = Schema.Struct({
7640
+ ...TelemetryEnvelopeProps,
7641
+ mode: NativeAuthorizationMode
7642
+ });
7643
+ const NativeAuthorizationConnectedProps = Schema.Struct({
7644
+ ...TelemetryEnvelopeProps,
7645
+ mode: NativeAuthorizationMode
7646
+ });
7647
+ const NativeAuthorizationFailedProps = Schema.Struct({
7648
+ ...TelemetryEnvelopeProps,
7649
+ mode: Schema.optional(NativeAuthorizationMode),
7650
+ /** The refusal word the store returned, for example `identity_mismatch` or
7651
+ * `request_expired`. These are the closed `CLIENT_AUTHORIZATION_REFUSALS` from
7652
+ * `@capxul/wire` plus the store-internal `fresh_session_required` (ruling R3),
7653
+ * which the continuation maps to `identity_mismatch` on the wire but reports
7654
+ * truthfully here. Kept as `OptionalString` rather than an imported literal
7655
+ * set: this package must not depend on the transport contract. */
7656
+ reason: OptionalString
7657
+ });
7427
7658
  const ProvisioningSafeCreatedProps = Schema.Struct({
7428
7659
  ...TelemetryEnvelopeProps,
7429
7660
  safe_address: OptionalAddress
@@ -7466,6 +7697,12 @@ const BootstrapFailedProps = Schema.Struct({
7466
7697
  * Organization row's chain, the configured token address — never from a label.
7467
7698
  * The verified `organization_id` and its group arrive from the backend
7468
7699
  * attribution, so they are not repeated here.
7700
+ *
7701
+ * D1 (2026-09-10): `asset_id` carries the canonical branded identity the read
7702
+ * resolved, `eip155:<chainId>/erc20:<lowercase-address>`, from the registry
7703
+ * row. `token_address`/`chain_id` are its parts; `currency` is the peg and a
7704
+ * display code. The producer emits the branded id so the live read can be
7705
+ * grouped by ASSET, never by symbol or peg.
7469
7706
  */
7470
7707
  const AccountBalanceReadProps = Schema.Struct({
7471
7708
  ...TelemetryEnvelopeProps,
@@ -7473,6 +7710,7 @@ const AccountBalanceReadProps = Schema.Struct({
7473
7710
  account_kind: OptionalAccountKind,
7474
7711
  chain_id: OptionalChainId,
7475
7712
  token_address: OptionalAddress,
7713
+ asset_id: OptionalString,
7476
7714
  currency: OptionalCurrencyCode,
7477
7715
  balance_bucket: OptionalBalanceBucket,
7478
7716
  durationMs: OptionalDurationMs
@@ -7941,6 +8179,30 @@ Schema.Struct({
7941
8179
  name: Schema.Literal("auth_signed_out"),
7942
8180
  props: AuthSignedOutProps
7943
8181
  });
8182
+ Schema.Struct({
8183
+ name: Schema.Literal("native_authorization_started"),
8184
+ props: NativeAuthorizationStartedProps
8185
+ });
8186
+ Schema.Struct({
8187
+ name: Schema.Literal("native_authorization_reviewed"),
8188
+ props: NativeAuthorizationReviewedProps
8189
+ });
8190
+ Schema.Struct({
8191
+ name: Schema.Literal("native_authorization_accepted"),
8192
+ props: NativeAuthorizationAcceptedProps
8193
+ });
8194
+ Schema.Struct({
8195
+ name: Schema.Literal("native_authorization_denied"),
8196
+ props: NativeAuthorizationDeniedProps
8197
+ });
8198
+ Schema.Struct({
8199
+ name: Schema.Literal("native_authorization_connected"),
8200
+ props: NativeAuthorizationConnectedProps
8201
+ });
8202
+ Schema.Struct({
8203
+ name: Schema.Literal("native_authorization_failed"),
8204
+ props: NativeAuthorizationFailedProps
8205
+ });
7944
8206
  Schema.Struct({
7945
8207
  name: Schema.Literal("onboarding_intent_selected"),
7946
8208
  props: OnboardingIntentSelectedProps
@@ -8195,12 +8457,18 @@ const CLI_COMMAND_NAMES = [
8195
8457
  "telemetry.status",
8196
8458
  "telemetry.enable",
8197
8459
  "telemetry.disable",
8460
+ "auth",
8461
+ "auth.login",
8462
+ "auth.signup",
8463
+ "auth.status",
8464
+ "auth.logout",
8198
8465
  "unknown"
8199
8466
  ];
8200
8467
  const CLI_CAPABILITIES = [
8201
8468
  "cli",
8202
8469
  "diagnostics",
8203
- "collection"
8470
+ "collection",
8471
+ "authentication"
8204
8472
  ];
8205
8473
  const CLI_INVOCATION_KINDS = [
8206
8474
  "command",
@@ -8218,8 +8486,9 @@ const CliInvocationProps = {
8218
8486
  capability: Schema.Literals(CLI_CAPABILITIES),
8219
8487
  invocation_kind: Schema.Literals(CLI_INVOCATION_KINDS),
8220
8488
  invocation_id: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u)),
8221
- cli_identity_kind: Schema.optional(Schema.Literal("anonymous")),
8489
+ cli_identity_kind: Schema.optional(Schema.Literals(["anonymous", "identified"])),
8222
8490
  anonymous_id: Schema.optional(Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u))),
8491
+ auth_user_id: Schema.optional(Schema.String.check(Schema.isPattern(/^[^\s]{1,256}$/u))),
8223
8492
  occurred_at: Schema.Number,
8224
8493
  cli_version: CliRelease,
8225
8494
  sdk_version: CliRelease,
@@ -10891,8 +11160,7 @@ const country = normalize((s) => s.toUpperCase()).pipe(Schema.refine((s) => COUN
10891
11160
  const credential = Schema.RedactedFromValue(Schema.String.check(Schema.isMinLength(32), Schema.isMaxLength(8192), Schema.isPattern(/^[A-Za-z0-9._~-]+$/u)), { label: "native authorization credential" });
10892
11161
  const otp = Schema.RedactedFromValue(Schema.String.check(Schema.isPattern(/^[0-9]{6}$/u)), { label: "OTP" });
10893
11162
  const scopes = Schema.Tuple([Schema.Literal(NATIVE_CLIENT_SCOPE)]);
10894
- /** Exact HTTPS origin, no credentials/path/query and no retired cloud deployment. */
10895
- const NativeHttpsOriginSchema = Schema.String.check(Schema.makeFilter((value) => {
11163
+ const isNativeHttpsOriginValue = (value) => {
10896
11164
  try {
10897
11165
  const url = new URL(value);
10898
11166
  const host = url.hostname.toLowerCase().replace(/\.$/u, "");
@@ -10900,20 +11168,43 @@ const NativeHttpsOriginSchema = Schema.String.check(Schema.makeFilter((value) =>
10900
11168
  } catch {
10901
11169
  return false;
10902
11170
  }
10903
- }, { message: "must be a canonical credential-free HTTPS origin outside retired Convex cloud hosts" }));
11171
+ };
11172
+ Schema.String.check(Schema.makeFilter(isNativeHttpsOriginValue, { message: "must be a canonical credential-free HTTPS origin outside retired Convex cloud hosts" }));
11173
+ const isLoopbackOriginValue = (value) => {
11174
+ try {
11175
+ const url = new URL(value);
11176
+ const host = url.hostname.toLowerCase().replace(/\.$/u, "");
11177
+ return url.protocol === "http:" && value === url.origin && !url.username && !url.password && !url.search && !url.hash && (host === "127.0.0.1" || host === "[::1]" || host === "localhost");
11178
+ } catch {
11179
+ return false;
11180
+ }
11181
+ };
11182
+ Schema.String.check(Schema.makeFilter(isLoopbackOriginValue, { message: "must be a canonical credential-free loopback HTTP origin" }));
11183
+ /**
11184
+ * Either a standing-tier HTTPS origin or a devnet loopback origin. A `Union` of
11185
+ * the two refined string schemas does not type-check in this Effect version —
11186
+ * it widens both fields to `unknown` — so the disjunction lives in one filter
11187
+ * and the struct check below is what binds a loopback origin to
11188
+ * `environment: "local"`. Loopback is never admissible on a standing tier.
11189
+ */
11190
+ const NativeOriginSchema = Schema.String.check(Schema.makeFilter((value) => isNativeHttpsOriginValue(value) || isLoopbackOriginValue(value), { message: "must be a canonical credential-free HTTPS origin outside retired Convex cloud hosts, or a loopback HTTP origin for the local devnet" }));
10904
11191
  const NativeClientConfigurationSchema = Schema.Struct({
10905
11192
  clientId: Schema.Literal(NATIVE_CLIENT_ID),
10906
11193
  applicationId: AppIdSchema,
10907
11194
  keyId,
10908
11195
  environment: Schema.Literals([
11196
+ "local",
10909
11197
  "development",
10910
11198
  "staging",
10911
11199
  "production"
10912
11200
  ]),
10913
11201
  keyEnvironment: Schema.Literals(["test", "live"]),
10914
- issuer: NativeHttpsOriginSchema,
10915
- verificationOrigin: NativeHttpsOriginSchema
10916
- }).annotate(strict).check(Schema.makeFilter((c) => c.keyEnvironment === (c.environment === "production" ? "live" : "test"), { message: "key environment must match the configured deployment" })).annotate(strict);
11202
+ issuer: NativeOriginSchema,
11203
+ verificationOrigin: NativeOriginSchema
11204
+ }).annotate(strict).check(Schema.makeFilter((c) => c.keyEnvironment === (c.environment === "production" ? "live" : "test"), { message: "key environment must match the configured deployment" })).check(Schema.makeFilter((c) => {
11205
+ const loopback = isLoopbackOriginValue(c.issuer) || isLoopbackOriginValue(c.verificationOrigin);
11206
+ return c.environment === "local" ? isLoopbackOriginValue(c.issuer) && isLoopbackOriginValue(c.verificationOrigin) : !loopback;
11207
+ }, { message: "loopback origins belong to the local devnet environment alone" })).annotate(strict);
10917
11208
  const NativeSignupProfileSchema = Schema.Struct({
10918
11209
  displayName: normalize((s) => s.trim()).check(Schema.isMinLength(1), Schema.isMaxLength(200)),
10919
11210
  country,
@@ -10967,7 +11258,7 @@ const profileSummary = {
10967
11258
  handle: handle$1,
10968
11259
  country
10969
11260
  };
10970
- Schema.Union([
11261
+ const ClientRequestViewSchema = Schema.Union([
10971
11262
  Schema.Struct({
10972
11263
  ...request,
10973
11264
  phase: Schema.Literal(CLIENT_AUTHORIZATION_PHASE.OTP_REQUIRED),
@@ -11034,8 +11325,7 @@ Schema.Struct({
11034
11325
  Schema.Struct({
11035
11326
  client_id: Schema.Literal(NATIVE_CLIENT_ID),
11036
11327
  grant_type: Schema.Literal("refresh_token"),
11037
- refresh_token: credential,
11038
- refreshAttemptId: Schema.RedactedFromValue(Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_-]{32,128}$/u)), { label: "refresh attempt" })
11328
+ refresh_token: credential
11039
11329
  }).annotate(strict);
11040
11330
  Schema.Struct({
11041
11331
  client_id: Schema.Literal(NATIVE_CLIENT_ID),
@@ -11107,6 +11397,33 @@ Schema.Struct({
11107
11397
  maximum: NATIVE_CLIENT_LIMITS.requestMs / 1e3
11108
11398
  }))
11109
11399
  }).annotate(strict);
11400
+ Schema.Struct({
11401
+ client_id: Schema.Literal(NATIVE_CLIENT_ID),
11402
+ token: credential,
11403
+ token_type_hint: Schema.optional(Schema.Literals([
11404
+ "access_token",
11405
+ "refresh_token",
11406
+ "device_code"
11407
+ ]))
11408
+ }).annotate(strict);
11409
+ Schema.Struct({
11410
+ client_id: Schema.Literal(NATIVE_CLIENT_ID),
11411
+ token: credential
11412
+ }).annotate(strict);
11413
+ Schema.Struct({
11414
+ error: Schema.Literals([
11415
+ "authorization_pending",
11416
+ "slow_down",
11417
+ "access_denied",
11418
+ "invalid_grant",
11419
+ "invalid_request",
11420
+ "expired_token",
11421
+ "server_error"
11422
+ ]),
11423
+ refusal: Schema.optional(Schema.Literals(CLIENT_AUTHORIZATION_REFUSALS)),
11424
+ retryable: Schema.Boolean,
11425
+ retry_after: Schema.optional(nonNegativeInt)
11426
+ }).annotate(strict);
11110
11427
  //#endregion
11111
11428
  //#region ../../packages/sdk/src/internal/invocation-observation.ts
11112
11429
  const INVOCATION_OBSERVATION = Symbol("capxul.invocation-observation");
@@ -13544,7 +13861,7 @@ function subscribeActivity(deps, actor, controls, onChange) {
13544
13861
  }
13545
13862
  //#endregion
13546
13863
  //#region ../../packages/sdk/package.json
13547
- var version$1 = "4.20.0-beta.3";
13864
+ var version$1 = "4.20.0-beta.5";
13548
13865
  //#endregion
13549
13866
  //#region ../../packages/sdk/src/telemetry/exception-projection.ts
13550
13867
  /** Fixed fallback for failures that have no safe message. */
@@ -16095,7 +16412,7 @@ const MINIMAL_ENUM_VALUES = /* @__PURE__ */ new Map([
16095
16412
  ["command", CLI_COMMAND_NAMES],
16096
16413
  ["capability", CLI_CAPABILITIES],
16097
16414
  ["invocation_kind", CLI_INVOCATION_KINDS],
16098
- ["cli_identity_kind", ["anonymous"]],
16415
+ ["cli_identity_kind", ["anonymous", "identified"]],
16099
16416
  ["output_mode", ["human", "json"]],
16100
16417
  ["unit", [
16101
16418
  "1",
@@ -21006,13 +21323,15 @@ var ConvexAccountAdapter = class {
21006
21323
  #convex;
21007
21324
  #fns;
21008
21325
  #telemetry;
21326
+ #rates;
21009
21327
  constructor(deps) {
21010
21328
  this.#convex = deps.convex;
21011
21329
  this.#fns = deps.functions ?? DEFAULT_FUNCTIONS$3;
21012
21330
  this.#telemetry = deps.telemetry;
21331
+ this.#rates = deps.rates ?? MONEY_READ_RATES;
21013
21332
  }
21014
21333
  readBalance(input) {
21015
- return retryIdempotentRead(this.#convex.action(this.#fns.readBalance, copyInvocationObservation(input, { chainId: wireChainId(input.chainId) })), CAPXUL_OPERATIONS.accounts.read, this.#telemetry, input).pipe(Effect.mapError((error) => accountReadErrorFromCapxul("readBalance", error.publicError, error)), Effect.flatMap((wire) => brandAccountEffect("readBalance", wire)), Effect.catchDefect((cause) => Effect.fail(accountReadErrorFromUnknown("readBalance", cause))));
21334
+ return retryIdempotentRead(this.#convex.action(this.#fns.readBalance, copyInvocationObservation(input, { chainId: wireChainId(input.chainId) })), CAPXUL_OPERATIONS.accounts.read, this.#telemetry, input).pipe(Effect.mapError((error) => accountReadErrorFromCapxul("readBalance", error.publicError, error)), Effect.flatMap((wire) => brandAccountEffect("readBalance", wire, this.#rates)), Effect.catchDefect((cause) => Effect.fail(accountReadErrorFromUnknown("readBalance", cause))));
21016
21335
  }
21017
21336
  fundFromFaucet(input) {
21018
21337
  const operation = "fundFromFaucet";
@@ -21025,26 +21344,21 @@ var ConvexAccountAdapter = class {
21025
21344
  }).pipe(Effect.mapError((error) => accountReadErrorFromCapxul(operation, error.publicError, error)), Effect.map((wire) => ({ txHash: wire.txHash })), Effect.catchDefect((cause) => Effect.fail(accountReadErrorFromUnknown(operation, cause))));
21026
21345
  }
21027
21346
  };
21028
- function ConvexAccountLayer() {
21347
+ function ConvexAccountLayer(input = {}) {
21029
21348
  return Layer.effect(AccountReadPortTag, Effect.all([ConvexCallPortTag, TelemetryPortTag]).pipe(Effect.map(([convex, telemetry]) => new ConvexAccountAdapter({
21030
21349
  convex,
21031
- telemetry
21350
+ telemetry,
21351
+ ...input
21032
21352
  }))));
21033
21353
  }
21034
- function brandAccountEffect(operation, wire) {
21354
+ function brandAccountEffect(operation, wire, rates) {
21035
21355
  return Effect.try({
21036
- try: () => brandAccount(wire),
21356
+ try: () => brandAccount(wire, rates),
21037
21357
  catch: (cause) => accountReadErrorFromUnknown(operation, cause)
21038
21358
  });
21039
21359
  }
21040
- function brandAccount(wire) {
21041
- const balance = fromWei(wire.rawBalance, wire.decimals, wire.currency);
21042
- const available = fromWei(wire.rawAvailableBalance ?? wire.rawBalance, wire.decimals, wire.currency);
21043
- return {
21044
- id: toAccountId(wire.accountId),
21045
- balance,
21046
- available
21047
- };
21360
+ function brandAccount(wire, rates) {
21361
+ return accountFromPositions(toAccountId(wire.accountId), wire.positions, void 0, rates);
21048
21362
  }
21049
21363
  function accountReadErrorFromUnknown(operation, cause) {
21050
21364
  if (cause instanceof CapxulError) return accountReadErrorFromCapxul(operation, cause);
@@ -21183,16 +21497,16 @@ function brandOrgView(wire, treasury, viewerRole) {
21183
21497
  };
21184
21498
  }
21185
21499
  /**
21186
- * Build the Org treasury `Account` from the raw on-chain `balanceOf` integer
21187
- * (the D3 RPC read). `available === balance` for a treasury with no envelope
21188
- * partition yet (a fresh Org reads back $0).
21500
+ * Build the Org treasury `Account` from the raw per-asset `balanceOf` reads
21501
+ * (the D3 RPC pull). `available === balance` for a treasury with no envelope
21502
+ * partition yet (a fresh Org reads back a zero position per asset).
21503
+ *
21504
+ * `rates` is the oracle the headline prices with (D6). The live read passes the
21505
+ * configured one; it defaults to `PEG_RATES` so an unpegged holding reads as
21506
+ * unrated rather than as a number nobody priced.
21189
21507
  */
21190
21508
  function brandOrgTreasury(input) {
21191
- return {
21192
- id: toAccountId(`account_${orgIdBody(input.orgId)}`),
21193
- balance: input.money,
21194
- available: input.money
21195
- };
21509
+ return accountFromAccountPositions(toAccountId(`account_${orgIdBody(input.orgId)}`), input.balances, void 0, input.rates);
21196
21510
  }
21197
21511
  function brandOrgRole(wire) {
21198
21512
  return {
@@ -21279,10 +21593,12 @@ var ConvexOrganizationAdapter = class {
21279
21593
  #convex;
21280
21594
  #fns;
21281
21595
  #telemetry;
21596
+ #rates;
21282
21597
  constructor(input) {
21283
21598
  this.#convex = input.convex;
21284
21599
  this.#fns = input.functions ?? DEFAULT_FUNCTIONS$1;
21285
21600
  this.#telemetry = input.telemetry;
21601
+ this.#rates = input.rates ?? MONEY_READ_RATES;
21286
21602
  }
21287
21603
  createOrg(_input) {
21288
21604
  return Effect.fail(orgErrorFromCapxul("createOrg", Errors.notImplemented("organizationSetup", "use onboarding.completeOrganization")));
@@ -21330,15 +21646,11 @@ var ConvexOrganizationAdapter = class {
21330
21646
  const orgId = String(input.orgId);
21331
21647
  return retryIdempotentRead(this.#convex.action(this.#fns.readTreasury, copyInvocationObservation(input, { orgId })), CAPXUL_OPERATIONS.org.treasury, this.#telemetry, input).pipe(Effect.mapError((error) => orgErrorFromCapxul("readTreasury", error.publicError, error)), Effect.map((wire) => {
21332
21648
  if (wire.orgId !== orgId) throw Errors.invalidInput("orgId", "Organization treasury scope does not match");
21333
- const balance = fromWei(wire.rawBalance, wire.decimals, wire.currency);
21334
- const available = fromWei(wire.rawAvailableBalance, wire.decimals, wire.currency);
21335
- return {
21336
- ...brandOrgTreasury({
21337
- orgId: wire.orgId,
21338
- money: balance
21339
- }),
21340
- available
21341
- };
21649
+ return brandOrgTreasury({
21650
+ orgId: wire.orgId,
21651
+ balances: accountPositionsFromWire(wire.positions),
21652
+ rates: this.#rates
21653
+ });
21342
21654
  }));
21343
21655
  }
21344
21656
  };
@@ -45926,6 +46238,157 @@ function makeAuthMethods(deps) {
45926
46238
  };
45927
46239
  }
45928
46240
  //#endregion
46241
+ //#region ../../packages/sdk/src/surface/client-requests.ts
46242
+ function decodeView(body) {
46243
+ try {
46244
+ return {
46245
+ ok: true,
46246
+ value: Schema.decodeUnknownSync(ClientRequestViewSchema)(body)
46247
+ };
46248
+ } catch {
46249
+ return {
46250
+ ok: false,
46251
+ error: Errors.invalidInput("clientRequest", "view is not a closed phase")
46252
+ };
46253
+ }
46254
+ }
46255
+ function httpError$1(status) {
46256
+ if (status === 401) return {
46257
+ ok: false,
46258
+ error: Errors.notAuthenticated()
46259
+ };
46260
+ if (status === 404) return {
46261
+ ok: false,
46262
+ error: Errors.invalidInput("requestId", "is not a live request")
46263
+ };
46264
+ if (status === 429) return {
46265
+ ok: false,
46266
+ error: Errors.rateLimited({ resource: "clientRequest" })
46267
+ };
46268
+ return {
46269
+ ok: false,
46270
+ error: Errors.networkError("clientRequests")
46271
+ };
46272
+ }
46273
+ function makeClientRequestMethods(deps) {
46274
+ const fetchImpl = deps.fetch ?? fetch;
46275
+ const urlFor = (path, query) => {
46276
+ const resolved = resolveAuthClientUrl(deps.authBaseUrl, path);
46277
+ return query === void 0 ? resolved : `${resolved}?${query}`;
46278
+ };
46279
+ async function readView(requestId, options) {
46280
+ if (options?.signal?.aborted) return {
46281
+ ok: false,
46282
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.clientRequests.read })
46283
+ };
46284
+ try {
46285
+ const response = await fetchImpl(urlFor("/api/auth/native/request", `requestId=${encodeURIComponent(requestId)}`), {
46286
+ method: "GET",
46287
+ credentials: "include",
46288
+ ...options?.signal === void 0 ? {} : { signal: options.signal }
46289
+ });
46290
+ const body = await response.json().catch(() => null);
46291
+ if (!response.ok) {
46292
+ const viewed = decodeView(body);
46293
+ return viewed.ok ? viewed : httpError$1(response.status);
46294
+ }
46295
+ return decodeView(body);
46296
+ } catch (cause) {
46297
+ if (options?.signal?.aborted) return {
46298
+ ok: false,
46299
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.clientRequests.read })
46300
+ };
46301
+ if (isCapxulError(cause)) return {
46302
+ ok: false,
46303
+ error: cause
46304
+ };
46305
+ return {
46306
+ ok: false,
46307
+ error: Errors.networkError("native request read failed")
46308
+ };
46309
+ }
46310
+ }
46311
+ async function postDecision(path, input, options) {
46312
+ if (options?.signal?.aborted) return {
46313
+ ok: false,
46314
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.clientRequests.decide })
46315
+ };
46316
+ try {
46317
+ const response = await fetchImpl(urlFor(path), {
46318
+ method: "POST",
46319
+ credentials: "include",
46320
+ headers: { "content-type": "application/json" },
46321
+ body: JSON.stringify({
46322
+ requestId: input.requestId,
46323
+ revision: input.revision
46324
+ }),
46325
+ ...options?.signal === void 0 ? {} : { signal: options.signal }
46326
+ });
46327
+ const viewed = decodeView(await response.json().catch(() => null));
46328
+ if (viewed.ok) return viewed;
46329
+ if (!response.ok) return httpError$1(response.status);
46330
+ return viewed;
46331
+ } catch (cause) {
46332
+ if (options?.signal?.aborted) return {
46333
+ ok: false,
46334
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.clientRequests.decide })
46335
+ };
46336
+ if (isCapxulError(cause)) return {
46337
+ ok: false,
46338
+ error: cause
46339
+ };
46340
+ return {
46341
+ ok: false,
46342
+ error: Errors.networkError("native request decision failed")
46343
+ };
46344
+ }
46345
+ }
46346
+ return {
46347
+ read: (input, options) => readView(input.requestId, options),
46348
+ async sendOtp(input, options) {
46349
+ const view = await readView(input.requestId, options);
46350
+ if (!view.ok) return view;
46351
+ if (view.value.phase !== "otp_required" && view.value.phase !== "review") return {
46352
+ ok: false,
46353
+ error: Errors.wrongState({
46354
+ method: "clientRequests.sendOtp",
46355
+ currentState: view.value.phase,
46356
+ validStates: ["otp_required", "review"]
46357
+ })
46358
+ };
46359
+ const sent = await deps.signIn({ email: view.value.email }, options);
46360
+ if (!sent.ok) return sent;
46361
+ return {
46362
+ ok: true,
46363
+ value: void 0
46364
+ };
46365
+ },
46366
+ async verifyOtp(input, options) {
46367
+ const view = await readView(input.requestId, options);
46368
+ if (!view.ok) return view;
46369
+ if (view.value.phase !== "otp_required" && view.value.phase !== "review") return {
46370
+ ok: false,
46371
+ error: Errors.wrongState({
46372
+ method: "clientRequests.verifyOtp",
46373
+ currentState: view.value.phase,
46374
+ validStates: ["otp_required", "review"]
46375
+ })
46376
+ };
46377
+ const verified = await deps.verifyOtp({
46378
+ email: view.value.email,
46379
+ code: input.code
46380
+ }, options);
46381
+ if (!verified.ok) return verified;
46382
+ return {
46383
+ ok: true,
46384
+ value: void 0
46385
+ };
46386
+ },
46387
+ accept: (input, options) => postDecision("/api/auth/native/request/accept", input, options),
46388
+ cancel: (input, options) => postDecision("/api/auth/native/request/deny", input, options)
46389
+ };
46390
+ }
46391
+ //#endregion
45929
46392
  //#region ../../packages/sdk/src/surface/smart-account-deps.ts
45930
46393
  /** The single Context tag the `smartAccount.*` methods resolve. */
45931
46394
  var SmartAccountDepsTag = class extends Context.Service()("@capxul/sdk/SmartAccountDeps") {};
@@ -47298,18 +47761,15 @@ var OrgDepsTag = class extends Context.Service()("@capxul/sdk/OrgDeps") {};
47298
47761
  function orgDepsLayer(deps) {
47299
47762
  return Layer.succeed(OrgDepsTag, deps);
47300
47763
  }
47301
- /** Zero `Money` in the USDX-backed display currency (a fresh Org's treasury). */
47302
- function zeroMoney() {
47303
- return fromWei("0", 6, "USD");
47304
- }
47305
- /** A fresh Org's treasury Account: `$0` balance, `available === balance`. */
47764
+ /** A fresh Org's treasury Account: a zero position per settlement asset. */
47306
47765
  function zeroTreasury(orgId) {
47307
- const balance = zeroMoney();
47308
- return {
47309
- id: toAccountId(`account_${stripPrefix(orgId)}`),
47310
- balance,
47311
- available: balance
47312
- };
47766
+ return accountFromAccountPositions(toAccountId(`account_${stripPrefix(orgId)}`), CONFIGURED_MONEY_ASSETS.map((asset) => ({
47767
+ asset: asset.assetId,
47768
+ symbol: asset.symbol,
47769
+ decimals: asset.decimals,
47770
+ balance: "0",
47771
+ available: "0"
47772
+ })), void 0, MONEY_READ_RATES);
47313
47773
  }
47314
47774
  /** Drop a known `<prefix>_` so the remainder is reusable as another brand seed. */
47315
47775
  function stripPrefix(value) {
@@ -47717,8 +48177,7 @@ function makeOrgMethods(deps) {
47717
48177
  return {
47718
48178
  id: treasuryResult.value.id,
47719
48179
  address: org?.safeAddress ?? null,
47720
- balance: treasuryResult.value.balance,
47721
- available: treasuryResult.value.available
48180
+ balances: treasuryResult.value.balances
47722
48181
  };
47723
48182
  }), observationOnlyControls(controls), CAPXUL_OPERATIONS.org.account.get, deps.runPromise);
47724
48183
  } },
@@ -47822,23 +48281,27 @@ const organizationPaymentExecutionUnavailable = () => Promise.resolve({
47822
48281
  const holdingsContract = { current: makeFunctionReference(CAPXUL_FUNCTIONS["holdings/actions"].current) };
47823
48282
  //#endregion
47824
48283
  //#region ../../packages/sdk/src/domain/money/primary-holding.ts
47825
- const CURRENCY_BY_TOKEN_SYMBOL = /* @__PURE__ */ new Map([["USDX", toCurrencyCode("USD")]]);
47826
48284
  /**
47827
- * The designated display asset: the payable row holding the most money, or
47828
- * `null` when no row is payable.
48285
+ * The designated display asset: the LOWEST `id` among the renderable rows, or
48286
+ * `null` when no row is renderable.
47829
48287
  *
47830
- * A `HoldingRow` (`packages/wire/src/money.ts`) is a RAW CHAIN ROW, and three
47831
- * of its shapes cannot become a `Holding`. Each is SKIPPED rather than
47832
- * reported, because a row nobody can render is not a failure of the read:
48288
+ * A `HoldingRow` (`packages/wire/src/money.ts`) is a RAW CHAIN ROW. A native
48289
+ * row has no ERC-20 identity; a row with no `decimals` cannot be lifted into
48290
+ * major units; a row with no `symbol` cannot be named. Each is SKIPPED rather
48291
+ * than reported — a row nobody can render is not a failure of the read.
47833
48292
  *
47834
- * - no `decimals` — the raw balance cannot be lifted into major units;
47835
- * - no `symbol` — the asset cannot be named;
47836
- * - a symbol that stands for no supported `CurrencyCode` — the balance
47837
- * cannot be stated as `Money` without inventing a currency for it.
48293
+ * WHICH row is named is decided by ASSET IDENTITY — ascending `id` — never by
48294
+ * quantity. Two rows with different assets are not comparable money, so no
48295
+ * quantity can order them: 100 USDC is not "more" than 1 WETH without a rate,
48296
+ * and ranking major units would show whatever asset happens to have the most
48297
+ * decimal places as "primary". An identity order is arbitrary as well, but it
48298
+ * is stable and claims nothing about value. ADR-0028 R6 retires
48299
+ * `holdings.primary` outright; this export stays only until that retirement
48300
+ * lands with its remaining consumers, so no new policy is invented here.
47838
48301
  *
47839
48302
  * This replaces the app's hand pick in `formatCurrentHoldingsBalance`
47840
48303
  * (`dashboard-formatters.ts`): a `.find()` over a hardcoded `["USDX","USDC"]`
47841
- * list falling back to `rows[0]`. Ties keep the earlier row, so the same
48304
+ * list falling back to `rows[0]`. Duplicate ids keep the first row, so the same
47842
48305
  * snapshot always yields the same answer.
47843
48306
  */
47844
48307
  function primaryHolding(rows) {
@@ -47846,37 +48309,21 @@ function primaryHolding(rows) {
47846
48309
  for (const row of rows) {
47847
48310
  const holding = toHolding(row);
47848
48311
  if (holding === null) continue;
47849
- if (primary === null || compareDecimal(holding.available.value, primary.available.value) > 0) primary = holding;
48312
+ if (primary === null || holding.id < primary.id) primary = holding;
47850
48313
  }
47851
48314
  return primary;
47852
48315
  }
47853
48316
  function toHolding(row) {
48317
+ if (row.assetKind !== "erc20") return null;
47854
48318
  if (row.symbol === void 0 || row.decimals === void 0) return null;
47855
- const currency = currencyForTokenSymbol(row.symbol);
47856
- if (currency === null) return null;
47857
48319
  return {
47858
- id: row.assetKind === "native" ? "native" : row.tokenAddress.toLowerCase(),
48320
+ id: row.tokenAddress.toLowerCase(),
48321
+ assetKind: row.assetKind,
47859
48322
  symbol: row.symbol,
47860
- available: fromWei(row.rawBalance, row.decimals, currency)
48323
+ decimals: row.decimals,
48324
+ value: formatUnits(BigInt(row.rawBalance), row.decimals)
47861
48325
  };
47862
48326
  }
47863
- function currencyForTokenSymbol(symbol) {
47864
- return CURRENCY_BY_TOKEN_SYMBOL.get(symbol.toUpperCase()) ?? null;
47865
- }
47866
- /**
47867
- * Order two non-negative major-unit decimal strings without converting either
47868
- * to a JavaScript number. Rows carry different `decimals`, so the raw integers
47869
- * are not comparable: 1999999999 at 9 decimals is LESS than 2000000 at 6.
47870
- */
47871
- function compareDecimal(first, second) {
47872
- const [firstWhole = "0", firstFraction = ""] = first.split(".");
47873
- const [secondWhole = "0", secondFraction = ""] = second.split(".");
47874
- const width = Math.max(firstFraction.length, secondFraction.length);
47875
- const firstScaled = BigInt(firstWhole + firstFraction.padEnd(width, "0"));
47876
- const secondScaled = BigInt(secondWhole + secondFraction.padEnd(width, "0"));
47877
- if (firstScaled === secondScaled) return 0;
47878
- return firstScaled < secondScaled ? -1 : 1;
47879
- }
47880
48327
  //#endregion
47881
48328
  //#region ../../packages/sdk/src/surface/holdings.ts
47882
48329
  /** SPEC Freshness: past this block age the read is labelled stale. Nothing refuses. */
@@ -48325,6 +48772,7 @@ const closeClientResources = (close) => toCapxulResult(Effect.promise(close), La
48325
48772
  function assembleCapxulClient(input) {
48326
48773
  const observation = input;
48327
48774
  const authCache = input.authCache ?? detectAuthCacheAdapter();
48775
+ const accountSetup = input.accountSetup ?? "automatic";
48328
48776
  const effectRunner = input.effectRunner ?? {
48329
48777
  runSync: Effect.runSync,
48330
48778
  runPromise: Effect.runPromise
@@ -48395,7 +48843,7 @@ function assembleCapxulClient(input) {
48395
48843
  });
48396
48844
  kickProvisioning = accountBundle.kickProvisioning;
48397
48845
  const account = accountBundle.methods;
48398
- const auth = makeAuthMethods({
48846
+ const authCore = makeAuthMethods({
48399
48847
  actor,
48400
48848
  authClient: input.ports.authClient,
48401
48849
  authCache,
@@ -48413,10 +48861,19 @@ function assembleCapxulClient(input) {
48413
48861
  }
48414
48862
  if (browserSigner.statusStore?.status() === "unknown" && typeof browserSigner.ensureWalletReady === "function") browserSigner.ensureWalletReady().catch(() => {});
48415
48863
  }
48864
+ if (accountSetup === "explicit") return;
48416
48865
  await detectPendingOrgInvitations?.();
48417
48866
  kickProvisioning?.();
48418
48867
  }
48419
48868
  });
48869
+ const auth = {
48870
+ ...authCore,
48871
+ clientRequests: makeClientRequestMethods({
48872
+ authBaseUrl: input.bootstrap.authBaseUrl,
48873
+ signIn: authCore.signIn,
48874
+ verifyOtp: authCore.verifyOtp
48875
+ })
48876
+ };
48420
48877
  const smartAccount = makeSmartAccountMethods({
48421
48878
  actor,
48422
48879
  smartAccountPort: input.ports.smartAccount,
@@ -48580,6 +49037,7 @@ function assembleCapxulClient(input) {
48580
49037
  ...input.ports.indexerRead === void 0 ? {} : { indexer: input.ports.indexerRead },
48581
49038
  organizationSetup: { getProofReceipt: (orgId) => runPortEffect(input.ports.convexCall.query(organizationSetupProofReceiptQuery, { orgId })) },
48582
49039
  telemetry: input.ports.telemetry,
49040
+ accountSetup,
48583
49041
  captureExternalAddressAcknowledged: (address, organizationId) => {
48584
49042
  const telemetry = input.ports.telemetry;
48585
49043
  if (telemetry === void 0) return;
@@ -49727,6 +50185,7 @@ async function createCapxulClientWithSignerControls(input, controls) {
49727
50185
  bootstrap: adapters.value.bootstrap,
49728
50186
  authCache: adapters.value.ports.authCache,
49729
50187
  requirement: input.requirement ?? "none",
50188
+ accountSetup: input.accountSetup,
49730
50189
  ...signer === void 0 ? {} : { signer },
49731
50190
  orgPort: Context.get(adapters.value.context, OrgPortTag),
49732
50191
  ...signer === void 0 ? {} : { organizationSetup: new ConvexOrganizationSetupAdapter({
@@ -50548,7 +51007,7 @@ function stdioIdentity(env = process.env, options = {}) {
50548
51007
  }
50549
51008
  //#endregion
50550
51009
  //#region package.json
50551
- var version = "4.20.0-beta.3";
51010
+ var version = "4.20.0-beta.5";
50552
51011
  //#endregion
50553
51012
  //#region src/deps.ts
50554
51013
  const NO_IDENTITY = async () => void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capxul/mcp",
3
- "version": "4.20.0-beta.3",
3
+ "version": "4.20.0-beta.5",
4
4
  "private": false,
5
5
  "description": "Capxul MCP server for auth, Account readiness, identity, Organizations, relationships, requests, destinations, and testnet funding over Streamable HTTP.",
6
6
  "keywords": [
@@ -51,8 +51,8 @@
51
51
  "vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
52
52
  "vite-plus": "0.3.0",
53
53
  "@capxul/config": "0.3.0",
54
- "@capxul/typescript-config": "0.0.0",
55
- "@capxul/sdk": "4.20.0-beta.3"
54
+ "@capxul/sdk": "4.20.0-beta.5",
55
+ "@capxul/typescript-config": "0.0.0"
56
56
  },
57
57
  "scripts": {
58
58
  "dev": "vp exec tsx src/main.ts serve",