otto-execute 0.1.0
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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/cdp-signer.d.ts +2 -0
- package/dist/cdp-signer.js +3 -0
- package/dist/cdp.d.ts +7 -0
- package/dist/cdp.js +8 -0
- package/dist/chain.d.ts +2 -0
- package/dist/chain.js +3 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +400 -0
- package/dist/delegate.d.ts +117 -0
- package/dist/delegate.js +394 -0
- package/dist/eoa-signer.d.ts +94 -0
- package/dist/eoa-signer.js +289 -0
- package/dist/erc20.d.ts +2 -0
- package/dist/erc20.js +3 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +19 -0
- package/dist/lifi-decode.d.ts +2 -0
- package/dist/lifi-decode.js +3 -0
- package/dist/mutations.d.ts +55 -0
- package/dist/mutations.js +363 -0
- package/dist/refusal.d.ts +2 -0
- package/dist/refusal.js +3 -0
- package/dist/vendor/otto-intel-mcp/VENDORED.json +52 -0
- package/dist/vendor/otto-intel-mcp/adapter/cdp-signer.d.ts +133 -0
- package/dist/vendor/otto-intel-mcp/adapter/cdp-signer.js +356 -0
- package/dist/vendor/otto-intel-mcp/adapter/chain.d.ts +36 -0
- package/dist/vendor/otto-intel-mcp/adapter/chain.js +65 -0
- package/dist/vendor/otto-intel-mcp/adapter/erc20.d.ts +39 -0
- package/dist/vendor/otto-intel-mcp/adapter/erc20.js +17 -0
- package/dist/vendor/otto-intel-mcp/adapter/lifi-decode.d.ts +52 -0
- package/dist/vendor/otto-intel-mcp/adapter/lifi-decode.js +149 -0
- package/dist/vendor/otto-intel-mcp/adapter/refusal.d.ts +21 -0
- package/dist/vendor/otto-intel-mcp/adapter/refusal.js +55 -0
- package/dist/vendor/otto-intel-mcp/adapter/sent-step.d.ts +15 -0
- package/dist/vendor/otto-intel-mcp/adapter/sent-step.js +6 -0
- package/dist/vendor/otto-intel-mcp/adapter/verify.d.ts +149 -0
- package/dist/vendor/otto-intel-mcp/adapter/verify.js +432 -0
- package/dist/vendor/otto-intel-mcp/adapter-cdp-index.d.ts +6 -0
- package/dist/vendor/otto-intel-mcp/adapter-cdp-index.js +7 -0
- package/dist/vendor/otto-intel-mcp/adapter-index.d.ts +15 -0
- package/dist/vendor/otto-intel-mcp/adapter-index.js +15 -0
- package/dist/vendor/otto-intel-mcp/artifact-id.d.ts +16 -0
- package/dist/vendor/otto-intel-mcp/artifact-id.js +60 -0
- package/dist/vendor/otto-intel-mcp/execution-config.d.ts +232 -0
- package/dist/vendor/otto-intel-mcp/execution-config.js +443 -0
- package/dist/vendor/otto-intel-mcp/execution-delegated-definition.d.ts +165 -0
- package/dist/vendor/otto-intel-mcp/execution-delegated-definition.js +116 -0
- package/dist/vendor/otto-intel-mcp/execution-delegation-admin-definition.d.ts +208 -0
- package/dist/vendor/otto-intel-mcp/execution-delegation-admin-definition.js +170 -0
- package/dist/vendor/otto-intel-mcp/execution-delegation-policy.d.ts +257 -0
- package/dist/vendor/otto-intel-mcp/execution-delegation-policy.js +279 -0
- package/dist/vendor/otto-intel-mcp/execution-errors.d.ts +9 -0
- package/dist/vendor/otto-intel-mcp/execution-errors.js +134 -0
- package/dist/vendor/otto-intel-mcp/execution-index.d.ts +17 -0
- package/dist/vendor/otto-intel-mcp/execution-index.js +16 -0
- package/dist/vendor/otto-intel-mcp/execution-intent.d.ts +14 -0
- package/dist/vendor/otto-intel-mcp/execution-intent.js +36 -0
- package/dist/vendor/otto-intel-mcp/execution-tool-definitions.d.ts +1103 -0
- package/dist/vendor/otto-intel-mcp/execution-tool-definitions.js +1051 -0
- package/dist/vendor/otto-intel-mcp/execution-types.d.ts +274 -0
- package/dist/vendor/otto-intel-mcp/execution-types.js +157 -0
- package/dist/verify.d.ts +2 -0
- package/dist/verify.js +3 -0
- package/dist/x402-table.d.ts +99 -0
- package/dist/x402-table.js +221 -0
- package/package.json +97 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402-table.ts — the expected-requirements table for x402 challenges (docs/0817_x402_leg_expected_requirements_table.md).
|
|
3
|
+
*
|
|
4
|
+
* In Model B the user's own adapter signs x402 payments. Before a challenge reaches that signer, every
|
|
5
|
+
* field the user is about to authorize payment against is checked against THIS static table — never
|
|
6
|
+
* derived from the incoming challenge. The failure this prevents: an altered or substituted 402 redirecting
|
|
7
|
+
* the payment to a substituted recipient, an inflated amount, or a long-lived authorization.
|
|
8
|
+
*
|
|
9
|
+
* Rules (0817 §2):
|
|
10
|
+
* - exact match, one canonical URL normalization (scheme+host lowercase, no trailing slash);
|
|
11
|
+
* addresses compared checksummed; amounts as BigInt atomic units, never floats.
|
|
12
|
+
* - unknown resource ⇒ refuse. The table is an allowlist.
|
|
13
|
+
* - the table is data, the check is code: adding a row never touches validation.
|
|
14
|
+
* - P3: rows are exact values — the type admits no pattern, prefix or regex field.
|
|
15
|
+
* - P4: fail-closed — a validation failure throws; nothing reaches the signer.
|
|
16
|
+
* - the validated requirement is returned as an IMMUTABLE snapshot, and the signer revalidates the
|
|
17
|
+
* document against the table again immediately before it signs (see eoa-signer.ts): validation
|
|
18
|
+
* and hand-off are two moments, and nothing that happens in between is trusted.
|
|
19
|
+
*/
|
|
20
|
+
import { getAddress } from 'viem';
|
|
21
|
+
export const X402_TABLE_VERSION = 'x402-req-2026-08-28-v4'; // v4: /base-season 1000 → 2000 (Phase-3 floor experiment, live 2026-08-27T23:07:40Z)
|
|
22
|
+
/** Otto's published x402 revenue recipient of record (captured live 2026-08-25/26 from all four challenges). */
|
|
23
|
+
export const OTTO_X402_PAY_TO = getAddress('0x0E84dDEdAaE6A779c462C22a59F301EC31B6b808');
|
|
24
|
+
export const BASE_USDC = getAddress('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
25
|
+
const ONE_MILLI_USDC = '1000';
|
|
26
|
+
/** /base-season since the Phase-3 floor experiment (live 2026-08-27T23:07:40Z; fixture re-captured 2026-08-27T23:13:08Z). */
|
|
27
|
+
const TWO_MILLI_USDC = '2000';
|
|
28
|
+
/**
|
|
29
|
+
* Rows whose SERVED price is changing on the storefront (catalog.ts already carries the new price)
|
|
30
|
+
* but whose live capture in test/fixtures has not been re-captured yet. This table is an EXACT
|
|
31
|
+
* match against a signed live 402, so it can only move AFTER the backend deploys the new price and
|
|
32
|
+
* the fixture is re-captured — between those two moments the adapter REFUSES the row (fail-closed,
|
|
33
|
+
* never an overpay). `scripts/audit/client-price-caps.mjs` downgrades these rows to a warning until
|
|
34
|
+
* the re-capture PR clears them; it hard-fails any other table/catalog mismatch, and it fails a
|
|
35
|
+
* declaration that lingers after the table already matches (so this list cannot go stale).
|
|
36
|
+
* EMPTY = every row's table amount equals its live capture and the catalog price.
|
|
37
|
+
*/
|
|
38
|
+
export const PENDING_RECAPTURE = Object.freeze([]);
|
|
39
|
+
/** Observed on every live challenge (2026-08-25/26). Any other window is refused — exact match, like every field. */
|
|
40
|
+
const OBSERVED_MAX_TIMEOUT_SECONDS = 300;
|
|
41
|
+
const USDC_DOMAIN = Object.freeze({ name: 'USD Coin', version: '2' });
|
|
42
|
+
function row(path, amountAtomic) {
|
|
43
|
+
return Object.freeze({
|
|
44
|
+
resource: `https://x402.ottoai.services/${path}`,
|
|
45
|
+
scheme: 'exact',
|
|
46
|
+
network: 'eip155:8453',
|
|
47
|
+
asset: BASE_USDC,
|
|
48
|
+
pay_to: OTTO_X402_PAY_TO,
|
|
49
|
+
amount_atomic: amountAtomic,
|
|
50
|
+
max_timeout_seconds: OBSERVED_MAX_TIMEOUT_SECONDS,
|
|
51
|
+
extra: USDC_DOMAIN,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** The no-argument intelligence resources the proof may pay for ($0.001 reads; /base-season $0.002). Every row has a live capture in test/fixtures. */
|
|
55
|
+
export const X402_TABLE = Object.freeze({
|
|
56
|
+
table_version: X402_TABLE_VERSION,
|
|
57
|
+
rows: Object.freeze([
|
|
58
|
+
row('pm-crypto', ONE_MILLI_USDC),
|
|
59
|
+
row('pm-markets', ONE_MILLI_USDC),
|
|
60
|
+
row('base-season', TWO_MILLI_USDC),
|
|
61
|
+
row('rh-season', ONE_MILLI_USDC),
|
|
62
|
+
]),
|
|
63
|
+
});
|
|
64
|
+
export const X402_REFUSAL_CODES = [
|
|
65
|
+
'X402_MALFORMED',
|
|
66
|
+
'X402_UNKNOWN_RESOURCE',
|
|
67
|
+
'X402_SCHEME_MISMATCH',
|
|
68
|
+
'X402_NETWORK_MISMATCH',
|
|
69
|
+
'X402_ASSET_MISMATCH',
|
|
70
|
+
'X402_PAYTO_MISMATCH',
|
|
71
|
+
'X402_AMOUNT_EXCEEDED',
|
|
72
|
+
'X402_TIMEOUT_EXCEEDED',
|
|
73
|
+
'X402_DOMAIN_MISMATCH',
|
|
74
|
+
/**
|
|
75
|
+
* The row matched the table but the amount exceeds the INDEPENDENT per-payment spend cap
|
|
76
|
+
* (`@x402/core` client spend controls). Distinct from X402_AMOUNT_EXCEEDED, which means the
|
|
77
|
+
* challenge disagreed with the table: this one means the table itself asked for more than the
|
|
78
|
+
* budget allows — the condition a table price typo produces, which no table check can catch
|
|
79
|
+
* because the table is the reference being checked against.
|
|
80
|
+
*/
|
|
81
|
+
'X402_SPEND_LIMIT_EXCEEDED',
|
|
82
|
+
];
|
|
83
|
+
export class X402Refusal extends Error {
|
|
84
|
+
code;
|
|
85
|
+
field;
|
|
86
|
+
expected;
|
|
87
|
+
actual;
|
|
88
|
+
tableVersion;
|
|
89
|
+
errorType;
|
|
90
|
+
constructor(code, field, expected, actual, tableVersion) {
|
|
91
|
+
super(`[${code}] ${field}: expected ${expected}, challenge carries ${actual} (table ${tableVersion})`);
|
|
92
|
+
this.code = code;
|
|
93
|
+
this.field = field;
|
|
94
|
+
this.expected = expected;
|
|
95
|
+
this.actual = actual;
|
|
96
|
+
this.tableVersion = tableVersion;
|
|
97
|
+
this.name = 'X402Refusal';
|
|
98
|
+
this.errorType = code;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function canonicalResourceUrl(raw) {
|
|
102
|
+
const url = new URL(raw);
|
|
103
|
+
url.protocol = url.protocol.toLowerCase();
|
|
104
|
+
url.hostname = url.hostname.toLowerCase();
|
|
105
|
+
url.hash = '';
|
|
106
|
+
let out = url.toString();
|
|
107
|
+
if (url.search === '' && out.endsWith('/'))
|
|
108
|
+
out = out.slice(0, -1);
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function record(value) {
|
|
112
|
+
return typeof value === 'object' && value !== null ? value : undefined;
|
|
113
|
+
}
|
|
114
|
+
function malformed(field, actual) {
|
|
115
|
+
throw new X402Refusal('X402_MALFORMED', field, 'a well-formed x402 v2 PaymentRequired document', actual, X402_TABLE_VERSION);
|
|
116
|
+
}
|
|
117
|
+
/** True iff `requirement` carries exactly the row's bound fields (checksummed addresses, exact amount, window ≤ ceiling, pinned domain). */
|
|
118
|
+
export function requirementMatchesRow(requirement, row) {
|
|
119
|
+
return mismatch(requirement, row, X402_TABLE_VERSION) === undefined;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Validate an x402 v2 PaymentRequired document against the table. Returns the single accepted
|
|
123
|
+
* requirement that matches its row exactly (as an immutable snapshot), or throws the refusal naming
|
|
124
|
+
* the first mismatched field.
|
|
125
|
+
*/
|
|
126
|
+
export function validateX402Challenge(paymentRequired, table = X402_TABLE) {
|
|
127
|
+
const document = record(paymentRequired);
|
|
128
|
+
if (!document)
|
|
129
|
+
malformed('document', typeof paymentRequired);
|
|
130
|
+
if (document.x402Version !== 2)
|
|
131
|
+
malformed('x402Version', String(document.x402Version));
|
|
132
|
+
const resource = record(document.resource);
|
|
133
|
+
if (typeof resource?.url !== 'string')
|
|
134
|
+
malformed('resource.url', 'missing');
|
|
135
|
+
const accepts = document.accepts;
|
|
136
|
+
if (!Array.isArray(accepts) || accepts.length === 0)
|
|
137
|
+
malformed('accepts', 'missing or empty');
|
|
138
|
+
const resourceUrl = canonicalResourceUrl(resource.url);
|
|
139
|
+
const matchedRow = table.rows.find((candidate) => canonicalResourceUrl(candidate.resource) === resourceUrl);
|
|
140
|
+
if (!matchedRow) {
|
|
141
|
+
throw new X402Refusal('X402_UNKNOWN_RESOURCE', 'resource', 'a listed resource', resourceUrl, table.table_version);
|
|
142
|
+
}
|
|
143
|
+
// Evaluate every accept; the first requirement to satisfy every field wins. If none does, the
|
|
144
|
+
// refusal names the FIRST field the closest candidate failed on, in precedence order.
|
|
145
|
+
let firstRefusal;
|
|
146
|
+
for (const [index, candidate] of accepts.entries()) {
|
|
147
|
+
const refusal = mismatch(candidate, matchedRow, table.table_version);
|
|
148
|
+
if (refusal) {
|
|
149
|
+
firstRefusal ??= refusal;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const requirement = candidate;
|
|
153
|
+
const extra = requirement.extra;
|
|
154
|
+
return Object.freeze({
|
|
155
|
+
row: matchedRow,
|
|
156
|
+
requirement: Object.freeze({
|
|
157
|
+
scheme: requirement.scheme,
|
|
158
|
+
network: requirement.network,
|
|
159
|
+
amount: requirement.amount,
|
|
160
|
+
asset: getAddress(requirement.asset),
|
|
161
|
+
payTo: getAddress(requirement.payTo),
|
|
162
|
+
maxTimeoutSeconds: requirement.maxTimeoutSeconds,
|
|
163
|
+
extra: Object.freeze({ name: extra.name, version: extra.version }),
|
|
164
|
+
}),
|
|
165
|
+
requirementIndex: index,
|
|
166
|
+
amount: BigInt(requirement.amount),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
throw firstRefusal ?? malformed('accepts', 'no evaluable requirement');
|
|
170
|
+
}
|
|
171
|
+
function mismatch(candidate, row, tableVersion) {
|
|
172
|
+
const requirement = record(candidate);
|
|
173
|
+
if (!requirement ||
|
|
174
|
+
typeof requirement.scheme !== 'string' ||
|
|
175
|
+
typeof requirement.network !== 'string' ||
|
|
176
|
+
typeof requirement.amount !== 'string' ||
|
|
177
|
+
typeof requirement.asset !== 'string' ||
|
|
178
|
+
typeof requirement.payTo !== 'string') {
|
|
179
|
+
return new X402Refusal('X402_MALFORMED', 'accepts[]', 'scheme/network/amount/asset/payTo strings', 'missing fields', tableVersion);
|
|
180
|
+
}
|
|
181
|
+
if (requirement.scheme !== row.scheme) {
|
|
182
|
+
return new X402Refusal('X402_SCHEME_MISMATCH', 'scheme', row.scheme, requirement.scheme, tableVersion);
|
|
183
|
+
}
|
|
184
|
+
if (requirement.network !== row.network) {
|
|
185
|
+
return new X402Refusal('X402_NETWORK_MISMATCH', 'network', row.network, requirement.network, tableVersion);
|
|
186
|
+
}
|
|
187
|
+
let asset;
|
|
188
|
+
try {
|
|
189
|
+
asset = getAddress(requirement.asset);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return new X402Refusal('X402_ASSET_MISMATCH', 'asset', row.asset, requirement.asset, tableVersion);
|
|
193
|
+
}
|
|
194
|
+
if (asset !== getAddress(row.asset)) {
|
|
195
|
+
return new X402Refusal('X402_ASSET_MISMATCH', 'asset', row.asset, requirement.asset, tableVersion);
|
|
196
|
+
}
|
|
197
|
+
let payTo;
|
|
198
|
+
try {
|
|
199
|
+
payTo = getAddress(requirement.payTo);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return new X402Refusal('X402_PAYTO_MISMATCH', 'payTo', row.pay_to, requirement.payTo, tableVersion);
|
|
203
|
+
}
|
|
204
|
+
if (payTo !== getAddress(row.pay_to)) {
|
|
205
|
+
return new X402Refusal('X402_PAYTO_MISMATCH', 'payTo', row.pay_to, requirement.payTo, tableVersion);
|
|
206
|
+
}
|
|
207
|
+
if (!/^\d+$/.test(requirement.amount) || BigInt(requirement.amount) !== BigInt(row.amount_atomic)) {
|
|
208
|
+
return new X402Refusal('X402_AMOUNT_EXCEEDED', 'amount', row.amount_atomic, requirement.amount, tableVersion);
|
|
209
|
+
}
|
|
210
|
+
const timeout = requirement.maxTimeoutSeconds;
|
|
211
|
+
if (typeof timeout !== 'number' || !Number.isSafeInteger(timeout) || timeout !== row.max_timeout_seconds) {
|
|
212
|
+
return new X402Refusal('X402_TIMEOUT_EXCEEDED', 'maxTimeoutSeconds', String(row.max_timeout_seconds), String(timeout), tableVersion);
|
|
213
|
+
}
|
|
214
|
+
const extra = record(requirement.extra);
|
|
215
|
+
const extraKeys = extra ? Object.keys(extra).sort().join(',') : '';
|
|
216
|
+
if (extraKeys !== 'name,version' || extra?.name !== row.extra.name || extra?.version !== row.extra.version) {
|
|
217
|
+
return new X402Refusal('X402_DOMAIN_MISMATCH', 'extra', `{name:${row.extra.name},version:${row.extra.version}} and nothing else`, `keys [${extraKeys}] ${String(extra?.name)}/${String(extra?.version)}`, tableVersion);
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=x402-table.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "otto-execute",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The user's side of Otto Model B: verify a prepare-only execution artifact from the Otto Intel MCP against your own intent and the ruled attribution, then sign and submit it with your own key (or under a delegation you minted). Otto never holds your keys or funds.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://docs.useotto.xyz",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://docs.useotto.xyz"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=22"
|
|
13
|
+
},
|
|
14
|
+
"devEngines": {
|
|
15
|
+
"runtime": {
|
|
16
|
+
"name": "node",
|
|
17
|
+
"version": "22.16.0",
|
|
18
|
+
"onFail": "warn"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"otto-execute": "./dist/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./cdp": {
|
|
30
|
+
"types": "./dist/cdp.d.ts",
|
|
31
|
+
"import": "./dist/cdp.js"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json",
|
|
34
|
+
"./delegate": {
|
|
35
|
+
"types": "./dist/delegate.d.ts",
|
|
36
|
+
"import": "./dist/delegate.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist/*.js",
|
|
41
|
+
"dist/*.d.ts",
|
|
42
|
+
"dist/vendor/otto-intel-mcp/**/*.js",
|
|
43
|
+
"dist/vendor/otto-intel-mcp/**/*.d.ts",
|
|
44
|
+
"dist/vendor/otto-intel-mcp/VENDORED.json",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.build.json && node scripts/vendor-seam.mjs",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"test": "node --import tsx --test \"test/**/*.test.ts\"",
|
|
52
|
+
"verify": "npm run typecheck && npm run build && npm test",
|
|
53
|
+
"prepublishOnly": "npm run verify",
|
|
54
|
+
"test:cli": "node --import tsx --test test/cli.test.ts",
|
|
55
|
+
"fixtures:capture": "tsx scripts/capture-envelopes.ts",
|
|
56
|
+
"fixtures:check": "tsx scripts/capture-envelopes.ts --check",
|
|
57
|
+
"prepack": "npm run verify && npm run vendor:check && npm run pack:audit",
|
|
58
|
+
"vendor:check": "node scripts/vendor-seam.mjs --check",
|
|
59
|
+
"pack:audit": "node scripts/pack-audit.mjs",
|
|
60
|
+
"smoke:install": "bash scripts/isolated-install-smoke.sh"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@x402/core": "2.23.0",
|
|
64
|
+
"@x402/evm": "2.23.0",
|
|
65
|
+
"viem": "2.55.2",
|
|
66
|
+
"zod": "4.4.3"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@coinbase/cdp-core": "0.0.120",
|
|
70
|
+
"@coinbase/cdp-sdk": "1.54.0",
|
|
71
|
+
"@types/node": "22.20.1",
|
|
72
|
+
"otto-intel-mcp": "0.1.1",
|
|
73
|
+
"react": "19.2.0",
|
|
74
|
+
"tsx": "4.23.1",
|
|
75
|
+
"typescript": "5.9.3"
|
|
76
|
+
},
|
|
77
|
+
"publishConfig": {
|
|
78
|
+
"access": "public"
|
|
79
|
+
},
|
|
80
|
+
"publishGate": "Publish shape (2026-09-01, seat-ruled): the otto-intel-mcp seam this package needs (/execution, /adapter, /adapter-cdp) is VENDORED file-for-file from the published otto-intel-mcp (devDependency, exact version) into dist/vendor at build time — a consumer installs this package + @x402/core + @x402/evm + viem + zod only; @coinbase/cdp-sdk stays an optional peer. dist/vendor/otto-intel-mcp/VENDORED.json records the version, registry integrity and per-file sha256; prepack re-derives it (vendor:check) and runs the privacy pack audit. Publication = the Founder's word: the seat flips `private` at publish time.",
|
|
81
|
+
"peerDependencies": {
|
|
82
|
+
"@coinbase/cdp-core": "0.0.120",
|
|
83
|
+
"@coinbase/cdp-sdk": "^1.54.0",
|
|
84
|
+
"react": "^19.0.0"
|
|
85
|
+
},
|
|
86
|
+
"peerDependenciesMeta": {
|
|
87
|
+
"@coinbase/cdp-sdk": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
90
|
+
"@coinbase/cdp-core": {
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
93
|
+
"react": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|