@agether/sdk 2.15.1 → 2.16.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/cli.js CHANGED
@@ -30,6 +30,57 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
+ // src/utils/retry.ts
34
+ function isRetriable(error) {
35
+ const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
36
+ return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
37
+ }
38
+ async function withRetry(fn, options = {}) {
39
+ const {
40
+ maxRetries = 3,
41
+ baseDelay = 1e3,
42
+ maxDelay = 15e3,
43
+ onRetry
44
+ } = options;
45
+ let lastError;
46
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
47
+ try {
48
+ return await fn();
49
+ } catch (error) {
50
+ lastError = error instanceof Error ? error : new Error(String(error));
51
+ if (attempt >= maxRetries || !isRetriable(error)) {
52
+ throw lastError;
53
+ }
54
+ const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
55
+ const jitter = delay * (0.5 + Math.random() * 0.5);
56
+ onRetry?.(attempt, lastError);
57
+ await new Promise((resolve) => setTimeout(resolve, jitter));
58
+ }
59
+ }
60
+ throw lastError;
61
+ }
62
+ var RETRIABLE_PATTERNS;
63
+ var init_retry = __esm({
64
+ "src/utils/retry.ts"() {
65
+ "use strict";
66
+ RETRIABLE_PATTERNS = [
67
+ "ECONNRESET",
68
+ "ECONNREFUSED",
69
+ "ENOTFOUND",
70
+ "ETIMEDOUT",
71
+ "fetch failed",
72
+ "network error",
73
+ "socket hang up",
74
+ "rate limit",
75
+ "429",
76
+ "502",
77
+ "503",
78
+ "504",
79
+ "timeout"
80
+ ];
81
+ }
82
+ });
83
+
33
84
  // src/types/index.ts
34
85
  var AgetherError;
