web3agent 0.1.0 → 0.2.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/README.md +112 -6
- package/WEB3_CONTEXT.md +79 -0
- package/dist/agdp/api.d.ts +65 -0
- package/dist/agdp/api.js +19 -0
- package/dist/chunk-4G55KHRO.js +63 -0
- package/dist/chunk-7ITJ5WGE.js +26 -0
- package/dist/{chunk-BF4PA46E.js → chunk-7QEKU2RP.js} +36 -4
- package/dist/chunk-B4LSSN7C.js +8914 -0
- package/dist/chunk-BJUU5ESI.js +1760 -0
- package/dist/chunk-ETI3ZR2C.js +90 -0
- package/dist/chunk-KPRIUALX.js +251 -0
- package/dist/cli.js +12807 -0
- package/dist/goat-XA66K7CZ.js +303 -0
- package/dist/index.d.ts +1450 -0
- package/dist/index.js +379 -38
- package/dist/managed-runtime-DCLqOBjp.d.ts +157 -0
- package/dist/mcp/index.d.ts +21 -0
- package/dist/mcp/index.js +276 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +15 -0
- package/dist/types-B_VpZGqQ.d.ts +174 -0
- package/dist/x402/client.d.ts +13 -0
- package/dist/x402/client.js +10 -0
- package/examples/root-api-smoke.mjs +30 -0
- package/examples/runtime-smoke.mjs +77 -0
- package/package.json +24 -9
- package/dist/chunk-4GQR4EEY.js +0 -8
- package/dist/init-DKWQSYDZ.js +0 -434
- package/dist/startup-PHXZQ2SL.js +0 -3912
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RESTRICTED_PLUGIN_CHAINS,
|
|
3
|
+
Web3AgentError,
|
|
4
|
+
assertAddress,
|
|
5
|
+
assertChainSupported,
|
|
6
|
+
buildGoatTools,
|
|
7
|
+
createPublicClientForRuntimeChain,
|
|
8
|
+
findRestrictedPlugin,
|
|
9
|
+
getChainForRuntime,
|
|
10
|
+
getConfirmedReceipt,
|
|
11
|
+
getRpcUrlForRuntimeChain,
|
|
12
|
+
getRuntimeConfigForChain,
|
|
13
|
+
loadPlugins,
|
|
14
|
+
lookupTokenByAddress
|
|
15
|
+
} from "./chunk-BJUU5ESI.js";
|
|
16
|
+
import "./chunk-KPRIUALX.js";
|
|
17
|
+
import "./chunk-7QEKU2RP.js";
|
|
18
|
+
|
|
19
|
+
// src/operations/goat-wallet.ts
|
|
20
|
+
import { encodeFunctionData, parseAbi } from "viem";
|
|
21
|
+
var erc20BalanceAbi = parseAbi(["function balanceOf(address account) view returns (uint256)"]);
|
|
22
|
+
function normalizeTypedDataTypes(types) {
|
|
23
|
+
const normalized = {};
|
|
24
|
+
for (const [typeName, entries] of Object.entries(types)) {
|
|
25
|
+
if (!Array.isArray(entries)) {
|
|
26
|
+
throw new Web3AgentError({
|
|
27
|
+
code: "GOAT_TOOL_ERROR",
|
|
28
|
+
message: `Typed data type ${typeName} must be an array`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
normalized[typeName] = entries.map((entry, index) => {
|
|
32
|
+
if (!entry || typeof entry !== "object") {
|
|
33
|
+
throw new Web3AgentError({
|
|
34
|
+
code: "GOAT_TOOL_ERROR",
|
|
35
|
+
message: `Typed data entry ${typeName}[${index}] must be an object`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const name = entry.name;
|
|
39
|
+
const type = entry.type;
|
|
40
|
+
if (typeof name !== "string" || typeof type !== "string") {
|
|
41
|
+
throw new Web3AgentError({
|
|
42
|
+
code: "GOAT_TOOL_ERROR",
|
|
43
|
+
message: `Typed data entry ${typeName}[${index}] must include string name/type`
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return { name, type };
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
var OperationPauseError = class extends Error {
|
|
52
|
+
constructor(action) {
|
|
53
|
+
super(`Operation paused for ${action.type}`);
|
|
54
|
+
this.action = action;
|
|
55
|
+
this.name = "OperationPauseError";
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var PreparedActionGoatWallet = class {
|
|
59
|
+
constructor(options) {
|
|
60
|
+
this.options = options;
|
|
61
|
+
const chain = getChainForRuntime(this.options.chainId);
|
|
62
|
+
this.publicClient = createPublicClientForRuntimeChain(this.options.chainId);
|
|
63
|
+
this.chain = {
|
|
64
|
+
type: "evm",
|
|
65
|
+
id: chain.id,
|
|
66
|
+
nativeCurrency: chain.nativeCurrency
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
publicClient;
|
|
70
|
+
chain;
|
|
71
|
+
transactionIndex = 0;
|
|
72
|
+
signTypedDataIndex = 0;
|
|
73
|
+
signMessageIndex = 0;
|
|
74
|
+
getAddress() {
|
|
75
|
+
return assertAddress(this.options.account, "account");
|
|
76
|
+
}
|
|
77
|
+
getChain() {
|
|
78
|
+
return this.chain;
|
|
79
|
+
}
|
|
80
|
+
getCoreTools() {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
async signMessage(message) {
|
|
84
|
+
const id = `sign-message:${this.signMessageIndex++}`;
|
|
85
|
+
const result = this.options.actionResults[id];
|
|
86
|
+
if (result?.type === "signature" || result?.type === "messageSignature") {
|
|
87
|
+
return { signature: result.signature };
|
|
88
|
+
}
|
|
89
|
+
throw new OperationPauseError({
|
|
90
|
+
id,
|
|
91
|
+
type: "signMessage",
|
|
92
|
+
label: "Sign message",
|
|
93
|
+
chainId: this.options.chainId,
|
|
94
|
+
message
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async signTypedData(data) {
|
|
98
|
+
const id = `sign-typed-data:${this.signTypedDataIndex++}`;
|
|
99
|
+
const result = this.options.actionResults[id];
|
|
100
|
+
if (result?.type === "signature") {
|
|
101
|
+
return { signature: result.signature };
|
|
102
|
+
}
|
|
103
|
+
throw new OperationPauseError({
|
|
104
|
+
id,
|
|
105
|
+
type: "signTypedData",
|
|
106
|
+
label: "Sign typed data",
|
|
107
|
+
chainId: this.options.chainId,
|
|
108
|
+
eip712: {
|
|
109
|
+
domain: data.domain,
|
|
110
|
+
types: normalizeTypedDataTypes(data.types),
|
|
111
|
+
primaryType: data.primaryType,
|
|
112
|
+
message: data.message
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async sendTransaction(transaction) {
|
|
117
|
+
const id = `transaction:${this.transactionIndex++}`;
|
|
118
|
+
const result = this.options.actionResults[id];
|
|
119
|
+
if (result?.type === "transaction") {
|
|
120
|
+
const to2 = assertAddress(transaction.to, "transaction.to");
|
|
121
|
+
const action = {
|
|
122
|
+
id,
|
|
123
|
+
type: "transaction",
|
|
124
|
+
label: `Execute transaction to ${to2}`,
|
|
125
|
+
tx: {
|
|
126
|
+
to: to2,
|
|
127
|
+
chainId: this.options.chainId
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
await getConfirmedReceipt(action, result);
|
|
131
|
+
return { hash: result.txHash };
|
|
132
|
+
}
|
|
133
|
+
const to = assertAddress(transaction.to, "transaction.to");
|
|
134
|
+
const data = transaction.data ?? (transaction.abi && transaction.functionName ? encodeFunctionData({
|
|
135
|
+
abi: transaction.abi,
|
|
136
|
+
functionName: transaction.functionName,
|
|
137
|
+
args: transaction.args
|
|
138
|
+
}) : void 0);
|
|
139
|
+
throw new OperationPauseError({
|
|
140
|
+
id,
|
|
141
|
+
type: "transaction",
|
|
142
|
+
label: transaction.functionName ? `Execute ${transaction.functionName}` : `Execute transaction to ${to}`,
|
|
143
|
+
tx: {
|
|
144
|
+
to,
|
|
145
|
+
chainId: this.options.chainId,
|
|
146
|
+
...data ? { data } : {},
|
|
147
|
+
...transaction.value !== void 0 ? { value: transaction.value.toString() } : {}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async read(request) {
|
|
152
|
+
const value = await this.publicClient.readContract({
|
|
153
|
+
address: assertAddress(request.address, "read.address"),
|
|
154
|
+
abi: request.abi,
|
|
155
|
+
functionName: request.functionName,
|
|
156
|
+
...request.args ? { args: request.args } : {}
|
|
157
|
+
});
|
|
158
|
+
return { value };
|
|
159
|
+
}
|
|
160
|
+
async getNativeBalance() {
|
|
161
|
+
return this.publicClient.getBalance({
|
|
162
|
+
address: this.getAddress()
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
async balanceOf(address, tokenAddress) {
|
|
166
|
+
if (!tokenAddress) {
|
|
167
|
+
const value = await this.publicClient.getBalance({
|
|
168
|
+
address: assertAddress(address, "address")
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
value: value.toString(),
|
|
172
|
+
decimals: this.chain.nativeCurrency.decimals,
|
|
173
|
+
symbol: this.chain.nativeCurrency.symbol,
|
|
174
|
+
name: this.chain.nativeCurrency.name,
|
|
175
|
+
inBaseUnits: value.toString()
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const normalizedTokenAddress = assertAddress(tokenAddress, "tokenAddress");
|
|
179
|
+
const tokenBalance = await this.publicClient.readContract({
|
|
180
|
+
address: normalizedTokenAddress,
|
|
181
|
+
abi: erc20BalanceAbi,
|
|
182
|
+
functionName: "balanceOf",
|
|
183
|
+
args: [assertAddress(address, "address")]
|
|
184
|
+
});
|
|
185
|
+
const token = lookupTokenByAddress(normalizedTokenAddress, this.options.chainId);
|
|
186
|
+
return {
|
|
187
|
+
value: tokenBalance.toString(),
|
|
188
|
+
decimals: token?.decimals ?? 18,
|
|
189
|
+
symbol: token?.symbol ?? "UNKNOWN",
|
|
190
|
+
name: token?.name ?? "Unknown Token",
|
|
191
|
+
inBaseUnits: tokenBalance.toString()
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async getTokenInfoByTicker(ticker) {
|
|
195
|
+
const toolHint = this.options.toolName ? ` (triggered by ${this.options.toolName})` : "";
|
|
196
|
+
throw new Web3AgentError({
|
|
197
|
+
code: "GOAT_TOOL_ERROR",
|
|
198
|
+
message: `Token lookup by ticker is not supported in prepared GOAT mode (${ticker})${toolHint}; resolve token addresses before running prepared GOAT tools`
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/operations/goat.ts
|
|
204
|
+
function assertGoatToolSupportedOnChain(toolName, chainId) {
|
|
205
|
+
assertChainSupported(chainId);
|
|
206
|
+
const pluginKey = findRestrictedPlugin(toolName);
|
|
207
|
+
if (!pluginKey) return;
|
|
208
|
+
const availableChains = RESTRICTED_PLUGIN_CHAINS[pluginKey];
|
|
209
|
+
if (!availableChains.includes(chainId)) {
|
|
210
|
+
throw new Web3AgentError({
|
|
211
|
+
code: "TOOL_UNAVAILABLE_ON_CHAIN",
|
|
212
|
+
message: `${toolName} is not available on chain ${chainId}. Available on chains: ${availableChains.join(", ")}`,
|
|
213
|
+
details: { availableChainIds: availableChains }
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function toCompletedResult(result) {
|
|
218
|
+
if (result && typeof result === "object" && !Array.isArray(result)) {
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
value: result
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function loadGoatPluginsForChain(chainId) {
|
|
226
|
+
const config = getRuntimeConfigForChain(chainId);
|
|
227
|
+
return loadPlugins({
|
|
228
|
+
hasWallet: true,
|
|
229
|
+
zeroxApiKey: config.zeroxApiKey,
|
|
230
|
+
coingeckoApiKey: config.coingeckoApiKey,
|
|
231
|
+
rpcUrl: getRpcUrlForRuntimeChain(chainId, config)
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function createGoatPreparedOperation(params) {
|
|
235
|
+
const { input, tool, actionResults, pause } = params;
|
|
236
|
+
return {
|
|
237
|
+
integration: "goat",
|
|
238
|
+
kind: "tool",
|
|
239
|
+
summary: tool.description || `Prepare GOAT tool ${tool.name} on chain ${input.chainId}`,
|
|
240
|
+
actions: [pause.action],
|
|
241
|
+
resumeState: {
|
|
242
|
+
version: 1,
|
|
243
|
+
integration: "goat",
|
|
244
|
+
kind: "tool",
|
|
245
|
+
state: {
|
|
246
|
+
toolName: input.toolName,
|
|
247
|
+
params: input.params ?? {},
|
|
248
|
+
chainId: input.chainId,
|
|
249
|
+
account: input.account,
|
|
250
|
+
actionResults
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
meta: {
|
|
254
|
+
toolName: tool.name,
|
|
255
|
+
description: tool.description
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
async function prepareOrResumeGoatOperation(params) {
|
|
260
|
+
const actionResults = params.actionResults ?? {};
|
|
261
|
+
assertGoatToolSupportedOnChain(params.input.toolName, params.input.chainId);
|
|
262
|
+
const pluginResult = loadGoatPluginsForChain(params.input.chainId);
|
|
263
|
+
const wallet = new PreparedActionGoatWallet({
|
|
264
|
+
account: params.input.account,
|
|
265
|
+
chainId: params.input.chainId,
|
|
266
|
+
actionResults,
|
|
267
|
+
toolName: params.input.toolName
|
|
268
|
+
});
|
|
269
|
+
const tools = await buildGoatTools({
|
|
270
|
+
wallet,
|
|
271
|
+
pluginResult
|
|
272
|
+
});
|
|
273
|
+
const executableTool = tools.find((candidate) => candidate.name === params.input.toolName);
|
|
274
|
+
if (!executableTool) {
|
|
275
|
+
throw new Web3AgentError({
|
|
276
|
+
code: "UNKNOWN_TOOL",
|
|
277
|
+
message: `Unknown GOAT tool: ${params.input.toolName}`
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
const parsed = executableTool.parameters.parse(params.input.params ?? {});
|
|
282
|
+
const result = await executableTool.execute(parsed);
|
|
283
|
+
return {
|
|
284
|
+
completed: true,
|
|
285
|
+
integration: "goat",
|
|
286
|
+
kind: "tool",
|
|
287
|
+
result: toCompletedResult(result)
|
|
288
|
+
};
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (error instanceof OperationPauseError) {
|
|
291
|
+
return createGoatPreparedOperation({
|
|
292
|
+
input: params.input,
|
|
293
|
+
tool: executableTool,
|
|
294
|
+
actionResults,
|
|
295
|
+
pause: error
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
throw Web3AgentError.fromUnknown("GOAT_TOOL_ERROR", error);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
export {
|
|
302
|
+
prepareOrResumeGoatOperation
|
|
303
|
+
};
|