@agenticvault/openclaw 0.1.0 → 0.1.2
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.ja.md +66 -9
- package/README.ko.md +66 -9
- package/README.md +65 -8
- package/README.zh-CN.md +66 -9
- package/README.zh-TW.md +66 -9
- package/dist/context.js +5 -1
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +371 -254
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +3 -28
- package/openclaw.plugin.json +34 -7
- package/package.json +13 -3
package/dist/tools.js
CHANGED
|
@@ -1,314 +1,428 @@
|
|
|
1
|
-
import { signDefiCall, signPermit, getAddressWorkflow, healthCheckWorkflow, } from '@agenticvault/agentic-vault/protocols';
|
|
2
|
-
// ─── Result Adapter ───
|
|
1
|
+
import { signDefiCall, signPermit, getAddressWorkflow, healthCheckWorkflow, getBalanceWorkflow, sendTransfer, sendErc20Transfer, } from '@agenticvault/agentic-vault/protocols';
|
|
3
2
|
function toResult(result) {
|
|
4
3
|
switch (result.status) {
|
|
5
4
|
case 'approved':
|
|
6
|
-
return { content: [{ type: 'text', text: result.data }] };
|
|
5
|
+
return { content: [{ type: 'text', text: result.data }], details: undefined };
|
|
7
6
|
case 'dry-run-approved': {
|
|
8
7
|
const replacer = (_k, v) => typeof v === 'bigint' ? v.toString() : v;
|
|
9
8
|
return {
|
|
10
9
|
content: [
|
|
11
10
|
{ type: 'text', text: JSON.stringify(result.details, replacer) },
|
|
12
11
|
],
|
|
12
|
+
details: undefined,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
case 'denied':
|
|
16
|
-
return { content: [{ type: 'text', text: result.reason }] };
|
|
16
|
+
return { content: [{ type: 'text', text: result.reason }], details: undefined };
|
|
17
17
|
case 'error':
|
|
18
|
-
return { content: [{ type: 'text', text: `Error: ${result.reason}` }] };
|
|
18
|
+
return { content: [{ type: 'text', text: `Error: ${result.reason}` }], details: undefined };
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
// ─── Safe Tools (always registered) ───
|
|
22
22
|
function registerGetAddress(api, ctx) {
|
|
23
|
-
api.registerTool(
|
|
23
|
+
api.registerTool({
|
|
24
|
+
name: 'vault_get_address',
|
|
25
|
+
label: 'Get Vault Address',
|
|
24
26
|
description: 'Get the wallet address managed by this vault',
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
parameters: { type: 'object', properties: {}, required: [] },
|
|
28
|
+
async execute(_toolCallId, _params) {
|
|
29
|
+
const result = await getAddressWorkflow(ctx);
|
|
30
|
+
return toResult(result);
|
|
31
|
+
},
|
|
28
32
|
});
|
|
29
33
|
}
|
|
30
34
|
function registerHealthCheck(api, ctx) {
|
|
31
|
-
api.registerTool(
|
|
35
|
+
api.registerTool({
|
|
36
|
+
name: 'vault_health_check',
|
|
37
|
+
label: 'Vault Health Check',
|
|
32
38
|
description: 'Check the health status of the vault signer',
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
parameters: { type: 'object', properties: {}, required: [] },
|
|
40
|
+
async execute(_toolCallId, _params) {
|
|
41
|
+
const result = await healthCheckWorkflow(ctx);
|
|
42
|
+
return toResult(result);
|
|
43
|
+
},
|
|
36
44
|
});
|
|
37
45
|
}
|
|
38
46
|
function registerSignDefiCall(api, ctx) {
|
|
39
|
-
api.registerTool(
|
|
47
|
+
api.registerTool({
|
|
48
|
+
name: 'vault_sign_defi_call',
|
|
49
|
+
label: 'Sign DeFi Call',
|
|
40
50
|
description: 'Sign a DeFi contract interaction after calldata decoding and policy validation',
|
|
41
51
|
parameters: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
chainId: {
|
|
55
|
+
type: 'number',
|
|
56
|
+
description: 'The chain ID for the transaction',
|
|
57
|
+
},
|
|
58
|
+
to: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'The target contract address (0x-prefixed)',
|
|
61
|
+
},
|
|
62
|
+
data: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'The calldata (hex-encoded, 0x-prefixed)',
|
|
65
|
+
},
|
|
66
|
+
value: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'The value in wei (decimal string)',
|
|
69
|
+
},
|
|
60
70
|
},
|
|
71
|
+
required: ['chainId', 'to', 'data'],
|
|
72
|
+
},
|
|
73
|
+
async execute(_toolCallId, params) {
|
|
74
|
+
const result = await signDefiCall(ctx, 'vault_sign_defi_call', {
|
|
75
|
+
chainId: params.chainId,
|
|
76
|
+
to: params.to,
|
|
77
|
+
data: params.data,
|
|
78
|
+
value: params.value,
|
|
79
|
+
});
|
|
80
|
+
return toResult(result);
|
|
61
81
|
},
|
|
62
|
-
}, async (args) => {
|
|
63
|
-
const result = await signDefiCall(ctx, 'vault_sign_defi_call', {
|
|
64
|
-
chainId: args.chainId,
|
|
65
|
-
to: args.to,
|
|
66
|
-
data: args.data,
|
|
67
|
-
value: args.value,
|
|
68
|
-
});
|
|
69
|
-
return toResult(result);
|
|
70
82
|
});
|
|
71
83
|
}
|
|
72
84
|
function registerSignPermit(api, ctx) {
|
|
73
|
-
api.registerTool(
|
|
85
|
+
api.registerTool({
|
|
86
|
+
name: 'vault_sign_permit',
|
|
87
|
+
label: 'Sign EIP-2612 Permit',
|
|
74
88
|
description: 'Sign an EIP-2612 permit after policy validation',
|
|
75
89
|
parameters: {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
description: 'The chain ID',
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
chainId: { type: 'number', description: 'The chain ID' },
|
|
93
|
+
token: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
description: 'The token contract address (0x-prefixed)',
|
|
96
|
+
},
|
|
97
|
+
spender: {
|
|
98
|
+
type: 'string',
|
|
99
|
+
description: 'The spender address (0x-prefixed)',
|
|
100
|
+
},
|
|
101
|
+
value: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
description: 'The permit value in wei (decimal string)',
|
|
104
|
+
},
|
|
105
|
+
deadline: {
|
|
106
|
+
type: 'number',
|
|
107
|
+
description: 'The permit deadline (unix timestamp)',
|
|
108
|
+
},
|
|
109
|
+
domain: { type: 'object', description: 'The EIP-712 domain' },
|
|
110
|
+
types: { type: 'object', description: 'The EIP-712 types' },
|
|
111
|
+
message: { type: 'object', description: 'The EIP-712 message' },
|
|
90
112
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
required: [
|
|
114
|
+
'chainId',
|
|
115
|
+
'token',
|
|
116
|
+
'spender',
|
|
117
|
+
'value',
|
|
118
|
+
'deadline',
|
|
119
|
+
'domain',
|
|
120
|
+
'types',
|
|
121
|
+
'message',
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
async execute(_toolCallId, params) {
|
|
125
|
+
const result = await signPermit(ctx, {
|
|
126
|
+
chainId: params.chainId,
|
|
127
|
+
token: params.token,
|
|
128
|
+
spender: params.spender,
|
|
129
|
+
value: params.value,
|
|
130
|
+
deadline: params.deadline,
|
|
131
|
+
domain: params.domain,
|
|
132
|
+
types: params.types,
|
|
133
|
+
message: params.message,
|
|
134
|
+
});
|
|
135
|
+
return toResult(result);
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function registerGetBalance(api, ctx) {
|
|
140
|
+
api.registerTool({
|
|
141
|
+
name: 'vault_get_balance',
|
|
142
|
+
label: 'Get Balance',
|
|
143
|
+
description: 'Query native ETH or ERC20 token balance for an address',
|
|
144
|
+
parameters: {
|
|
145
|
+
type: 'object',
|
|
146
|
+
properties: {
|
|
147
|
+
chainId: {
|
|
148
|
+
type: 'number',
|
|
149
|
+
description: 'The chain ID to query',
|
|
150
|
+
},
|
|
151
|
+
address: {
|
|
152
|
+
type: 'string',
|
|
153
|
+
description: 'The address to query (defaults to vault address)',
|
|
154
|
+
},
|
|
155
|
+
token: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
description: 'ERC20 token address (omit for native ETH balance)',
|
|
158
|
+
},
|
|
105
159
|
},
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
160
|
+
required: ['chainId'],
|
|
161
|
+
},
|
|
162
|
+
async execute(_toolCallId, params) {
|
|
163
|
+
const result = await getBalanceWorkflow(ctx, {
|
|
164
|
+
chainId: params.chainId,
|
|
165
|
+
address: params.address,
|
|
166
|
+
token: params.token,
|
|
167
|
+
});
|
|
168
|
+
return toResult(result);
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function registerSendTransfer(api, ctx) {
|
|
173
|
+
api.registerTool({
|
|
174
|
+
name: 'vault_send_transfer',
|
|
175
|
+
label: 'Send ETH Transfer',
|
|
176
|
+
description: 'Send native ETH transfer after policy validation, sign and broadcast',
|
|
177
|
+
parameters: {
|
|
178
|
+
type: 'object',
|
|
179
|
+
properties: {
|
|
180
|
+
chainId: {
|
|
181
|
+
type: 'number',
|
|
182
|
+
description: 'The chain ID for the transaction',
|
|
183
|
+
},
|
|
184
|
+
to: {
|
|
185
|
+
type: 'string',
|
|
186
|
+
description: 'The recipient address (0x-prefixed)',
|
|
187
|
+
},
|
|
188
|
+
value: {
|
|
189
|
+
type: 'string',
|
|
190
|
+
description: 'Amount in wei (decimal string)',
|
|
191
|
+
},
|
|
110
192
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
193
|
+
required: ['chainId', 'to', 'value'],
|
|
194
|
+
},
|
|
195
|
+
async execute(_toolCallId, params) {
|
|
196
|
+
const result = await sendTransfer(ctx, {
|
|
197
|
+
chainId: params.chainId,
|
|
198
|
+
to: params.to,
|
|
199
|
+
value: params.value,
|
|
200
|
+
});
|
|
201
|
+
return toResult(result);
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function registerSendErc20Transfer(api, ctx) {
|
|
206
|
+
api.registerTool({
|
|
207
|
+
name: 'vault_send_erc20_transfer',
|
|
208
|
+
label: 'Send ERC20 Transfer',
|
|
209
|
+
description: 'Send ERC20 token transfer after policy validation, sign and broadcast',
|
|
210
|
+
parameters: {
|
|
211
|
+
type: 'object',
|
|
212
|
+
properties: {
|
|
213
|
+
chainId: {
|
|
214
|
+
type: 'number',
|
|
215
|
+
description: 'The chain ID for the transaction',
|
|
216
|
+
},
|
|
217
|
+
token: {
|
|
218
|
+
type: 'string',
|
|
219
|
+
description: 'The ERC20 token contract address (0x-prefixed)',
|
|
220
|
+
},
|
|
221
|
+
to: {
|
|
222
|
+
type: 'string',
|
|
223
|
+
description: 'The recipient address (0x-prefixed)',
|
|
224
|
+
},
|
|
225
|
+
amount: {
|
|
226
|
+
type: 'string',
|
|
227
|
+
description: 'Amount in smallest unit (decimal string)',
|
|
228
|
+
},
|
|
115
229
|
},
|
|
230
|
+
required: ['chainId', 'token', 'to', 'amount'],
|
|
231
|
+
},
|
|
232
|
+
async execute(_toolCallId, params) {
|
|
233
|
+
const result = await sendErc20Transfer(ctx, {
|
|
234
|
+
chainId: params.chainId,
|
|
235
|
+
token: params.token,
|
|
236
|
+
to: params.to,
|
|
237
|
+
amount: params.amount,
|
|
238
|
+
});
|
|
239
|
+
return toResult(result);
|
|
116
240
|
},
|
|
117
|
-
}, async (args) => {
|
|
118
|
-
const result = await signPermit(ctx, {
|
|
119
|
-
chainId: args.chainId,
|
|
120
|
-
token: args.token,
|
|
121
|
-
spender: args.spender,
|
|
122
|
-
value: args.value,
|
|
123
|
-
deadline: args.deadline,
|
|
124
|
-
domain: args.domain,
|
|
125
|
-
types: args.types,
|
|
126
|
-
message: args.message,
|
|
127
|
-
});
|
|
128
|
-
return toResult(result);
|
|
129
241
|
});
|
|
130
242
|
}
|
|
131
243
|
// ─── Dual-Gated Tools (only with enableUnsafeRawSign) ───
|
|
132
244
|
function registerSignTransaction(api, ctx) {
|
|
133
|
-
api.registerTool(
|
|
245
|
+
api.registerTool({
|
|
246
|
+
name: 'vault_sign_transaction',
|
|
247
|
+
label: 'Sign Raw Transaction',
|
|
134
248
|
description: '[UNSAFE] Sign a raw EVM transaction. Only available when enableUnsafeRawSign is configured.',
|
|
135
249
|
parameters: {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
description: 'The chain ID',
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
type: '
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
type: 'string',
|
|
165
|
-
description: 'Max priority fee per gas in wei',
|
|
250
|
+
type: 'object',
|
|
251
|
+
properties: {
|
|
252
|
+
chainId: { type: 'number', description: 'The chain ID' },
|
|
253
|
+
to: {
|
|
254
|
+
type: 'string',
|
|
255
|
+
description: 'The target address (0x-prefixed)',
|
|
256
|
+
},
|
|
257
|
+
data: {
|
|
258
|
+
type: 'string',
|
|
259
|
+
description: 'The calldata (hex-encoded)',
|
|
260
|
+
},
|
|
261
|
+
value: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'The value in wei (decimal string)',
|
|
264
|
+
},
|
|
265
|
+
nonce: { type: 'number', description: 'The transaction nonce' },
|
|
266
|
+
gas: {
|
|
267
|
+
type: 'string',
|
|
268
|
+
description: 'The gas limit (decimal string)',
|
|
269
|
+
},
|
|
270
|
+
maxFeePerGas: {
|
|
271
|
+
type: 'string',
|
|
272
|
+
description: 'Max fee per gas in wei',
|
|
273
|
+
},
|
|
274
|
+
maxPriorityFeePerGas: {
|
|
275
|
+
type: 'string',
|
|
276
|
+
description: 'Max priority fee per gas in wei',
|
|
277
|
+
},
|
|
166
278
|
},
|
|
279
|
+
required: ['chainId', 'to'],
|
|
167
280
|
},
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
281
|
+
async execute(_toolCallId, params) {
|
|
282
|
+
if (!ctx.signer) {
|
|
283
|
+
ctx.auditSink.log({
|
|
284
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
285
|
+
action: 'vault_sign_transaction',
|
|
286
|
+
who: ctx.caller,
|
|
287
|
+
what: 'Signer not available for raw transaction signing',
|
|
288
|
+
why: 'Configuration error: signer is required',
|
|
289
|
+
result: 'error',
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
content: [{ type: 'text', text: 'Error: Signer is not available' }],
|
|
293
|
+
details: undefined,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const to = params.to.toLowerCase();
|
|
298
|
+
const tx = {
|
|
299
|
+
chainId: params.chainId,
|
|
300
|
+
to,
|
|
301
|
+
type: 'eip1559',
|
|
302
|
+
};
|
|
303
|
+
if (params.data)
|
|
304
|
+
tx.data = params.data;
|
|
305
|
+
if (params.value)
|
|
306
|
+
tx.value = BigInt(params.value);
|
|
307
|
+
if (params.nonce !== undefined)
|
|
308
|
+
tx.nonce = params.nonce;
|
|
309
|
+
if (params.gas)
|
|
310
|
+
tx.gas = BigInt(params.gas);
|
|
311
|
+
if (params.maxFeePerGas)
|
|
312
|
+
tx.maxFeePerGas = BigInt(params.maxFeePerGas);
|
|
313
|
+
if (params.maxPriorityFeePerGas)
|
|
314
|
+
tx.maxPriorityFeePerGas = BigInt(params.maxPriorityFeePerGas);
|
|
315
|
+
const signedTx = await ctx.signer.signTransaction(tx);
|
|
316
|
+
ctx.auditSink.log({
|
|
317
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
318
|
+
action: 'vault_sign_transaction',
|
|
319
|
+
who: ctx.caller,
|
|
320
|
+
what: `Signed raw transaction to ${to} on chain ${params.chainId}`,
|
|
321
|
+
why: 'Raw transaction signing (enableUnsafeRawSign enabled)',
|
|
322
|
+
result: 'approved',
|
|
323
|
+
details: { chainId: params.chainId, to },
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
content: [{ type: 'text', text: signedTx }],
|
|
327
|
+
details: undefined,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
332
|
+
ctx.auditSink.log({
|
|
333
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
334
|
+
action: 'vault_sign_transaction',
|
|
335
|
+
who: ctx.caller,
|
|
336
|
+
what: `Failed to sign raw transaction to ${params.to}`,
|
|
337
|
+
why: 'Signing error',
|
|
338
|
+
result: 'error',
|
|
339
|
+
details: { error: msg },
|
|
340
|
+
});
|
|
341
|
+
return {
|
|
342
|
+
content: [{ type: 'text', text: `Signing error: ${msg}` }],
|
|
343
|
+
details: undefined,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
}, { optional: true });
|
|
230
348
|
}
|
|
231
349
|
function registerSignTypedData(api, ctx) {
|
|
232
|
-
api.registerTool(
|
|
350
|
+
api.registerTool({
|
|
351
|
+
name: 'vault_sign_typed_data',
|
|
352
|
+
label: 'Sign Raw Typed Data',
|
|
233
353
|
description: '[UNSAFE] Sign raw EIP-712 typed data. Only available when enableUnsafeRawSign is configured.',
|
|
234
354
|
parameters: {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
description: 'The EIP-712 domain',
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
},
|
|
245
|
-
primaryType: {
|
|
246
|
-
type: 'string',
|
|
247
|
-
description: 'The primary type name',
|
|
248
|
-
required: true,
|
|
249
|
-
},
|
|
250
|
-
message: {
|
|
251
|
-
type: 'object',
|
|
252
|
-
description: 'The EIP-712 message',
|
|
253
|
-
required: true,
|
|
355
|
+
type: 'object',
|
|
356
|
+
properties: {
|
|
357
|
+
domain: { type: 'object', description: 'The EIP-712 domain' },
|
|
358
|
+
types: { type: 'object', description: 'The EIP-712 types' },
|
|
359
|
+
primaryType: {
|
|
360
|
+
type: 'string',
|
|
361
|
+
description: 'The primary type name',
|
|
362
|
+
},
|
|
363
|
+
message: { type: 'object', description: 'The EIP-712 message' },
|
|
254
364
|
},
|
|
365
|
+
required: ['domain', 'types', 'primaryType', 'message'],
|
|
255
366
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
367
|
+
async execute(_toolCallId, params) {
|
|
368
|
+
if (!ctx.signer) {
|
|
369
|
+
ctx.auditSink.log({
|
|
370
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
371
|
+
action: 'vault_sign_typed_data',
|
|
372
|
+
who: ctx.caller,
|
|
373
|
+
what: 'Signer not available for typed data signing',
|
|
374
|
+
why: 'Configuration error: signer is required',
|
|
375
|
+
result: 'error',
|
|
376
|
+
});
|
|
377
|
+
return {
|
|
378
|
+
content: [{ type: 'text', text: 'Error: Signer is not available' }],
|
|
379
|
+
details: undefined,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
const sig = await ctx.signer.signTypedData({
|
|
384
|
+
domain: params.domain,
|
|
385
|
+
types: params.types,
|
|
386
|
+
primaryType: params.primaryType,
|
|
387
|
+
message: params.message,
|
|
388
|
+
});
|
|
389
|
+
ctx.auditSink.log({
|
|
390
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
391
|
+
action: 'vault_sign_typed_data',
|
|
392
|
+
who: ctx.caller,
|
|
393
|
+
what: `Signed typed data with primaryType ${params.primaryType}`,
|
|
394
|
+
why: 'Raw typed data signing (enableUnsafeRawSign enabled)',
|
|
395
|
+
result: 'approved',
|
|
396
|
+
details: { primaryType: params.primaryType },
|
|
397
|
+
});
|
|
398
|
+
return {
|
|
399
|
+
content: [{ type: 'text', text: JSON.stringify(sig) }],
|
|
400
|
+
details: undefined,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
405
|
+
ctx.auditSink.log({
|
|
406
|
+
service: ctx.service ?? 'agentic-vault-openclaw',
|
|
407
|
+
action: 'vault_sign_typed_data',
|
|
408
|
+
who: ctx.caller,
|
|
409
|
+
what: `Failed to sign typed data with primaryType ${params.primaryType}`,
|
|
410
|
+
why: 'Signing error',
|
|
411
|
+
result: 'error',
|
|
412
|
+
details: { error: msg },
|
|
413
|
+
});
|
|
414
|
+
return {
|
|
415
|
+
content: [{ type: 'text', text: `Signing error: ${msg}` }],
|
|
416
|
+
details: undefined,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
}, { optional: true });
|
|
307
421
|
}
|
|
308
422
|
// ─── Public Registration ───
|
|
309
423
|
/**
|
|
310
424
|
* Register all OpenClaw tools.
|
|
311
|
-
*
|
|
425
|
+
* 7 safe tools are always registered.
|
|
312
426
|
* 2 dual-gated tools are only registered when enableUnsafeRawSign is true.
|
|
313
427
|
*/
|
|
314
428
|
export function registerTools(api, ctx, config) {
|
|
@@ -317,6 +431,9 @@ export function registerTools(api, ctx, config) {
|
|
|
317
431
|
registerHealthCheck(api, ctx);
|
|
318
432
|
registerSignDefiCall(api, ctx);
|
|
319
433
|
registerSignPermit(api, ctx);
|
|
434
|
+
registerGetBalance(api, ctx);
|
|
435
|
+
registerSendTransfer(api, ctx);
|
|
436
|
+
registerSendErc20Transfer(api, ctx);
|
|
320
437
|
// Dual-gated tools — only with enableUnsafeRawSign
|
|
321
438
|
if (config.enableUnsafeRawSign) {
|
|
322
439
|
registerSignTransaction(api, ctx);
|