@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.
- package/dist/main.mjs +562 -103
- 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: "
|
|
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 = [
|
|
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.
|
|
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
|
-
|
|
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
|
-
}
|
|
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:
|
|
10915
|
-
verificationOrigin:
|
|
10916
|
-
}).annotate(strict).check(Schema.makeFilter((c) => c.keyEnvironment === (c.environment === "production" ? "live" : "test"), { message: "key environment must match the configured deployment" })).
|
|
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.
|
|
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
|
-
|
|
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
|
|
21187
|
-
* (the D3 RPC
|
|
21188
|
-
* partition yet (a fresh Org reads back
|
|
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
|
-
|
|
21334
|
-
|
|
21335
|
-
|
|
21336
|
-
|
|
21337
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
47308
|
-
|
|
47309
|
-
|
|
47310
|
-
|
|
47311
|
-
|
|
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
|
-
|
|
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
|
|
47828
|
-
* `null` when no row is
|
|
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
|
|
47831
|
-
*
|
|
47832
|
-
*
|
|
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
|
-
*
|
|
47835
|
-
*
|
|
47836
|
-
*
|
|
47837
|
-
*
|
|
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]`.
|
|
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 ||
|
|
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.
|
|
48320
|
+
id: row.tokenAddress.toLowerCase(),
|
|
48321
|
+
assetKind: row.assetKind,
|
|
47859
48322
|
symbol: row.symbol,
|
|
47860
|
-
|
|
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
|
|
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.
|
|
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
|
+
"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/
|
|
55
|
-
"@capxul/
|
|
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",
|