@agether/openclaw-plugin 1.1.1 → 1.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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/index.ts +64 -37
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "agether",
|
|
3
3
|
"name": "Agether Credit",
|
|
4
4
|
"description": "On-chain credit protocol for AI agents — Morpho-backed overcollateralized credit, ERC-8004 identity, x402 payments",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"skills": ["skills/agether"],
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ const ERC8004_ABI = [
|
|
|
30
30
|
"function register(string agentURI) returns (uint256)",
|
|
31
31
|
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
32
32
|
"function balanceOf(address owner) view returns (uint256)",
|
|
33
|
+
"function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)",
|
|
33
34
|
];
|
|
34
35
|
|
|
35
36
|
const COLLATERAL_TOKENS: Record<string, { address: string; decimals: number }> = {
|
|
@@ -69,6 +70,23 @@ async function getAccountAddr(signer: ethers.Wallet, factoryAddr: string, agentI
|
|
|
69
70
|
return addr;
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
// ─── Auto-resolve agentId from chain ──────────────────────
|
|
74
|
+
let _cachedAgentId: string | null = null;
|
|
75
|
+
|
|
76
|
+
async function resolveAgentId(cfg: PluginConfig, signer: ethers.Wallet, status: any): Promise<string> {
|
|
77
|
+
// 1. Config takes priority
|
|
78
|
+
if (cfg.agentId && cfg.agentId !== "0") return cfg.agentId;
|
|
79
|
+
// 2. Session cache
|
|
80
|
+
if (_cachedAgentId) return _cachedAgentId;
|
|
81
|
+
// 3. Look up on-chain: does this wallet own any ERC-8004 token?
|
|
82
|
+
const agentRegistry = new ethers.Contract(status.contracts.agentRegistry, ERC8004_ABI, signer.provider!);
|
|
83
|
+
const balance: bigint = await agentRegistry.balanceOf(signer.address);
|
|
84
|
+
if (balance === 0n) throw new Error("No agent registered. Use agether_register first.");
|
|
85
|
+
const tokenId: bigint = await agentRegistry.tokenOfOwnerByIndex(signer.address, 0);
|
|
86
|
+
_cachedAgentId = tokenId.toString();
|
|
87
|
+
return _cachedAgentId;
|
|
88
|
+
}
|
|
89
|
+
|
|
72
90
|
function ok(text: string) {
|
|
73
91
|
return { content: [{ type: "text" as const, text }] };
|
|
74
92
|
}
|
|
@@ -103,15 +121,17 @@ export default function register(api: any) {
|
|
|
103
121
|
|
|
104
122
|
const result: any = {
|
|
105
123
|
address,
|
|
106
|
-
agentId: cfg.agentId || "not
|
|
124
|
+
agentId: cfg.agentId || _cachedAgentId || "not registered",
|
|
107
125
|
eth: ethers.formatEther(ethBal),
|
|
108
126
|
usdc: ethers.formatUnits(usdcBal, 6),
|
|
109
127
|
};
|
|
110
128
|
|
|
111
|
-
// AgentAccount balances
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
129
|
+
// AgentAccount balances — try to auto-resolve agentId
|
|
130
|
+
try {
|
|
131
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
132
|
+
result.agentId = agentId;
|
|
133
|
+
if (status.contracts.accountFactory) {
|
|
134
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
115
135
|
const accEth = await provider.getBalance(accountAddr);
|
|
116
136
|
const accUsdc = await usdc.balanceOf(accountAddr);
|
|
117
137
|
result.agentAccount = {
|
|
@@ -119,8 +139,8 @@ export default function register(api: any) {
|
|
|
119
139
|
eth: ethers.formatEther(accEth),
|
|
120
140
|
usdc: ethers.formatUnits(accUsdc, 6),
|
|
121
141
|
};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
142
|
+
}
|
|
143
|
+
} catch { /* no agent registered yet */ }
|
|
124
144
|
|
|
125
145
|
return ok(JSON.stringify(result, null, 2));
|
|
126
146
|
} catch (e) { return fail(e); }
|
|
@@ -211,13 +231,15 @@ export default function register(api: any) {
|
|
|
211
231
|
accountAddr = await factory.getAccount(agentId);
|
|
212
232
|
}
|
|
213
233
|
|
|
234
|
+
// Cache agentId for the session so all subsequent tools work
|
|
235
|
+
_cachedAgentId = agentId.toString();
|
|
236
|
+
|
|
214
237
|
return ok(JSON.stringify({
|
|
215
238
|
status: "registered",
|
|
216
239
|
agentId: agentId.toString(),
|
|
217
240
|
address: signer.address,
|
|
218
241
|
agentAccount: accountAddr,
|
|
219
242
|
tx: tx.hash,
|
|
220
|
-
important: "Save this agentId in your plugin config: plugins.entries.agether.config.agentId",
|
|
221
243
|
}));
|
|
222
244
|
} catch (e) { return fail(e); }
|
|
223
245
|
},
|
|
@@ -236,9 +258,9 @@ export default function register(api: any) {
|
|
|
236
258
|
const cfg = getConfig(api);
|
|
237
259
|
const signer = getSigner(cfg);
|
|
238
260
|
const status = await getBackendStatus(cfg);
|
|
239
|
-
|
|
261
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
240
262
|
|
|
241
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
263
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
242
264
|
const morpho = new ethers.Contract(status.contracts.morphoCredit, MORPHO_CREDIT_ABI, signer.provider!);
|
|
243
265
|
|
|
244
266
|
const positions: any[] = [];
|
|
@@ -285,13 +307,13 @@ export default function register(api: any) {
|
|
|
285
307
|
const cfg = getConfig(api);
|
|
286
308
|
const signer = getSigner(cfg);
|
|
287
309
|
const status = await getBackendStatus(cfg);
|
|
288
|
-
|
|
310
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
289
311
|
|
|
290
312
|
const tokenInfo = COLLATERAL_TOKENS[params.token];
|
|
291
313
|
if (!tokenInfo) return fail(`Unsupported token: ${params.token}. Use WETH, wstETH, or cbETH`);
|
|
292
314
|
|
|
293
315
|
const morphoCreditAddr = status.contracts.morphoCredit;
|
|
294
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
316
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
295
317
|
const amount = ethers.parseUnits(params.amount, tokenInfo.decimals);
|
|
296
318
|
|
|
297
319
|
// Check balance
|
|
@@ -351,13 +373,13 @@ export default function register(api: any) {
|
|
|
351
373
|
const cfg = getConfig(api);
|
|
352
374
|
const signer = getSigner(cfg);
|
|
353
375
|
const status = await getBackendStatus(cfg);
|
|
354
|
-
|
|
376
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
355
377
|
|
|
356
378
|
const tokenInfo = COLLATERAL_TOKENS[params.token];
|
|
357
379
|
if (!tokenInfo) return fail(`Unsupported token: ${params.token}`);
|
|
358
380
|
|
|
359
381
|
const morphoCreditAddr = status.contracts.morphoCredit;
|
|
360
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
382
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
361
383
|
const collateralWei = ethers.parseUnits(params.collateralAmount, tokenInfo.decimals);
|
|
362
384
|
const borrowWei = ethers.parseUnits(params.borrowAmount, 6);
|
|
363
385
|
|
|
@@ -526,9 +548,9 @@ export default function register(api: any) {
|
|
|
526
548
|
const cfg = getConfig(api);
|
|
527
549
|
const signer = getSigner(cfg);
|
|
528
550
|
const status = await getBackendStatus(cfg);
|
|
529
|
-
|
|
551
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
530
552
|
|
|
531
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
553
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
532
554
|
const morpho = new ethers.Contract(status.contracts.morphoCredit, MORPHO_CREDIT_ABI, signer.provider!);
|
|
533
555
|
|
|
534
556
|
// Find active collateral
|
|
@@ -583,9 +605,9 @@ export default function register(api: any) {
|
|
|
583
605
|
const cfg = getConfig(api);
|
|
584
606
|
const signer = getSigner(cfg);
|
|
585
607
|
const status = await getBackendStatus(cfg);
|
|
586
|
-
|
|
608
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
587
609
|
|
|
588
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
610
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
589
611
|
const morpho = new ethers.Contract(status.contracts.morphoCredit, MORPHO_CREDIT_ABI, signer.provider!);
|
|
590
612
|
|
|
591
613
|
// Find active collateral with debt
|
|
@@ -652,12 +674,12 @@ export default function register(api: any) {
|
|
|
652
674
|
const cfg = getConfig(api);
|
|
653
675
|
const signer = getSigner(cfg);
|
|
654
676
|
const status = await getBackendStatus(cfg);
|
|
655
|
-
|
|
677
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
656
678
|
|
|
657
679
|
const tokenInfo = COLLATERAL_TOKENS[params.token];
|
|
658
680
|
if (!tokenInfo) return fail(`Unsupported token: ${params.token}`);
|
|
659
681
|
|
|
660
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
682
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
661
683
|
const morpho = new ethers.Contract(status.contracts.morphoCredit, MORPHO_CREDIT_ABI, signer.provider!);
|
|
662
684
|
const pos = await morpho.getPosition(accountAddr, tokenInfo.address);
|
|
663
685
|
|
|
@@ -758,8 +780,10 @@ export default function register(api: any) {
|
|
|
758
780
|
async execute() {
|
|
759
781
|
try {
|
|
760
782
|
const cfg = getConfig(api);
|
|
761
|
-
|
|
762
|
-
const
|
|
783
|
+
const signer = getSigner(cfg);
|
|
784
|
+
const status = await getBackendStatus(cfg);
|
|
785
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
786
|
+
const { data } = await axios.get(`${cfg.backendUrl}/credit/score/${agentId}`);
|
|
763
787
|
return ok(JSON.stringify(data, null, 2));
|
|
764
788
|
} catch (e) { return fail(e); }
|
|
765
789
|
},
|
|
@@ -783,9 +807,9 @@ export default function register(api: any) {
|
|
|
783
807
|
const cfg = getConfig(api);
|
|
784
808
|
const signer = getSigner(cfg);
|
|
785
809
|
const status = await getBackendStatus(cfg);
|
|
786
|
-
|
|
810
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
787
811
|
|
|
788
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
812
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
789
813
|
const amountWei = ethers.parseUnits(params.amount, 6);
|
|
790
814
|
|
|
791
815
|
const usdc = new ethers.Contract(status.contracts.usdc, ERC20_ABI, signer);
|
|
@@ -834,15 +858,15 @@ export default function register(api: any) {
|
|
|
834
858
|
|
|
835
859
|
// Resolve AgentAccount address for x402 payments
|
|
836
860
|
let accountAddress: string | undefined;
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
861
|
+
let agentId: string | undefined;
|
|
862
|
+
try {
|
|
863
|
+
agentId = await resolveAgentId(cfg, signer, status);
|
|
864
|
+
accountAddress = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
865
|
+
} catch { /* no account, pay from EOA */ }
|
|
842
866
|
|
|
843
867
|
// Auto-draw: if enabled, check USDC balance and borrow if needed
|
|
844
868
|
const shouldAutoDraw = params.autoDraw ?? cfg.autoDraw;
|
|
845
|
-
if (shouldAutoDraw && accountAddress &&
|
|
869
|
+
if (shouldAutoDraw && accountAddress && agentId) {
|
|
846
870
|
const usdc = new ethers.Contract(status.contracts.usdc, ERC20_ABI, signer.provider!);
|
|
847
871
|
const accBalance = await usdc.balanceOf(accountAddress);
|
|
848
872
|
// If balance < $1, try to auto-borrow $10 (enough for several x402 calls)
|
|
@@ -871,7 +895,7 @@ export default function register(api: any) {
|
|
|
871
895
|
privateKey: cfg.privateKey,
|
|
872
896
|
rpcUrl: cfg.rpcUrl!,
|
|
873
897
|
backendUrl: cfg.backendUrl!,
|
|
874
|
-
agentId:
|
|
898
|
+
agentId: agentId,
|
|
875
899
|
accountAddress,
|
|
876
900
|
});
|
|
877
901
|
|
|
@@ -912,14 +936,17 @@ export default function register(api: any) {
|
|
|
912
936
|
const usdc = new ethers.Contract(status.contracts.usdc, ERC20_ABI, provider);
|
|
913
937
|
const usdcBal = await usdc.balanceOf(signer.address);
|
|
914
938
|
|
|
915
|
-
let
|
|
939
|
+
let agentId: string | undefined;
|
|
940
|
+
try { agentId = await resolveAgentId(cfg, signer, status); } catch {}
|
|
941
|
+
|
|
942
|
+
let text = `💰 Agent #${agentId || "?"}\n`;
|
|
916
943
|
text += `Address: ${signer.address}\n`;
|
|
917
944
|
text += `ETH: ${parseFloat(ethers.formatEther(ethBal)).toFixed(6)}\n`;
|
|
918
945
|
text += `USDC: $${ethers.formatUnits(usdcBal, 6)}`;
|
|
919
946
|
|
|
920
|
-
if (
|
|
947
|
+
if (agentId && status.contracts.accountFactory) {
|
|
921
948
|
try {
|
|
922
|
-
const accAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
949
|
+
const accAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
923
950
|
const accUsdc = await usdc.balanceOf(accAddr);
|
|
924
951
|
text += `\n\n🏦 AgentAccount: ${accAddr}\nUSDC: $${ethers.formatUnits(accUsdc, 6)}`;
|
|
925
952
|
} catch { /* no account */ }
|
|
@@ -940,13 +967,13 @@ export default function register(api: any) {
|
|
|
940
967
|
const cfg = getConfig(api);
|
|
941
968
|
const signer = getSigner(cfg);
|
|
942
969
|
const status = await getBackendStatus(cfg);
|
|
943
|
-
|
|
970
|
+
const agentId = await resolveAgentId(cfg, signer, status);
|
|
944
971
|
|
|
945
|
-
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory,
|
|
972
|
+
const accountAddr = await getAccountAddr(signer, status.contracts.accountFactory, agentId);
|
|
946
973
|
const morpho = new ethers.Contract(status.contracts.morphoCredit, MORPHO_CREDIT_ABI, signer.provider!);
|
|
947
974
|
const totalDebt = await morpho.getTotalDebt(accountAddr);
|
|
948
975
|
|
|
949
|
-
let text = `📊 Morpho — Agent #${
|
|
976
|
+
let text = `📊 Morpho — Agent #${agentId}\nAccount: ${accountAddr}\nTotal debt: $${ethers.formatUnits(totalDebt, 6)}\n`;
|
|
950
977
|
|
|
951
978
|
for (const [symbol, info] of Object.entries(COLLATERAL_TOKENS)) {
|
|
952
979
|
const pos = await morpho.getPosition(accountAddr, info.address);
|