@agether/agether 2.6.4 → 2.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/agether",
3
- "version": "2.6.4",
3
+ "version": "2.9.0",
4
4
  "description": "OpenClaw plugin for Agether — onchain credit for AI agents on Ethereum & Base",
5
5
  "main": "src/index.ts",
6
6
  "openclaw": {
@@ -460,12 +460,12 @@ Contracts are deployed on both **Ethereum** and **Base** mainnets. The SDK auto-
460
460
 
461
461
  | Contract | Address |
462
462
  |----------|---------|
463
- | Agether4337Factory | `0x8aeE4961EfaA4a1D36e2b24C5b430C8613fB5b8C` |
464
- | Agether8004ValidationModule | `0x7B18a7E3D5B3d043FC3525Efcd9a2bB1aE1369Ab` |
465
- | AgetherHookMultiplexer | `0x2D98eff4b959F3dc76f14c5682A8546438406c4A` |
466
- | Agether7579Bootstrap | `0x5e8e4644c628CB464936981e338635476d012B5F` |
467
- | Agether8004Scorer | `0xA1a0B09147688a09A3027F960623Ae16d1ca7F69` |
468
- | TimelockController | `0x7f104DBe209E2a05FFc1700b27eaE1C397f011c4` |
463
+ | Agether4337Factory | `0x73f4153bf1d46dB203Db27fc8FC942f6279D8d38` |
464
+ | Agether8004ValidationModule | `0x85C8C97cE5AE540a4408D6A77a6D3aFcA9BCdB71` |
465
+ | AgetherHookMultiplexer | `0x688cab46ce5A7450D706e9E3C8e0F31BaEa6c8BE` |
466
+ | Agether7579Bootstrap | `0xbD0BDFE70fDB88fc03F2Ea22B81A2dfc99298E42` |
467
+ | Agether8004Scorer | `0x33eB904fe9975e2D8c577aD7e5B14CefBD4A65E1` |
468
+ | TimelockController | `0xB3FD04f0B7c9DeC7f7B52d5c2CdfdCB3Fc9eE111` |
469
469
  | USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
470
470
  | WETH | `0x4200000000000000000000000000000000000006` |
471
471
  | wstETH | `0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452` |
@@ -475,12 +475,12 @@ Contracts are deployed on both **Ethereum** and **Base** mainnets. The SDK auto-
475
475
 
476
476
  | Contract | Address |
477
477
  |----------|---------|
478
- | Agether4337Factory | `0xE350660Ab3EA87b50233854eacCC6328e268fb48` |
479
- | Agether8004ValidationModule | `0x87Aa07Be4Ab4A2e8EeBf4a4e2451c775D0e3fbf1` |
480
- | AgetherHookMultiplexer | `0xC0b96e36B20d6689F4E4b8C7A0c19C28e8B45B8B` |
481
- | Agether7579Bootstrap | `0xD1268B50149e468591Bcba5f6fD3E87b49D43008` |
482
- | Agether8004Scorer | `0xd281a8ec667E406Fcf1097A64A65d1C88Fb0F7Fa` |
483
- | TimelockController | `0x2033CD354aAf19191F23211c6A6974fCE038AFBe` |
478
+ | Agether4337Factory | `0xb6363c2B5C72C14D3fC4261e3dd836D8966bE072` |
479
+ | Agether8004ValidationModule | `0xE282fB8615abb8bA53F07b8BAB2937C78fE3867D` |
480
+ | AgetherHookMultiplexer | `0xeD62ac874F58CEc9F065aB8e6872752Eb0F6eA14` |
481
+ | Agether7579Bootstrap | `0x055C2e70dd011C4ADEEfB795Ab77D74437be6D33` |
482
+ | Agether8004Scorer | `0x960853769d52B14aA0daeab7E1E59f5c9299cb65` |
483
+ | TimelockController | `0x78e0227f9DE577e583B8149C73F0bA1E7200AD01` |
484
484
  | USDC | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` |
485
485
  | WETH | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` |
486
486
  | wstETH | `0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0` |
package/src/index.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * Agether OpenClaw Plugin — thin wrapper over @agether/sdk
3
3
  *
4
- * Each tool = MorphoClient / X402Client call → format result with txLink.
4
+ * Architecture:
5
+ * - AgetherClient: registration, balances, withdrawals, sponsorship, identity, scoring
6
+ * - MorphoClient: Morpho Blue lending only (deposit, borrow, repay, supply, withdraw collateral)
7
+ * - X402Client: HTTP 402 payment protocol
8
+ *
9
+ * Each tool = AgetherClient / MorphoClient / X402Client call → format result with txLink.
5
10
  * Market discovery via Morpho GraphQL API (no backend dependency for markets).
6
11
  *
7
12
  * Supported chains: Ethereum (1, default), Base (8453).
@@ -18,6 +23,7 @@
18
23
  import * as fs from "fs";
19
24
  import * as path from "path";
20
25
  import {
26
+ AgetherClient,
21
27
  MorphoClient,
22
28
  X402Client,
23
29
  ScoringClient,
@@ -192,8 +198,28 @@ function requireChain(cfg: PluginConfig): void {
192
198
  }
193
199
  }
194
200
 
195
- function createClient(cfg: PluginConfig): MorphoClient {
201
+ /**
202
+ * Create an AgetherClient for protocol operations (register, balances, withdraw, sponsor).
203
+ * If agentId is known, creates a client bound to that agent. Otherwise creates an unbound
204
+ * client (only register() and getBalances() available).
205
+ */
206
+ function createAgetherClient(cfg: PluginConfig): AgetherClient {
207
+ const agentId = cachedAgentIds[cfg.chainId] || cfg.agentId;
208
+ if (agentId) {
209
+ return AgetherClient.fromPrivateKey(cfg.privateKey, BigInt(agentId), cfg.chainId);
210
+ }
211
+ return AgetherClient.fromPrivateKey(cfg.privateKey, cfg.chainId);
212
+ }
213
+
214
+ /**
215
+ * Create a MorphoClient for Morpho Blue lending operations.
216
+ * Requires agentId — use AgetherClient.register() first.
217
+ */
218
+ function createMorphoClient(cfg: PluginConfig): MorphoClient {
196
219
  const agentId = cachedAgentIds[cfg.chainId] || cfg.agentId;
220
+ if (!agentId) {
221
+ throw new Error("agentId not set. Register first with agether_register, then try again.");
222
+ }
197
223
  return new MorphoClient({
198
224
  privateKey: cfg.privateKey,
199
225
  rpcUrl: cfg.rpcUrl,
@@ -202,6 +228,11 @@ function createClient(cfg: PluginConfig): MorphoClient {
202
228
  });
203
229
  }
204
230
 
231
+ /** @deprecated Use createAgetherClient or createMorphoClient instead */
232
+ function createClient(cfg: PluginConfig): MorphoClient {
233
+ return createMorphoClient(cfg);
234
+ }
235
+
205
236
  /** Persist agentId to openclaw.json so it survives restarts. */
206
237
  function persistAgentId(agentId: string): string {
207
238
  cachedAgentIds[activeChainId] = agentId;
@@ -263,7 +294,7 @@ export default function register(api: any) {
263
294
  async execute() {
264
295
  try {
265
296
  const cfg = getConfig(api);
266
- const client = createClient(cfg);
297
+ const client = createAgetherClient(cfg);
267
298
  const result = await client.getBalances();
268
299
  return ok(JSON.stringify(result, null, 2));
269
300
  } catch (e) { return fail(e); }
@@ -281,16 +312,16 @@ export default function register(api: any) {
281
312
  parameters: {
282
313
  type: "object",
283
314
  properties: {
284
- name: { type: "string", description: "Agent display name" },
315
+ name: { type: "string", description: "Agent display name (informational only)" },
285
316
  },
286
- required: ["name"],
317
+ required: [],
287
318
  },
288
- async execute(_id: string, params: { name: string }) {
319
+ async execute(_id: string, _params: { name?: string }) {
289
320
  try {
290
321
  const cfg = getConfig(api);
291
322
  requireChain(cfg);
292
- const client = createClient(cfg);
293
- const result = await client.register(params.name);
323
+ const client = createAgetherClient(cfg);
324
+ const result = await client.register();
294
325
  const persistStatus = persistAgentId(result.agentId);
295
326
  const kyaMessage = result.kyaRequired
296
327
  ? "⚠️ KYA required: submit your agent code hash for review before using credit"
@@ -328,11 +359,7 @@ export default function register(api: any) {
328
359
  try {
329
360
  const cfg = getConfig(api);
330
361
  // Verify onchain that this agentId exists and belongs to this wallet
331
- const client = new MorphoClient({
332
- privateKey: cfg.privateKey,
333
- rpcUrl: cfg.rpcUrl,
334
- agentId: params.agentId,
335
- });
362
+ const client = AgetherClient.fromPrivateKey(cfg.privateKey, BigInt(params.agentId), cfg.chainId);
336
363
  const acctAddr = await client.getAccountAddress();
337
364
  const persistStatus = persistAgentId(params.agentId);
338
365
  return ok(JSON.stringify({
@@ -403,7 +430,7 @@ export default function register(api: any) {
403
430
  async execute() {
404
431
  try {
405
432
  const cfg = getConfig(api);
406
- const client = createClient(cfg);
433
+ const client = createAgetherClient(cfg);
407
434
  const required = await client.isKyaRequired();
408
435
  return ok(
409
436
  required
@@ -438,7 +465,6 @@ export default function register(api: any) {
438
465
  try {
439
466
  const cfg = getConfig(api);
440
467
  requireChain(cfg);
441
- const client = createClient(cfg);
442
468
 
443
469
  // Build the calldata for ERC8004ValidationModule.setValidationRegistry — the owner (Timelock) must execute it
444
470
  const { ethers } = await import("ethers");
@@ -486,7 +512,7 @@ export default function register(api: any) {
486
512
  async execute() {
487
513
  try {
488
514
  const cfg = getConfig(api);
489
- const client = createClient(cfg);
515
+ const client = createMorphoClient(cfg);
490
516
  const [status, maxBorrow] = await Promise.all([
491
517
  client.getStatus(),
492
518
  client.getMaxBorrowable(),
@@ -548,7 +574,7 @@ export default function register(api: any) {
548
574
  try {
549
575
  const cfg = getConfig(api);
550
576
  requireChain(cfg);
551
- const client = createClient(cfg);
577
+ const client = createMorphoClient(cfg);
552
578
  const result = await client.supplyCollateral(params.token, params.amount);
553
579
  return ok(JSON.stringify({
554
580
  status: "deposited",
@@ -581,7 +607,7 @@ export default function register(api: any) {
581
607
  try {
582
608
  const cfg = getConfig(api);
583
609
  requireChain(cfg);
584
- const client = createClient(cfg);
610
+ const client = createMorphoClient(cfg);
585
611
  const result = await client.depositAndBorrow(
586
612
  params.token,
587
613
  params.collateralAmount,
@@ -602,17 +628,17 @@ export default function register(api: any) {
602
628
  // TOOL: morpho_sponsor
603
629
  // ═══════════════════════════════════════════════════════
604
630
  api.registerTool({
605
- name: "morpho_sponsor",
631
+ name: "agether_sponsor",
606
632
  description:
607
- "Transfer collateral tokens to another agent's AgentAccount. " +
608
- "The target agent can then supply the collateral to Morpho Blue themselves.",
633
+ "Transfer tokens to another agent's Safe account (or any address). " +
634
+ "The target agent can then supply the tokens to Morpho Blue or use them directly.",
609
635
  parameters: {
610
636
  type: "object",
611
637
  properties: {
612
638
  agentId: { type: "string", description: "Target agent's ERC-8004 ID (e.g. '17676')" },
613
- agentAddress: { type: "string", description: "Target AgentAccount address (alternative to agentId)" },
614
- amount: { type: "string", description: "Collateral amount (e.g. '0.05')" },
615
- token: { type: "string", description: "Collateral token" },
639
+ agentAddress: { type: "string", description: "Target account address (alternative to agentId)" },
640
+ amount: { type: "string", description: "Token amount (e.g. '0.05')" },
641
+ token: { type: "string", description: "Token to send (e.g. 'WETH', 'USDC')" },
616
642
  },
617
643
  required: ["amount", "token"],
618
644
  },
@@ -621,7 +647,7 @@ export default function register(api: any) {
621
647
  if (!params.agentId && !params.agentAddress) return fail("Provide either agentId or agentAddress");
622
648
  const cfg = getConfig(api);
623
649
  requireChain(cfg);
624
- const client = createClient(cfg);
650
+ const client = createAgetherClient(cfg);
625
651
 
626
652
  const target = params.agentId
627
653
  ? { agentId: params.agentId }
@@ -632,7 +658,7 @@ export default function register(api: any) {
632
658
  status: "sponsored",
633
659
  target: result.targetAccount,
634
660
  targetAgentId: result.targetAgentId || "by address",
635
- collateral: `${params.amount} ${params.token}`,
661
+ amount: `${params.amount} ${params.token}`,
636
662
  tx: txLink(result.tx),
637
663
  }));
638
664
  } catch (e) { return fail(e); }
@@ -659,7 +685,7 @@ export default function register(api: any) {
659
685
  try {
660
686
  const cfg = getConfig(api);
661
687
  requireChain(cfg);
662
- const client = createClient(cfg);
688
+ const client = createMorphoClient(cfg);
663
689
  const result = await client.borrow(params.amount, params.token);
664
690
  return ok(JSON.stringify({
665
691
  status: "borrowed",
@@ -692,7 +718,7 @@ export default function register(api: any) {
692
718
  try {
693
719
  const cfg = getConfig(api);
694
720
  requireChain(cfg);
695
- const client = createClient(cfg);
721
+ const client = createMorphoClient(cfg);
696
722
  const result = await client.repay(params.amount, params.token);
697
723
  return ok(JSON.stringify({
698
724
  status: "repaid",
@@ -726,7 +752,7 @@ export default function register(api: any) {
726
752
  try {
727
753
  const cfg = getConfig(api);
728
754
  requireChain(cfg);
729
- const client = createClient(cfg);
755
+ const client = createMorphoClient(cfg);
730
756
  // Default: keep in AgentAccount. toEoa=true → send to EOA.
731
757
  const receiver = params.toEoa ? await client.getSignerAddress() : await client.getAccountAddress();
732
758
  const result = await client.withdrawCollateral(params.token, params.amount, undefined, receiver);
@@ -767,7 +793,7 @@ export default function register(api: any) {
767
793
  try {
768
794
  const cfg = getConfig(api);
769
795
  requireChain(cfg);
770
- const client = createClient(cfg);
796
+ const client = createMorphoClient(cfg);
771
797
  const result = await client.supplyAsset(params.amount, params.market);
772
798
  return ok(JSON.stringify({
773
799
  status: "supplied",
@@ -804,7 +830,7 @@ export default function register(api: any) {
804
830
  async execute(_id: string, params: { market?: string }) {
805
831
  try {
806
832
  const cfg = getConfig(api);
807
- const client = createClient(cfg);
833
+ const client = createMorphoClient(cfg);
808
834
  const positions = await client.getSupplyPositions(params.market);
809
835
 
810
836
  if (positions.length === 0) {
@@ -860,7 +886,7 @@ export default function register(api: any) {
860
886
  try {
861
887
  const cfg = getConfig(api);
862
888
  requireChain(cfg);
863
- const client = createClient(cfg);
889
+ const client = createMorphoClient(cfg);
864
890
  // Default: keep in AgentAccount. toEoa=true → send to EOA.
865
891
  const receiver = params.toEoa ? await client.getSignerAddress() : await client.getAccountAddress();
866
892
  const result = await client.withdrawSupply(params.amount, params.market, receiver);
@@ -893,7 +919,7 @@ export default function register(api: any) {
893
919
  async execute(_id: string, params: { token?: string }) {
894
920
  try {
895
921
  const cfg = getConfig(api);
896
- const client = createClient(cfg);
922
+ const client = createMorphoClient(cfg);
897
923
  const rates = await client.getMarketRates(params.token);
898
924
 
899
925
  if (rates.length === 0) return ok("No markets found.");
@@ -933,8 +959,8 @@ export default function register(api: any) {
933
959
  try {
934
960
  const cfg = getConfig(api);
935
961
  requireChain(cfg);
936
- const client = createClient(cfg);
937
- const agentId = client.getAgentId();
962
+ const client = createAgetherClient(cfg);
963
+ const agentId = client.getAgentId().toString();
938
964
 
939
965
  if (params.refresh) {
940
966
  // x402-gated fresh score via ScoringClient
@@ -983,13 +1009,12 @@ export default function register(api: any) {
983
1009
  try {
984
1010
  const cfg = getConfig(api);
985
1011
  requireChain(cfg);
986
- const client = createClient(cfg);
1012
+ const client = createAgetherClient(cfg);
987
1013
  const result = await client.fundAccount(params.amount);
988
1014
  return ok(JSON.stringify({
989
1015
  status: "funded",
990
1016
  amount: `$${params.amount}`,
991
- agentAccount: result.agentAccount,
992
- tx: txLink(result.tx),
1017
+ tx: txLink(result.txHash),
993
1018
  }));
994
1019
  } catch (e) { return fail(e); }
995
1020
  },
@@ -1016,7 +1041,7 @@ export default function register(api: any) {
1016
1041
  try {
1017
1042
  const cfg = getConfig(api);
1018
1043
  requireChain(cfg);
1019
- const client = createClient(cfg);
1044
+ const client = createAgetherClient(cfg);
1020
1045
  const result = await client.withdrawToken(params.token, params.amount);
1021
1046
  return ok(JSON.stringify({
1022
1047
  status: "withdrawn",
@@ -1048,7 +1073,7 @@ export default function register(api: any) {
1048
1073
  try {
1049
1074
  const cfg = getConfig(api);
1050
1075
  requireChain(cfg);
1051
- const client = createClient(cfg);
1076
+ const client = createAgetherClient(cfg);
1052
1077
  const result = await client.withdrawEth(params.amount);
1053
1078
  return ok(JSON.stringify({
1054
1079
  status: "withdrawn",
@@ -1084,13 +1109,13 @@ export default function register(api: any) {
1084
1109
  const cfg = getConfig(api);
1085
1110
  requireChain(cfg);
1086
1111
  const agetherCfg = api.config?.plugins?.entries?.agether?.config || {};
1087
- const client = createClient(cfg);
1112
+ const agether = createAgetherClient(cfg);
1088
1113
 
1089
1114
  let accountAddress: string | undefined;
1090
1115
  let agentId: string | undefined;
1091
1116
  try {
1092
- agentId = client.getAgentId();
1093
- accountAddress = await client.getAccountAddress();
1117
+ agentId = agether.getAgentId().toString();
1118
+ accountAddress = await agether.getAccountAddress();
1094
1119
  } catch (e) {
1095
1120
  console.warn('[agether] x402_pay: getAccountAddress failed, paying from EOA:', e instanceof Error ? e.message : e);
1096
1121
  }
@@ -1117,8 +1142,9 @@ export default function register(api: any) {
1117
1142
  let result;
1118
1143
  if ((autoDrawEnabled || autoYieldEnabled) && agentId) {
1119
1144
  // Use payWithAutoDraw which handles waterfall: balance → yield → borrow
1145
+ const morpho = createMorphoClient(cfg);
1120
1146
  const fetchOpts: any = {
1121
- morphoClient: client,
1147
+ morphoClient: morpho,
1122
1148
  };
1123
1149
  if (params.method?.toUpperCase() === "POST" && params.body) {
1124
1150
  fetchOpts.method = "POST";
@@ -1172,7 +1198,7 @@ export default function register(api: any) {
1172
1198
  async execute() {
1173
1199
  try {
1174
1200
  const cfg = getConfig(api);
1175
- const client = createClient(cfg);
1201
+ const client = createMorphoClient(cfg);
1176
1202
  const result = await client.getMaxBorrowable();
1177
1203
 
1178
1204
  const formatted = {
@@ -1205,13 +1231,14 @@ export default function register(api: any) {
1205
1231
  const cfg = getConfig(api);
1206
1232
  const agetherCfg = api.config?.plugins?.entries?.agether?.config ?? {};
1207
1233
  const healthThreshold = agetherCfg.healthAlertThreshold ?? 70;
1208
- const client = createClient(cfg);
1234
+ const agether = createAgetherClient(cfg);
1235
+ const morpho = createMorphoClient(cfg);
1209
1236
 
1210
1237
  // Gather everything in parallel where possible
1211
1238
  const [balances, status, maxBorrow] = await Promise.all([
1212
- client.getBalances(),
1213
- client.getStatus(),
1214
- client.getMaxBorrowable(),
1239
+ agether.getBalances(),
1240
+ morpho.getStatus(),
1241
+ morpho.getMaxBorrowable(),
1215
1242
  ]);
1216
1243
 
1217
1244
  // Build per-position health analysis
@@ -1330,7 +1357,7 @@ export default function register(api: any) {
1330
1357
  // 3. Agent registration
1331
1358
  try {
1332
1359
  const cfg = getConfig(api);
1333
- const client = createClient(cfg);
1360
+ const client = createAgetherClient(cfg);
1334
1361
  const balances = await client.getBalances();
1335
1362
 
1336
1363
  if (balances.agentId && balances.agentId !== '?') {
@@ -1375,7 +1402,7 @@ export default function register(api: any) {
1375
1402
  handler: async () => {
1376
1403
  try {
1377
1404
  const cfg = getConfig(api);
1378
- const client = createClient(cfg);
1405
+ const client = createAgetherClient(cfg);
1379
1406
  const b = await client.getBalances();
1380
1407
 
1381
1408
  const nz = (v: string) => parseFloat(v) > 0;
@@ -1417,7 +1444,7 @@ export default function register(api: any) {
1417
1444
  handler: async () => {
1418
1445
  try {
1419
1446
  const cfg = getConfig(api);
1420
- const client = createClient(cfg);
1447
+ const client = createMorphoClient(cfg);
1421
1448
  const [s, maxBorrow] = await Promise.all([
1422
1449
  client.getStatus(),
1423
1450
  client.getMaxBorrowable(),
@@ -1450,12 +1477,13 @@ export default function register(api: any) {
1450
1477
  const cfg = getConfig(api);
1451
1478
  const agetherCfg = api.config?.plugins?.entries?.agether?.config ?? {};
1452
1479
  const healthThreshold = agetherCfg.healthAlertThreshold ?? 70;
1453
- const client = createClient(cfg);
1480
+ const agether = createAgetherClient(cfg);
1481
+ const morpho = createMorphoClient(cfg);
1454
1482
 
1455
1483
  const [balances, status, maxBorrow] = await Promise.all([
1456
- client.getBalances(),
1457
- client.getStatus(),
1458
- client.getMaxBorrowable(),
1484
+ agether.getBalances(),
1485
+ morpho.getStatus(),
1486
+ morpho.getMaxBorrowable(),
1459
1487
  ]);
1460
1488
 
1461
1489
  let text = `🏥 Health — Agent #${balances.agentId}\n`;
@@ -1489,7 +1517,7 @@ export default function register(api: any) {
1489
1517
  handler: async () => {
1490
1518
  try {
1491
1519
  const cfg = getConfig(api);
1492
- const client = createClient(cfg);
1520
+ const client = createMorphoClient(cfg);
1493
1521
  const rates = await client.getMarketRates();
1494
1522
 
1495
1523
  if (rates.length === 0) return { text: "No markets found." };
@@ -1516,7 +1544,7 @@ export default function register(api: any) {
1516
1544
  // starts with awareness of the current state.
1517
1545
  try {
1518
1546
  const cfg = getConfig(api);
1519
- const client = createClient(cfg);
1547
+ const client = createAgetherClient(cfg);
1520
1548
  const balances = await client.getBalances();
1521
1549
  const agentId = balances.agentId ?? "?";
1522
1550
  const safeUsdc = balances.agentAccount?.usdc ?? "0";