shll-skills 3.1.0 → 4.0.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/dist/chunk-EUGNHCIP.mjs +502 -0
- package/dist/index.mjs +28 -526
- package/dist/mcp.d.mts +1 -0
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +942 -0
- package/dist/mcp.mjs +451 -0
- package/package.json +9 -6
- package/src/mcp.ts +538 -0
- package/tsup.config.ts +1 -1
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
// node_modules/shll-policy-sdk/dist/index.js
|
|
2
|
+
import {
|
|
3
|
+
createPublicClient,
|
|
4
|
+
createWalletClient,
|
|
5
|
+
http
|
|
6
|
+
} from "viem";
|
|
7
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
8
|
+
import { bsc, bscTestnet } from "viem/chains";
|
|
9
|
+
var PolicyGuardV4Abi = [
|
|
10
|
+
{
|
|
11
|
+
name: "validate",
|
|
12
|
+
type: "function",
|
|
13
|
+
stateMutability: "view",
|
|
14
|
+
inputs: [
|
|
15
|
+
{ name: "nfa", type: "address" },
|
|
16
|
+
{ name: "tokenId", type: "uint256" },
|
|
17
|
+
{ name: "agentAccount", type: "address" },
|
|
18
|
+
{ name: "caller", type: "address" },
|
|
19
|
+
{
|
|
20
|
+
name: "action",
|
|
21
|
+
type: "tuple",
|
|
22
|
+
components: [
|
|
23
|
+
{ name: "target", type: "address" },
|
|
24
|
+
{ name: "value", type: "uint256" },
|
|
25
|
+
{ name: "data", type: "bytes" }
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
outputs: [
|
|
30
|
+
{ name: "ok", type: "bool" },
|
|
31
|
+
{ name: "reason", type: "string" }
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "getActivePolicies",
|
|
36
|
+
type: "function",
|
|
37
|
+
stateMutability: "view",
|
|
38
|
+
inputs: [{ name: "instanceId", type: "uint256" }],
|
|
39
|
+
outputs: [{ name: "", type: "address[]" }]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "getTemplatePolicies",
|
|
43
|
+
type: "function",
|
|
44
|
+
stateMutability: "view",
|
|
45
|
+
inputs: [{ name: "templateId", type: "bytes32" }],
|
|
46
|
+
outputs: [{ name: "", type: "address[]" }]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "instanceTemplateId",
|
|
50
|
+
type: "function",
|
|
51
|
+
stateMutability: "view",
|
|
52
|
+
inputs: [{ name: "instanceId", type: "uint256" }],
|
|
53
|
+
outputs: [{ name: "", type: "bytes32" }]
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
var AgentNFAAbi = [
|
|
57
|
+
{
|
|
58
|
+
name: "execute",
|
|
59
|
+
type: "function",
|
|
60
|
+
stateMutability: "payable",
|
|
61
|
+
inputs: [
|
|
62
|
+
{ name: "tokenId", type: "uint256" },
|
|
63
|
+
{
|
|
64
|
+
name: "action",
|
|
65
|
+
type: "tuple",
|
|
66
|
+
components: [
|
|
67
|
+
{ name: "target", type: "address" },
|
|
68
|
+
{ name: "value", type: "uint256" },
|
|
69
|
+
{ name: "data", type: "bytes" }
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
outputs: [{ name: "result", type: "bytes" }]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "executeBatch",
|
|
77
|
+
type: "function",
|
|
78
|
+
stateMutability: "payable",
|
|
79
|
+
inputs: [
|
|
80
|
+
{ name: "tokenId", type: "uint256" },
|
|
81
|
+
{
|
|
82
|
+
name: "actions",
|
|
83
|
+
type: "tuple[]",
|
|
84
|
+
components: [
|
|
85
|
+
{ name: "target", type: "address" },
|
|
86
|
+
{ name: "value", type: "uint256" },
|
|
87
|
+
{ name: "data", type: "bytes" }
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
outputs: [{ name: "results", type: "bytes[]" }]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "accountOf",
|
|
95
|
+
type: "function",
|
|
96
|
+
stateMutability: "view",
|
|
97
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
98
|
+
outputs: [{ name: "", type: "address" }]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "userOf",
|
|
102
|
+
type: "function",
|
|
103
|
+
stateMutability: "view",
|
|
104
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
105
|
+
outputs: [{ name: "", type: "address" }]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "userExpires",
|
|
109
|
+
type: "function",
|
|
110
|
+
stateMutability: "view",
|
|
111
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
112
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "operatorOf",
|
|
116
|
+
type: "function",
|
|
117
|
+
stateMutability: "view",
|
|
118
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
119
|
+
outputs: [{ name: "", type: "address" }]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "operatorExpiresOf",
|
|
123
|
+
type: "function",
|
|
124
|
+
stateMutability: "view",
|
|
125
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
126
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "operatorNonceOf",
|
|
130
|
+
type: "function",
|
|
131
|
+
stateMutability: "view",
|
|
132
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
133
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "setOperatorWithSig",
|
|
137
|
+
type: "function",
|
|
138
|
+
stateMutability: "nonpayable",
|
|
139
|
+
inputs: [
|
|
140
|
+
{
|
|
141
|
+
name: "req",
|
|
142
|
+
type: "tuple",
|
|
143
|
+
components: [
|
|
144
|
+
{ name: "tokenId", type: "uint256" },
|
|
145
|
+
{ name: "renter", type: "address" },
|
|
146
|
+
{ name: "operator", type: "address" },
|
|
147
|
+
{ name: "expires", type: "uint64" },
|
|
148
|
+
{ name: "nonce", type: "uint256" },
|
|
149
|
+
{ name: "deadline", type: "uint256" }
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{ name: "signature", type: "bytes" }
|
|
153
|
+
],
|
|
154
|
+
outputs: []
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "clearOperator",
|
|
158
|
+
type: "function",
|
|
159
|
+
stateMutability: "nonpayable",
|
|
160
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
161
|
+
outputs: []
|
|
162
|
+
}
|
|
163
|
+
];
|
|
164
|
+
var IPolicyAbi = [
|
|
165
|
+
{
|
|
166
|
+
name: "policyType",
|
|
167
|
+
type: "function",
|
|
168
|
+
stateMutability: "pure",
|
|
169
|
+
inputs: [],
|
|
170
|
+
outputs: [{ name: "", type: "bytes32" }]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "renterConfigurable",
|
|
174
|
+
type: "function",
|
|
175
|
+
stateMutability: "pure",
|
|
176
|
+
inputs: [],
|
|
177
|
+
outputs: [{ name: "", type: "bool" }]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "check",
|
|
181
|
+
type: "function",
|
|
182
|
+
stateMutability: "view",
|
|
183
|
+
inputs: [
|
|
184
|
+
{ name: "instanceId", type: "uint256" },
|
|
185
|
+
{ name: "caller", type: "address" },
|
|
186
|
+
{ name: "target", type: "address" },
|
|
187
|
+
{ name: "selector", type: "bytes4" },
|
|
188
|
+
{ name: "callData", type: "bytes" },
|
|
189
|
+
{ name: "value", type: "uint256" }
|
|
190
|
+
],
|
|
191
|
+
outputs: [
|
|
192
|
+
{ name: "ok", type: "bool" },
|
|
193
|
+
{ name: "reason", type: "string" }
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
];
|
|
197
|
+
var POLICY_TYPE_NAMES = {
|
|
198
|
+
// keccak256(abi.encodePacked("spending_limit"))
|
|
199
|
+
"0xfc881f20d88f7ec7e942f0b796f40ce121974015a83f091cd5ef2cf146443d4e": "spending_limit",
|
|
200
|
+
// keccak256(abi.encodePacked("cooldown"))
|
|
201
|
+
"0x7230b2ae91f8efdf9ea182e9a9d1fef92adfda3e61d5512778c2f81580b13d10": "cooldown",
|
|
202
|
+
// keccak256(abi.encodePacked("receiver_guard"))
|
|
203
|
+
"0xccead04e892f4bd05d3e2491948809479bf4641d233bf37f3fac8411960a97de": "receiver_guard",
|
|
204
|
+
// keccak256(abi.encodePacked("dex_whitelist"))
|
|
205
|
+
"0xb5ba0ef255153fe2c4c7201fbd5f2658f86e25a723f1844d5bf64a5c48e0c9ed": "dex_whitelist",
|
|
206
|
+
// keccak256(abi.encodePacked("defi_guard"))
|
|
207
|
+
"0xe109b0d2bf06e570d9aecb2cd18dafe849a5c1d8b9b9f6ecd8b9ed727f816bb9": "defi_guard",
|
|
208
|
+
// keccak256(abi.encodePacked("token_whitelist"))
|
|
209
|
+
"0xf4717a1c69e76a67584dd6d514cc591ec961b52113ec085dfe157bd9e238e1f3": "token_whitelist"
|
|
210
|
+
};
|
|
211
|
+
var PolicyClient = class {
|
|
212
|
+
publicClient;
|
|
213
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
214
|
+
_walletClient;
|
|
215
|
+
_operatorAddress;
|
|
216
|
+
agentNfaAddress;
|
|
217
|
+
policyGuardAddress;
|
|
218
|
+
constructor(config) {
|
|
219
|
+
const chain = config.chainId === 97 ? bscTestnet : bsc;
|
|
220
|
+
this.publicClient = createPublicClient({
|
|
221
|
+
chain,
|
|
222
|
+
transport: http(config.rpcUrl)
|
|
223
|
+
});
|
|
224
|
+
this.agentNfaAddress = config.agentNfaAddress;
|
|
225
|
+
this.policyGuardAddress = config.policyGuardAddress;
|
|
226
|
+
if (config.operatorPrivateKey) {
|
|
227
|
+
const account = privateKeyToAccount(config.operatorPrivateKey);
|
|
228
|
+
this._operatorAddress = account.address;
|
|
229
|
+
this._walletClient = createWalletClient({
|
|
230
|
+
account,
|
|
231
|
+
chain,
|
|
232
|
+
transport: http(config.rpcUrl)
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
this._operatorAddress = null;
|
|
236
|
+
this._walletClient = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ═══════════════════════════════════════════════════════
|
|
240
|
+
// VALIDATION
|
|
241
|
+
// ═══════════════════════════════════════════════════════
|
|
242
|
+
/**
|
|
243
|
+
* Validate an action against all active on-chain policies.
|
|
244
|
+
* This is an off-chain simulation — saves gas by catching rejections before submission.
|
|
245
|
+
*
|
|
246
|
+
* @param tokenId - Agent NFA token ID
|
|
247
|
+
* @param action - The action to validate
|
|
248
|
+
* @param callerOverride - Optional caller address override (defaults to operator)
|
|
249
|
+
*/
|
|
250
|
+
async validate(tokenId, action, callerOverride) {
|
|
251
|
+
const caller = callerOverride ?? this._operatorAddress;
|
|
252
|
+
if (!caller) {
|
|
253
|
+
return { ok: false, reason: "No caller address \u2014 provide operatorPrivateKey or callerOverride" };
|
|
254
|
+
}
|
|
255
|
+
const vault = await this.getVault(tokenId);
|
|
256
|
+
try {
|
|
257
|
+
const [ok, reason] = await this.publicClient.readContract({
|
|
258
|
+
address: this.policyGuardAddress,
|
|
259
|
+
abi: PolicyGuardV4Abi,
|
|
260
|
+
functionName: "validate",
|
|
261
|
+
args: [
|
|
262
|
+
this.agentNfaAddress,
|
|
263
|
+
tokenId,
|
|
264
|
+
vault,
|
|
265
|
+
caller,
|
|
266
|
+
{ target: action.target, value: action.value, data: action.data }
|
|
267
|
+
]
|
|
268
|
+
});
|
|
269
|
+
return { ok, reason: reason || void 0 };
|
|
270
|
+
} catch (error) {
|
|
271
|
+
const message = error instanceof Error ? error.message : "Simulation reverted";
|
|
272
|
+
return { ok: false, reason: `Simulation reverted: ${message.slice(0, 300)}` };
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// ═══════════════════════════════════════════════════════
|
|
276
|
+
// EXECUTION
|
|
277
|
+
// ═══════════════════════════════════════════════════════
|
|
278
|
+
/**
|
|
279
|
+
* Execute a single action through AgentNFA.
|
|
280
|
+
* Simulates first, then submits if validation passes.
|
|
281
|
+
*
|
|
282
|
+
* @param tokenId - Agent NFA token ID
|
|
283
|
+
* @param action - The action to execute
|
|
284
|
+
* @param skipValidation - Skip pre-flight validation (default: false)
|
|
285
|
+
*/
|
|
286
|
+
async execute(tokenId, action, skipValidation = false) {
|
|
287
|
+
this.requireWallet();
|
|
288
|
+
if (!skipValidation) {
|
|
289
|
+
const sim = await this.validate(tokenId, action);
|
|
290
|
+
if (!sim.ok) {
|
|
291
|
+
throw new Error(`Policy rejected: ${sim.reason}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const hash = await this._walletClient.writeContract({
|
|
295
|
+
address: this.agentNfaAddress,
|
|
296
|
+
abi: AgentNFAAbi,
|
|
297
|
+
functionName: "execute",
|
|
298
|
+
args: [tokenId, { target: action.target, value: action.value, data: action.data }]
|
|
299
|
+
});
|
|
300
|
+
return { hash };
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Execute multiple actions atomically via AgentNFA.executeBatch().
|
|
304
|
+
* Useful for approve+swap in a single transaction.
|
|
305
|
+
*
|
|
306
|
+
* @param tokenId - Agent NFA token ID
|
|
307
|
+
* @param actions - Array of actions to execute
|
|
308
|
+
* @param skipValidation - Skip per-action pre-flight validation (default: false)
|
|
309
|
+
*/
|
|
310
|
+
async executeBatch(tokenId, actions, skipValidation = false) {
|
|
311
|
+
this.requireWallet();
|
|
312
|
+
if (!skipValidation) {
|
|
313
|
+
for (const action of actions) {
|
|
314
|
+
const sim = await this.validate(tokenId, action);
|
|
315
|
+
if (!sim.ok) {
|
|
316
|
+
throw new Error(`Policy rejected action (target=${action.target}): ${sim.reason}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const hash = await this._walletClient.writeContract({
|
|
321
|
+
address: this.agentNfaAddress,
|
|
322
|
+
abi: AgentNFAAbi,
|
|
323
|
+
functionName: "executeBatch",
|
|
324
|
+
args: [
|
|
325
|
+
tokenId,
|
|
326
|
+
actions.map((a) => ({ target: a.target, value: a.value, data: a.data }))
|
|
327
|
+
]
|
|
328
|
+
});
|
|
329
|
+
return { hash };
|
|
330
|
+
}
|
|
331
|
+
// ═══════════════════════════════════════════════════════
|
|
332
|
+
// POLICY QUERIES
|
|
333
|
+
// ═══════════════════════════════════════════════════════
|
|
334
|
+
/**
|
|
335
|
+
* Get all active policies for an agent instance, with type info.
|
|
336
|
+
*
|
|
337
|
+
* @param tokenId - Agent NFA token ID
|
|
338
|
+
* @returns Array of PolicyInfo objects
|
|
339
|
+
*/
|
|
340
|
+
async getPolicies(tokenId) {
|
|
341
|
+
const addresses = await this.publicClient.readContract({
|
|
342
|
+
address: this.policyGuardAddress,
|
|
343
|
+
abi: PolicyGuardV4Abi,
|
|
344
|
+
functionName: "getActivePolicies",
|
|
345
|
+
args: [tokenId]
|
|
346
|
+
});
|
|
347
|
+
const results = [];
|
|
348
|
+
for (const addr of addresses) {
|
|
349
|
+
try {
|
|
350
|
+
const [policyType, renterConfigurable] = await Promise.all([
|
|
351
|
+
this.publicClient.readContract({
|
|
352
|
+
address: addr,
|
|
353
|
+
abi: IPolicyAbi,
|
|
354
|
+
functionName: "policyType"
|
|
355
|
+
}),
|
|
356
|
+
this.publicClient.readContract({
|
|
357
|
+
address: addr,
|
|
358
|
+
abi: IPolicyAbi,
|
|
359
|
+
functionName: "renterConfigurable"
|
|
360
|
+
})
|
|
361
|
+
]);
|
|
362
|
+
const typeName = POLICY_TYPE_NAMES[policyType] ?? "unknown";
|
|
363
|
+
results.push({
|
|
364
|
+
address: addr,
|
|
365
|
+
policyType,
|
|
366
|
+
policyTypeName: typeName,
|
|
367
|
+
renterConfigurable
|
|
368
|
+
});
|
|
369
|
+
} catch {
|
|
370
|
+
results.push({
|
|
371
|
+
address: addr,
|
|
372
|
+
policyType: "0x",
|
|
373
|
+
policyTypeName: "unknown",
|
|
374
|
+
renterConfigurable: false
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return results;
|
|
379
|
+
}
|
|
380
|
+
// ═══════════════════════════════════════════════════════
|
|
381
|
+
// OPERATOR PERMIT
|
|
382
|
+
// ═══════════════════════════════════════════════════════
|
|
383
|
+
/**
|
|
384
|
+
* Read the current operator state for a token — useful for constructing permits.
|
|
385
|
+
*
|
|
386
|
+
* @param tokenId - Agent NFA token ID
|
|
387
|
+
* @returns Current operator, renter, vault, and nonce info
|
|
388
|
+
*/
|
|
389
|
+
async getOperatorState(tokenId) {
|
|
390
|
+
const [operator, operatorExpires, renter, renterExpires, vault, operatorNonce] = await Promise.all([
|
|
391
|
+
this.publicClient.readContract({
|
|
392
|
+
address: this.agentNfaAddress,
|
|
393
|
+
abi: AgentNFAAbi,
|
|
394
|
+
functionName: "operatorOf",
|
|
395
|
+
args: [tokenId]
|
|
396
|
+
}),
|
|
397
|
+
this.publicClient.readContract({
|
|
398
|
+
address: this.agentNfaAddress,
|
|
399
|
+
abi: AgentNFAAbi,
|
|
400
|
+
functionName: "operatorExpiresOf",
|
|
401
|
+
args: [tokenId]
|
|
402
|
+
}),
|
|
403
|
+
this.publicClient.readContract({
|
|
404
|
+
address: this.agentNfaAddress,
|
|
405
|
+
abi: AgentNFAAbi,
|
|
406
|
+
functionName: "userOf",
|
|
407
|
+
args: [tokenId]
|
|
408
|
+
}),
|
|
409
|
+
this.publicClient.readContract({
|
|
410
|
+
address: this.agentNfaAddress,
|
|
411
|
+
abi: AgentNFAAbi,
|
|
412
|
+
functionName: "userExpires",
|
|
413
|
+
args: [tokenId]
|
|
414
|
+
}),
|
|
415
|
+
this.publicClient.readContract({
|
|
416
|
+
address: this.agentNfaAddress,
|
|
417
|
+
abi: AgentNFAAbi,
|
|
418
|
+
functionName: "accountOf",
|
|
419
|
+
args: [tokenId]
|
|
420
|
+
}),
|
|
421
|
+
this.publicClient.readContract({
|
|
422
|
+
address: this.agentNfaAddress,
|
|
423
|
+
abi: AgentNFAAbi,
|
|
424
|
+
functionName: "operatorNonceOf",
|
|
425
|
+
args: [tokenId]
|
|
426
|
+
})
|
|
427
|
+
]);
|
|
428
|
+
return { operator, operatorExpires, renter, renterExpires, vault, operatorNonce };
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Submit a signed OperatorPermit on-chain to authorize this runner as operator.
|
|
432
|
+
*
|
|
433
|
+
* @param permit - The OperatorPermit struct
|
|
434
|
+
* @param signature - EIP-712 signature from the renter
|
|
435
|
+
*/
|
|
436
|
+
async setOperatorWithPermit(permit, signature) {
|
|
437
|
+
this.requireWallet();
|
|
438
|
+
const hash = await this._walletClient.writeContract({
|
|
439
|
+
address: this.agentNfaAddress,
|
|
440
|
+
abi: AgentNFAAbi,
|
|
441
|
+
functionName: "setOperatorWithSig",
|
|
442
|
+
args: [
|
|
443
|
+
{
|
|
444
|
+
tokenId: permit.tokenId,
|
|
445
|
+
renter: permit.renter,
|
|
446
|
+
operator: permit.operator,
|
|
447
|
+
expires: permit.expires,
|
|
448
|
+
nonce: permit.nonce,
|
|
449
|
+
deadline: permit.deadline
|
|
450
|
+
},
|
|
451
|
+
signature
|
|
452
|
+
]
|
|
453
|
+
});
|
|
454
|
+
return { hash };
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Clear the operator permit for a token.
|
|
458
|
+
*
|
|
459
|
+
* @param tokenId - Agent NFA token ID
|
|
460
|
+
*/
|
|
461
|
+
async clearOperator(tokenId) {
|
|
462
|
+
this.requireWallet();
|
|
463
|
+
const hash = await this._walletClient.writeContract({
|
|
464
|
+
address: this.agentNfaAddress,
|
|
465
|
+
abi: AgentNFAAbi,
|
|
466
|
+
functionName: "clearOperator",
|
|
467
|
+
args: [tokenId]
|
|
468
|
+
});
|
|
469
|
+
return { hash };
|
|
470
|
+
}
|
|
471
|
+
// ═══════════════════════════════════════════════════════
|
|
472
|
+
// HELPERS
|
|
473
|
+
// ═══════════════════════════════════════════════════════
|
|
474
|
+
/**
|
|
475
|
+
* Get the vault (AgentAccount) address for a token.
|
|
476
|
+
*/
|
|
477
|
+
async getVault(tokenId) {
|
|
478
|
+
return await this.publicClient.readContract({
|
|
479
|
+
address: this.agentNfaAddress,
|
|
480
|
+
abi: AgentNFAAbi,
|
|
481
|
+
functionName: "accountOf",
|
|
482
|
+
args: [tokenId]
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Get the operator address configured for this client.
|
|
487
|
+
*/
|
|
488
|
+
getOperatorAddress() {
|
|
489
|
+
return this._operatorAddress;
|
|
490
|
+
}
|
|
491
|
+
requireWallet() {
|
|
492
|
+
if (!this._walletClient) {
|
|
493
|
+
throw new Error(
|
|
494
|
+
"PolicyClient: operatorPrivateKey is required for write operations (execute, setOperator)"
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
export {
|
|
501
|
+
PolicyClient
|
|
502
|
+
};
|