35
86
  var init_types = __esm({
@@ -280,6 +331,7 @@ var init_MorphoClient = __esm({
280
331
  "use strict";
281
332
  import_ethers = require("ethers");
282
333
  import_axios = __toESM(require("axios"));
334
+ init_retry();
283
335
  init_types();
284
336
  init_abis();
285
337
  init_config();
@@ -429,7 +481,10 @@ var init_MorphoClient = __esm({
429
481
  }
430
482
  }`;
431
483
  try {
432
- const resp = await import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
484
+ const resp = await withRetry(
485
+ () => import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 }),
486
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
487
+ );
433
488
  const items = resp.data?.data?.markets?.items ?? [];
434
489
  this._discoveredMarkets = items.map((m) => ({
435
490
  uniqueKey: m.uniqueKey,
@@ -613,7 +668,10 @@ var init_MorphoClient = __esm({
613
668
  }
614
669
  }
615
670
  }`;
616
- const resp = await import_axios.default.post(MORPHO_API_URL, { query: posQuery }, { timeout: 15e3 });
671
+ const resp = await withRetry(
672
+ () => import_axios.default.post(MORPHO_API_URL, { query: posQuery }, { timeout: 15e3 }),
673
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho position query retry ${n}:`, e.message) }
674
+ );
617
675
  const items = resp.data?.data?.marketPositions?.items ?? [];
618
676
  for (const item of items) {
619
677
  const supplyShares = BigInt(item.supplyShares ?? "0");
@@ -832,7 +890,10 @@ var init_MorphoClient = __esm({
832
890
  }
833
891
  }`;
834
892
  try {
835
- const resp = await import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
893
+ const resp = await withRetry(
894
+ () => import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 }),
895
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
896
+ );
836
897
  let items = resp.data?.data?.markets?.items ?? [];
837
898
  if (searchTerm && collateralSymbolOrAddress && !collateralSymbolOrAddress.startsWith("0x")) {
838
899
  const sym = collateralSymbolOrAddress.toUpperCase();
@@ -898,7 +959,10 @@ var init_MorphoClient = __esm({
898
959
  }
899
960
  }`;
900
961
  try {
901
- const resp = await import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
962
+ const resp = await withRetry(
963
+ () => import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 }),
964
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
965
+ );
902
966
  let items = resp.data?.data?.markets?.items ?? [];
903
967
  items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers.ethers.ZeroAddress);
904
968
  const searchUpper = search.toUpperCase();
package/dist/index.d.mts CHANGED
@@ -1413,7 +1413,7 @@ declare class AgentIdentityClient {
1413
1413
  /**
1414
1414
  * Give positive feedback (shorthand)
1415
1415
  */
1416
- givePosisitiveFeedback(agentId: bigint, value?: number, tags?: {
1416
+ givePositiveFeedback(agentId: bigint, value?: number, tags?: {
1417
1417
  tag1?: string;
1418
1418
  tag2?: string;
1419
1419
  }): Promise<string>;
@@ -1567,4 +1567,26 @@ declare function getMorphoBlueAddress(chainId: ChainId): string;
1567
1567
  */
1568
1568
  declare function getContractAddresses(chainId: ChainId): ContractAddresses;
1569
1569
 
1570
- export { ACCOUNT_FACTORY_ABI, AGENT_REPUTATION_ABI, AGETHER_4337_FACTORY_ABI, AGETHER_8004_SCORER_ABI, AGETHER_8004_VALIDATION_MODULE_ABI, AGETHER_HOOK_MULTIPLEXER_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type AgetherSigner, type AgetherViemWallet, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ENTRYPOINT_V07_ABI, ERC20_ABI, ERC8004_VALIDATION_MODULE_ABI, HOOK_MULTIPLEXER_ABI, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, type MarketFilter, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PayFromYieldResult, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, SAFE7579_ACCOUNT_ABI, SAFE_AGENT_FACTORY_ABI, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type SupplyAssetResult, type SupplyPositionResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawFromAccountResult, type WithdrawResult, type WithdrawSupplyResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getContractAddresses, getDefaultConfig, getMorphoBlueAddress, getUSDCAddress, parseUnits, rateToBps };
1570
+ /**
1571
+ * Retry utility with exponential backoff for network operations.
1572
+ *
1573
+ * Phase 2: Added to handle transient RPC failures, rate limits,
1574
+ * and network timeouts gracefully instead of failing immediately.
1575
+ */
1576
+ interface RetryOptions {
1577
+ /** Maximum number of attempts (default: 3) */
1578
+ maxRetries?: number;
1579
+ /** Base delay in ms (default: 1000) */
1580
+ baseDelay?: number;
1581
+ /** Maximum delay in ms (default: 15000) */
1582
+ maxDelay?: number;
1583
+ /** Called before each retry with attempt number and error */
1584
+ onRetry?: (attempt: number, error: Error) => void;
1585
+ }
1586
+ /**
1587
+ * Execute an async function with retry and exponential backoff.
1588
+ * Only retries on transient network errors, not business logic errors.
1589
+ */
1590
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
1591
+
1592
+ export { ACCOUNT_FACTORY_ABI, AGENT_REPUTATION_ABI, AGETHER_4337_FACTORY_ABI, AGETHER_8004_SCORER_ABI, AGETHER_8004_VALIDATION_MODULE_ABI, AGETHER_HOOK_MULTIPLEXER_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type AgetherSigner, type AgetherViemWallet, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ENTRYPOINT_V07_ABI, ERC20_ABI, ERC8004_VALIDATION_MODULE_ABI, HOOK_MULTIPLEXER_ABI, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, type MarketFilter, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PayFromYieldResult, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, type RetryOptions, SAFE7579_ACCOUNT_ABI, SAFE_AGENT_FACTORY_ABI, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type SupplyAssetResult, type SupplyPositionResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawFromAccountResult, type WithdrawResult, type WithdrawSupplyResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getContractAddresses, getDefaultConfig, getMorphoBlueAddress, getUSDCAddress, parseUnits, rateToBps, withRetry };
package/dist/index.d.ts CHANGED
@@ -1413,7 +1413,7 @@ declare class AgentIdentityClient {
1413
1413
  /**
1414
1414
  * Give positive feedback (shorthand)
1415
1415
  */
1416
- givePosisitiveFeedback(agentId: bigint, value?: number, tags?: {
1416
+ givePositiveFeedback(agentId: bigint, value?: number, tags?: {
1417
1417
  tag1?: string;
1418
1418
  tag2?: string;
1419
1419
  }): Promise<string>;
@@ -1567,4 +1567,26 @@ declare function getMorphoBlueAddress(chainId: ChainId): string;
1567
1567
  */
1568
1568
  declare function getContractAddresses(chainId: ChainId): ContractAddresses;
1569
1569
 
1570
- export { ACCOUNT_FACTORY_ABI, AGENT_REPUTATION_ABI, AGETHER_4337_FACTORY_ABI, AGETHER_8004_SCORER_ABI, AGETHER_8004_VALIDATION_MODULE_ABI, AGETHER_HOOK_MULTIPLEXER_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type AgetherSigner, type AgetherViemWallet, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ENTRYPOINT_V07_ABI, ERC20_ABI, ERC8004_VALIDATION_MODULE_ABI, HOOK_MULTIPLEXER_ABI, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, type MarketFilter, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PayFromYieldResult, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, SAFE7579_ACCOUNT_ABI, SAFE_AGENT_FACTORY_ABI, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type SupplyAssetResult, type SupplyPositionResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawFromAccountResult, type WithdrawResult, type WithdrawSupplyResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getContractAddresses, getDefaultConfig, getMorphoBlueAddress, getUSDCAddress, parseUnits, rateToBps };
1570
+ /**
1571
+ * Retry utility with exponential backoff for network operations.
1572
+ *
1573
+ * Phase 2: Added to handle transient RPC failures, rate limits,
1574
+ * and network timeouts gracefully instead of failing immediately.
1575
+ */
1576
+ interface RetryOptions {
1577
+ /** Maximum number of attempts (default: 3) */
1578
+ maxRetries?: number;
1579
+ /** Base delay in ms (default: 1000) */
1580
+ baseDelay?: number;
1581
+ /** Maximum delay in ms (default: 15000) */
1582
+ maxDelay?: number;
1583
+ /** Called before each retry with attempt number and error */
1584
+ onRetry?: (attempt: number, error: Error) => void;
1585
+ }
1586
+ /**
1587
+ * Execute an async function with retry and exponential backoff.
1588
+ * Only retries on transient network errors, not business logic errors.
1589
+ */
1590
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
1591
+
1592
+ export { ACCOUNT_FACTORY_ABI, AGENT_REPUTATION_ABI, AGETHER_4337_FACTORY_ABI, AGETHER_8004_SCORER_ABI, AGETHER_8004_VALIDATION_MODULE_ABI, AGETHER_HOOK_MULTIPLEXER_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type AgetherSigner, type AgetherViemWallet, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ENTRYPOINT_V07_ABI, ERC20_ABI, ERC8004_VALIDATION_MODULE_ABI, HOOK_MULTIPLEXER_ABI, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, type MarketFilter, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PayFromYieldResult, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, type RetryOptions, SAFE7579_ACCOUNT_ABI, SAFE_AGENT_FACTORY_ABI, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type SupplyAssetResult, type SupplyPositionResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawFromAccountResult, type WithdrawResult, type WithdrawSupplyResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getContractAddresses, getDefaultConfig, getMorphoBlueAddress, getUSDCAddress, parseUnits, rateToBps, withRetry };
package/dist/index.js CHANGED
@@ -69,7 +69,8 @@ __export(index_exports, {
69
69
  getMorphoBlueAddress: () => getMorphoBlueAddress,
70
70
  getUSDCAddress: () => getUSDCAddress,
71
71
  parseUnits: () => parseUnits,
72
- rateToBps: () => rateToBps
72
+ rateToBps: () => rateToBps,
73
+ withRetry: () => withRetry
73
74
  });
74
75
  module.exports = __toCommonJS(index_exports);
75
76
 
@@ -1200,6 +1201,53 @@ var AgetherClient = class _AgetherClient {
1200
1201
  // src/clients/MorphoClient.ts
1201
1202
  var import_ethers2 = require("ethers");
1202
1203
  var import_axios2 = __toESM(require("axios"));
1204
+
1205
+ // src/utils/retry.ts
1206
+ var RETRIABLE_PATTERNS = [
1207
+ "ECONNRESET",
1208
+ "ECONNREFUSED",
1209
+ "ENOTFOUND",
1210
+ "ETIMEDOUT",
1211
+ "fetch failed",
1212
+ "network error",
1213
+ "socket hang up",
1214
+ "rate limit",
1215
+ "429",
1216
+ "502",
1217
+ "503",
1218
+ "504",
1219
+ "timeout"
1220
+ ];
1221
+ function isRetriable(error) {
1222
+ const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
1223
+ return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
1224
+ }
1225
+ async function withRetry(fn, options = {}) {
1226
+ const {
1227
+ maxRetries = 3,
1228
+ baseDelay = 1e3,
1229
+ maxDelay = 15e3,
1230
+ onRetry
1231
+ } = options;
1232
+ let lastError;
1233
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1234
+ try {
1235
+ return await fn();
1236
+ } catch (error) {
1237
+ lastError = error instanceof Error ? error : new Error(String(error));
1238
+ if (attempt >= maxRetries || !isRetriable(error)) {
1239
+ throw lastError;
1240
+ }
1241
+ const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
1242
+ const jitter = delay * (0.5 + Math.random() * 0.5);
1243
+ onRetry?.(attempt, lastError);
1244
+ await new Promise((resolve) => setTimeout(resolve, jitter));
1245
+ }
1246
+ }
1247
+ throw lastError;
1248
+ }
1249
+
1250
+ // src/clients/MorphoClient.ts
1203
1251
  var MORPHO_API_URL2 = "https://api.morpho.org/graphql";
1204
1252
  var MODE_SINGLE2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
1205
1253
  var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
@@ -1346,7 +1394,10 @@ var MorphoClient = class {
1346
1394
  }
1347
1395
  }`;
1348
1396
  try {
1349
- const resp = await import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1397
+ const resp = await withRetry(
1398
+ () => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1399
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1400
+ );
1350
1401
  const items = resp.data?.data?.markets?.items ?? [];
1351
1402
  this._discoveredMarkets = items.map((m) => ({
1352
1403
  uniqueKey: m.uniqueKey,
@@ -1530,7 +1581,10 @@ var MorphoClient = class {
1530
1581
  }
1531
1582
  }
1532
1583
  }`;
1533
- const resp = await import_axios2.default.post(MORPHO_API_URL2, { query: posQuery }, { timeout: 15e3 });
1584
+ const resp = await withRetry(
1585
+ () => import_axios2.default.post(MORPHO_API_URL2, { query: posQuery }, { timeout: 15e3 }),
1586
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho position query retry ${n}:`, e.message) }
1587
+ );
1534
1588
  const items = resp.data?.data?.marketPositions?.items ?? [];
1535
1589
  for (const item of items) {
1536
1590
  const supplyShares = BigInt(item.supplyShares ?? "0");
@@ -1749,7 +1803,10 @@ var MorphoClient = class {
1749
1803
  }
1750
1804
  }`;
1751
1805
  try {
1752
- const resp = await import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1806
+ const resp = await withRetry(
1807
+ () => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1808
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1809
+ );
1753
1810
  let items = resp.data?.data?.markets?.items ?? [];
1754
1811
  if (searchTerm && collateralSymbolOrAddress && !collateralSymbolOrAddress.startsWith("0x")) {
1755
1812
  const sym = collateralSymbolOrAddress.toUpperCase();
@@ -1815,7 +1872,10 @@ var MorphoClient = class {
1815
1872
  }
1816
1873
  }`;
1817
1874
  try {
1818
- const resp = await import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1875
+ const resp = await withRetry(
1876
+ () => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1877
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1878
+ );
1819
1879
  let items = resp.data?.data?.markets?.items ?? [];
1820
1880
  items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress);
1821
1881
  const searchUpper = search.toUpperCase();
@@ -3826,7 +3886,7 @@ var AgentIdentityClient = class {
3826
3886
  /**
3827
3887
  * Give positive feedback (shorthand)
3828
3888
  */
3829
- async givePosisitiveFeedback(agentId, value = 100, tags = {}) {
3889
+ async givePositiveFeedback(agentId, value = 100, tags = {}) {
3830
3890
  return this.giveFeedback({
3831
3891
  agentId,
3832
3892
  value: Math.abs(value),
@@ -4032,5 +4092,6 @@ function rateToBps(rate) {
4032
4092
  getMorphoBlueAddress,
4033
4093
  getUSDCAddress,
4034
4094
  parseUnits,
4035
- rateToBps
4095
+ rateToBps,
4096
+ withRetry
4036
4097
  });
package/dist/index.mjs CHANGED
@@ -1125,6 +1125,53 @@ var AgetherClient = class _AgetherClient {
1125
1125
  // src/clients/MorphoClient.ts
1126
1126
  import { ethers as ethers2, Contract as Contract2 } from "ethers";
1127
1127
  import axios2 from "axios";
1128
+
1129
+ // src/utils/retry.ts
1130
+ var RETRIABLE_PATTERNS = [
1131
+ "ECONNRESET",
1132
+ "ECONNREFUSED",
1133
+ "ENOTFOUND",
1134
+ "ETIMEDOUT",
1135
+ "fetch failed",
1136
+ "network error",
1137
+ "socket hang up",
1138
+ "rate limit",
1139
+ "429",
1140
+ "502",
1141
+ "503",
1142
+ "504",
1143
+ "timeout"
1144
+ ];
1145
+ function isRetriable(error) {
1146
+ const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
1147
+ return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
1148
+ }
1149
+ async function withRetry(fn, options = {}) {
1150
+ const {
1151
+ maxRetries = 3,
1152
+ baseDelay = 1e3,
1153
+ maxDelay = 15e3,
1154
+ onRetry
1155
+ } = options;
1156
+ let lastError;
1157
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1158
+ try {
1159
+ return await fn();
1160
+ } catch (error) {
1161
+ lastError = error instanceof Error ? error : new Error(String(error));
1162
+ if (attempt >= maxRetries || !isRetriable(error)) {
1163
+ throw lastError;
1164
+ }
1165
+ const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
1166
+ const jitter = delay * (0.5 + Math.random() * 0.5);
1167
+ onRetry?.(attempt, lastError);
1168
+ await new Promise((resolve) => setTimeout(resolve, jitter));
1169
+ }
1170
+ }
1171
+ throw lastError;
1172
+ }
1173
+
1174
+ // src/clients/MorphoClient.ts
1128
1175
  var MORPHO_API_URL2 = "https://api.morpho.org/graphql";
1129
1176
  var MODE_SINGLE2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
1130
1177
  var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
@@ -1271,7 +1318,10 @@ var MorphoClient = class {
1271
1318
  }
1272
1319
  }`;
1273
1320
  try {
1274
- const resp = await axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1321
+ const resp = await withRetry(
1322
+ () => axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1323
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1324
+ );
1275
1325
  const items = resp.data?.data?.markets?.items ?? [];
1276
1326
  this._discoveredMarkets = items.map((m) => ({
1277
1327
  uniqueKey: m.uniqueKey,
@@ -1455,7 +1505,10 @@ var MorphoClient = class {
1455
1505
  }
1456
1506
  }
1457
1507
  }`;
1458
- const resp = await axios2.post(MORPHO_API_URL2, { query: posQuery }, { timeout: 15e3 });
1508
+ const resp = await withRetry(
1509
+ () => axios2.post(MORPHO_API_URL2, { query: posQuery }, { timeout: 15e3 }),
1510
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho position query retry ${n}:`, e.message) }
1511
+ );
1459
1512
  const items = resp.data?.data?.marketPositions?.items ?? [];
1460
1513
  for (const item of items) {
1461
1514
  const supplyShares = BigInt(item.supplyShares ?? "0");
@@ -1674,7 +1727,10 @@ var MorphoClient = class {
1674
1727
  }
1675
1728
  }`;
1676
1729
  try {
1677
- const resp = await axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1730
+ const resp = await withRetry(
1731
+ () => axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1732
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1733
+ );
1678
1734
  let items = resp.data?.data?.markets?.items ?? [];
1679
1735
  if (searchTerm && collateralSymbolOrAddress && !collateralSymbolOrAddress.startsWith("0x")) {
1680
1736
  const sym = collateralSymbolOrAddress.toUpperCase();
@@ -1740,7 +1796,10 @@ var MorphoClient = class {
1740
1796
  }
1741
1797
  }`;
1742
1798
  try {
1743
- const resp = await axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 });
1799
+ const resp = await withRetry(
1800
+ () => axios2.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
1801
+ { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1802
+ );
1744
1803
  let items = resp.data?.data?.markets?.items ?? [];
1745
1804
  items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== ethers2.ZeroAddress);
1746
1805
  const searchUpper = search.toUpperCase();
@@ -3751,7 +3810,7 @@ var AgentIdentityClient = class {
3751
3810
  /**
3752
3811
  * Give positive feedback (shorthand)
3753
3812
  */
3754
- async givePosisitiveFeedback(agentId, value = 100, tags = {}) {
3813
+ async givePositiveFeedback(agentId, value = 100, tags = {}) {
3755
3814
  return this.giveFeedback({
3756
3815
  agentId,
3757
3816
  value: Math.abs(value),
@@ -3956,5 +4015,6 @@ export {
3956
4015
  getMorphoBlueAddress,
3957
4016
  getUSDCAddress,
3958
4017
  parseUnits,
3959
- rateToBps
4018
+ rateToBps,
4019
+ withRetry
3960
4020
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/sdk",
3
- "version": "2.15.1",
3
+ "version": "2.16.0",
4
4
  "description": "TypeScript SDK for Agether - autonomous credit for AI agents on Ethereum & Base",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/dist/cli.d.ts DELETED
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Agether CLI — Direct Morpho Blue Credit for AI Agents
4
- *
5
- * Architecture (v2 — Safe + Safe7579):
6
- * - All commands sign transactions directly with the agent's private key
7
- * - Uses MorphoClient for lending (ERC-4337 UserOps through Safe account)
8
- * - Uses X402Client for paid API calls
9
- *
10
- * Supported chains: Ethereum (1, default), Base (8453), Base Sepolia (84532)
11
- *
12
- * Usage:
13
- * agether init <private-key> [--agent-id <id>] [--chain <chainId>]
14
- * agether register [--name <n>] Register ERC-8004 + Safe account
15
- * agether balance Check balances
16
- * agether status Show Morpho positions
17
- * agether score Get credit score (x402-gated)
18
- * agether markets List Morpho markets
19
- * agether deposit --amount 0.05 --token WETH Deposit collateral
20
- * agether borrow --amount 100 Borrow USDC
21
- * agether deposit-and-borrow --amount 0.05 --token WETH --borrow 100
22
- * agether repay --amount 50 Repay USDC
23
- * agether withdraw --amount 0.05 --token WETH Withdraw collateral
24
- * agether sponsor --amount 0.05 --token WETH --agent-id 123
25
- * agether fund --amount 50 Fund Safe account with USDC
26
- * agether x402 <url> [--method GET|POST] [--body <json>]
27
- */
28
- export {};
29
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
@@ -1,200 +0,0 @@
1
- /**
2
- * AgentIdentityClient - Integration with ag0 (ERC-8004)
3
- *
4
- * ERC-8004 is a per-chain singleton — different chain = different agentId.
5
- *
6
- * Contract Addresses:
7
- * - Ethereum IdentityRegistry: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
8
- * - Base IdentityRegistry: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
9
- * - Sepolia IdentityRegistry: 0x8004A818BFB912233c491871b3d84c89A494BD9e
10
- * - Sepolia ReputationRegistry: 0x8004B663056A597Dffe9eCcC1965A193B7388713
11
- *
12
- * SDKs:
13
- * - TypeScript: https://github.com/agent0lab/agent0-ts
14
- * - Python: https://github.com/agent0lab/agent0-py
15
- *
16
- * Docs: https://sdk.ag0.xyz/docs
17
- */
18
- import { Signer } from 'ethers';
19
- import { AgetherConfig } from '../types';
20
- export declare const ERC8004_SEPOLIA: {
21
- identityRegistry: string;
22
- reputationRegistry: string;
23
- };
24
- export declare const ERC8004_MAINNET: {
25
- identityRegistry: string;
26
- reputationRegistry: string;
27
- };
28
- export declare const ERC8004_BASE: {
29
- identityRegistry: string;
30
- reputationRegistry: string;
31
- };
32
- export interface AgentIdentityClientOptions {
33
- config: AgetherConfig;
34
- signer: Signer;
35
- /** Optional: Use ag0 TypeScript SDK instead of direct contracts */
36
- useAg0SDK?: boolean;
37
- }
38
- export interface AgentMetadata {
39
- name: string;
40
- description: string;
41
- image?: string;
42
- endpoints?: {
43
- name: string;
44
- endpoint: string;
45
- version?: string;
46
- }[];
47
- x402Support?: boolean;
48
- active?: boolean;
49
- }
50
- export interface FeedbackInput {
51
- agentId: bigint;
52
- value: number;
53
- decimals?: number;
54
- tag1?: string;
55
- tag2?: string;
56
- endpoint?: string;
57
- feedbackURI?: string;
58
- }
59
- export interface ReputationSummary {
60
- count: number;
61
- totalValue: number;
62
- averageValue: number;
63
- clients: string[];
64
- }
65
- export declare class AgentIdentityClient {
66
- readonly config: AgetherConfig;
67
- private signer;
68
- private identityRegistry;
69
- private reputationRegistry;
70
- constructor(options: AgentIdentityClientOptions);
71
- /**
72
- * Register a new agent (minimal - no metadata)
73
- */
74
- register(): Promise<{
75
- agentId: bigint;
76
- txHash: string;
77
- }>;
78
- /**
79
- * Register agent with IPFS/HTTP URI to metadata JSON
80
- * @param agentURI URI pointing to agent metadata (ipfs:// or https://)
81
- */
82
- registerWithURI(agentURI: string): Promise<{
83
- agentId: bigint;
84
- txHash: string;
85
- }>;
86
- /**
87
- * Check if the signer already owns an ERC-8004 identity token.
88
- * Returns true if balanceOf > 0, false otherwise.
89
- * Note: Cannot determine the specific agentId without enumeration —
90
- * use agether init <pk> --agent-id <id> if you know your agentId.
91
- */
92
- hasExistingIdentity(): Promise<boolean>;
93
- /**
94
- * Register only if no identity exists; otherwise throw.
95
- * Prevents accidental double-registration.
96
- */
97
- registerOrGet(): Promise<{
98
- agentId: bigint;
99
- txHash: string | null;
100
- existing: boolean;
101
- }>;
102
- /**
103
- * Register with URI only if no identity exists; otherwise throw.
104
- * Prevents accidental double-registration.
105
- */
106
- registerOrGetWithURI(agentURI: string): Promise<{
107
- agentId: bigint;
108
- txHash: string | null;
109
- existing: boolean;
110
- }>;
111
- /**
112
- * Register agent with URI and onchain metadata
113
- */
114
- registerWithMetadata(agentURI: string, metadata: {
115
- key: string;
116
- value: string;
117
- }[]): Promise<{
118
- agentId: bigint;
119
- txHash: string;
120
- }>;
121
- /**
122
- * Get agent owner address
123
- */
124
- getOwner(agentId: bigint): Promise<string>;
125
- /**
126
- * Get agent URI (metadata JSON location)
127
- */
128
- getAgentURI(agentId: bigint): Promise<string>;
129
- /**
130
- * Update agent URI
131
- */
132
- setAgentURI(agentId: bigint, newURI: string): Promise<string>;
133
- /**
134
- * Set onchain metadata (key-value)
135
- */
136
- setMetadata(agentId: bigint, key: string, value: string): Promise<string>;
137
- /**
138
- * Get onchain metadata
139
- */
140
- getMetadata(agentId: bigint, key: string): Promise<string>;
141
- /**
142
- * Transfer agent to new owner
143
- */
144
- transfer(agentId: bigint, to: string): Promise<string>;
145
- /**
146
- * Fetch and parse agent metadata from URI
147
- */
148
- fetchAgentMetadata(agentId: bigint): Promise<AgentMetadata | null>;
149
- /**
150
- * Give feedback to an agent
151
- */
152
- giveFeedback(input: FeedbackInput): Promise<string>;
153
- /**
154
- * Give positive feedback (shorthand)
155
- */
156
- givePosisitiveFeedback(agentId: bigint, value?: number, tags?: {
157
- tag1?: string;
158
- tag2?: string;
159
- }): Promise<string>;
160
- /**
161
- * Give negative feedback (e.g., for defaults)
162
- */
163
- giveNegativeFeedback(agentId: bigint, value?: number, tags?: {
164
- tag1?: string;
165
- tag2?: string;
166
- }): Promise<string>;
167
- /**
168
- * Record credit default in reputation system
169
- */
170
- recordCreditDefault(agentId: bigint, creditLineId: bigint): Promise<string>;
171
- /**
172
- * Get reputation summary for an agent
173
- */
174
- getReputation(agentId: bigint, tag1?: string, tag2?: string): Promise<ReputationSummary>;
175
- /**
176
- * Check if agent has negative credit reputation
177
- */
178
- hasNegativeCreditReputation(agentId: bigint): Promise<boolean>;
179
- /**
180
- * Verify agent is eligible for Agether credit
181
- * Checks:
182
- * 1. Agent exists in ERC-8004 registry
183
- * 2. Agent has no negative credit reputation
184
- */
185
- verifyForCredit(agentId: bigint): Promise<{
186
- eligible: boolean;
187
- reason?: string;
188
- owner?: string;
189
- reputation?: ReputationSummary;
190
- }>;
191
- private parseAgentIdFromReceipt;
192
- /**
193
- * Get contract addresses
194
- */
195
- getContractAddresses(): {
196
- identity: string;
197
- reputation: string;
198
- };
199
- }
200
- //# sourceMappingURL=AgentIdentityClient.d.ts.map