@agether/sdk 2.15.1 → 2.16.1
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 +134 -8
- package/dist/index.d.mts +35 -5
- package/dist/index.d.ts +35 -5
- package/dist/index.js +134 -11
- package/dist/index.mjs +132 -10
- package/package.json +1 -1
- package/dist/cli.d.ts +0 -29
- package/dist/cli.d.ts.map +0 -1
- package/dist/clients/AgentIdentityClient.d.ts +0 -200
- package/dist/clients/AgentIdentityClient.d.ts.map +0 -1
- package/dist/clients/AgentIdentityClient.js +0 -351
- package/dist/clients/AgetherClient.d.ts +0 -242
- package/dist/clients/AgetherClient.d.ts.map +0 -1
- package/dist/clients/AgetherClient.js +0 -736
- package/dist/clients/MorphoClient.d.ts +0 -572
- package/dist/clients/MorphoClient.d.ts.map +0 -1
- package/dist/clients/MorphoClient.js +0 -1974
- package/dist/clients/ScoringClient.d.ts +0 -103
- package/dist/clients/ScoringClient.d.ts.map +0 -1
- package/dist/clients/ScoringClient.js +0 -112
- package/dist/clients/X402Client.d.ts +0 -198
- package/dist/clients/X402Client.d.ts.map +0 -1
- package/dist/clients/X402Client.js +0 -438
- package/dist/index.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -132
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -46
- package/dist/utils/abis.d.ts +0 -29
- package/dist/utils/abis.d.ts.map +0 -1
- package/dist/utils/abis.js +0 -138
- package/dist/utils/config.d.ts +0 -36
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -168
- package/dist/utils/format.d.ts +0 -44
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js +0 -75
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
|
|
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
|
|
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
|
|
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
|
|
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();
|
|
@@ -2493,13 +2557,64 @@ var init_AgetherClient = __esm({
|
|
|
2493
2557
|
return this.agether4337Factory.accountExists(id);
|
|
2494
2558
|
}
|
|
2495
2559
|
// ════════════════════════════════════════════════════════
|
|
2560
|
+
// Token Discovery (for dynamic balance queries)
|
|
2561
|
+
// ════════════════════════════════════════════════════════
|
|
2562
|
+
/**
|
|
2563
|
+
* Discover token addresses from active Morpho Blue positions.
|
|
2564
|
+
* Queries the Morpho GraphQL API for markets involving this agent's account,
|
|
2565
|
+
* then extracts collateral and loan token info.
|
|
2566
|
+
*/
|
|
2567
|
+
async _discoverPositionTokens() {
|
|
2568
|
+
const tokens = {};
|
|
2569
|
+
try {
|
|
2570
|
+
const acctAddr = await this.getAccountAddress();
|
|
2571
|
+
const chainId = this.config.chainId;
|
|
2572
|
+
const query = `{
|
|
2573
|
+
marketPositions(
|
|
2574
|
+
where: { userAddress_in: ["${acctAddr.toLowerCase()}"], chainId_in: [${chainId}] }
|
|
2575
|
+
first: 20
|
|
2576
|
+
) {
|
|
2577
|
+
items {
|
|
2578
|
+
market {
|
|
2579
|
+
collateralAsset { address symbol decimals }
|
|
2580
|
+
loanAsset { address symbol decimals }
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
}`;
|
|
2585
|
+
const resp = await fetch("https://blue-api.morpho.org/graphql", {
|
|
2586
|
+
method: "POST",
|
|
2587
|
+
headers: { "Content-Type": "application/json" },
|
|
2588
|
+
body: JSON.stringify({ query }),
|
|
2589
|
+
signal: AbortSignal.timeout(5e3)
|
|
2590
|
+
});
|
|
2591
|
+
if (!resp.ok) return tokens;
|
|
2592
|
+
const data = await resp.json();
|
|
2593
|
+
const items = data?.data?.marketPositions?.items ?? [];
|
|
2594
|
+
for (const item of items) {
|
|
2595
|
+
const col = item?.market?.collateralAsset;
|
|
2596
|
+
const loan = item?.market?.loanAsset;
|
|
2597
|
+
if (col?.symbol && col?.address) {
|
|
2598
|
+
tokens[col.symbol] = { address: col.address, symbol: col.symbol, decimals: col.decimals ?? 18 };
|
|
2599
|
+
}
|
|
2600
|
+
if (loan?.symbol && loan?.address) {
|
|
2601
|
+
tokens[loan.symbol] = { address: loan.address, symbol: loan.symbol, decimals: loan.decimals ?? 18 };
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
} catch {
|
|
2605
|
+
}
|
|
2606
|
+
return tokens;
|
|
2607
|
+
}
|
|
2608
|
+
// ════════════════════════════════════════════════════════
|
|
2496
2609
|
// Balances
|
|
2497
2610
|
// ════════════════════════════════════════════════════════
|
|
2498
2611
|
/**
|
|
2499
|
-
* Get ETH, USDC, and
|
|
2612
|
+
* Get ETH, USDC, and all token balances for EOA and Safe account.
|
|
2500
2613
|
*
|
|
2501
|
-
*
|
|
2502
|
-
*
|
|
2614
|
+
* Tokens are resolved from:
|
|
2615
|
+
* 1. Built-in registry of well-known tokens (WETH, wstETH, cbETH)
|
|
2616
|
+
* 2. Dynamic discovery from active Morpho positions (loan + collateral tokens)
|
|
2617
|
+
* This ensures tokens like LCAP or any new Morpho market tokens appear in balances.
|
|
2503
2618
|
*/
|
|
2504
2619
|
async getBalances() {
|
|
2505
2620
|
const provider = this.signer.provider;
|
|
@@ -2507,7 +2622,18 @@ var init_AgetherClient = __esm({
|
|
|
2507
2622
|
const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
2508
2623
|
const ethBal = await provider.getBalance(eoaAddr);
|
|
2509
2624
|
const usdcBal = await usdc.balanceOf(eoaAddr);
|
|
2510
|
-
const knownTokens =
|
|
2625
|
+
const knownTokens = {
|
|
2626
|
+
...KNOWN_TOKENS[this.config.chainId] ?? {}
|
|
2627
|
+
};
|
|
2628
|
+
try {
|
|
2629
|
+
const positions = await this._discoverPositionTokens();
|
|
2630
|
+
for (const [symbol, info] of Object.entries(positions)) {
|
|
2631
|
+
if (!knownTokens[symbol]) {
|
|
2632
|
+
knownTokens[symbol] = info;
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
} catch {
|
|
2636
|
+
}
|
|
2511
2637
|
const eoaCollateral = {};
|
|
2512
2638
|
for (const [symbol, info] of Object.entries(knownTokens)) {
|
|
2513
2639
|
try {
|
package/dist/index.d.mts
CHANGED
|
@@ -244,10 +244,18 @@ declare class AgetherClient {
|
|
|
244
244
|
/** Check whether the Safe account has been deployed. */
|
|
245
245
|
accountExists(): Promise<boolean>;
|
|
246
246
|
/**
|
|
247
|
-
*
|
|
247
|
+
* Discover token addresses from active Morpho Blue positions.
|
|
248
|
+
* Queries the Morpho GraphQL API for markets involving this agent's account,
|
|
249
|
+
* then extracts collateral and loan token info.
|
|
250
|
+
*/
|
|
251
|
+
private _discoverPositionTokens;
|
|
252
|
+
/**
|
|
253
|
+
* Get ETH, USDC, and all token balances for EOA and Safe account.
|
|
248
254
|
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
255
|
+
* Tokens are resolved from:
|
|
256
|
+
* 1. Built-in registry of well-known tokens (WETH, wstETH, cbETH)
|
|
257
|
+
* 2. Dynamic discovery from active Morpho positions (loan + collateral tokens)
|
|
258
|
+
* This ensures tokens like LCAP or any new Morpho market tokens appear in balances.
|
|
251
259
|
*/
|
|
252
260
|
getBalances(): Promise<BalancesResult>;
|
|
253
261
|
/**
|
|
@@ -1413,7 +1421,7 @@ declare class AgentIdentityClient {
|
|
|
1413
1421
|
/**
|
|
1414
1422
|
* Give positive feedback (shorthand)
|
|
1415
1423
|
*/
|
|
1416
|
-
|
|
1424
|
+
givePositiveFeedback(agentId: bigint, value?: number, tags?: {
|
|
1417
1425
|
tag1?: string;
|
|
1418
1426
|
tag2?: string;
|
|
1419
1427
|
}): Promise<string>;
|
|
@@ -1567,4 +1575,26 @@ declare function getMorphoBlueAddress(chainId: ChainId): string;
|
|
|
1567
1575
|
*/
|
|
1568
1576
|
declare function getContractAddresses(chainId: ChainId): ContractAddresses;
|
|
1569
1577
|
|
|
1570
|
-
|
|
1578
|
+
/**
|
|
1579
|
+
* Retry utility with exponential backoff for network operations.
|
|
1580
|
+
*
|
|
1581
|
+
* Phase 2: Added to handle transient RPC failures, rate limits,
|
|
1582
|
+
* and network timeouts gracefully instead of failing immediately.
|
|
1583
|
+
*/
|
|
1584
|
+
interface RetryOptions {
|
|
1585
|
+
/** Maximum number of attempts (default: 3) */
|
|
1586
|
+
maxRetries?: number;
|
|
1587
|
+
/** Base delay in ms (default: 1000) */
|
|
1588
|
+
baseDelay?: number;
|
|
1589
|
+
/** Maximum delay in ms (default: 15000) */
|
|
1590
|
+
maxDelay?: number;
|
|
1591
|
+
/** Called before each retry with attempt number and error */
|
|
1592
|
+
onRetry?: (attempt: number, error: Error) => void;
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Execute an async function with retry and exponential backoff.
|
|
1596
|
+
* Only retries on transient network errors, not business logic errors.
|
|
1597
|
+
*/
|
|
1598
|
+
declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
1599
|
+
|
|
1600
|
+
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
|
@@ -244,10 +244,18 @@ declare class AgetherClient {
|
|
|
244
244
|
/** Check whether the Safe account has been deployed. */
|
|
245
245
|
accountExists(): Promise<boolean>;
|
|
246
246
|
/**
|
|
247
|
-
*
|
|
247
|
+
* Discover token addresses from active Morpho Blue positions.
|
|
248
|
+
* Queries the Morpho GraphQL API for markets involving this agent's account,
|
|
249
|
+
* then extracts collateral and loan token info.
|
|
250
|
+
*/
|
|
251
|
+
private _discoverPositionTokens;
|
|
252
|
+
/**
|
|
253
|
+
* Get ETH, USDC, and all token balances for EOA and Safe account.
|
|
248
254
|
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
255
|
+
* Tokens are resolved from:
|
|
256
|
+
* 1. Built-in registry of well-known tokens (WETH, wstETH, cbETH)
|
|
257
|
+
* 2. Dynamic discovery from active Morpho positions (loan + collateral tokens)
|
|
258
|
+
* This ensures tokens like LCAP or any new Morpho market tokens appear in balances.
|
|
251
259
|
*/
|
|
252
260
|
getBalances(): Promise<BalancesResult>;
|
|
253
261
|
/**
|
|
@@ -1413,7 +1421,7 @@ declare class AgentIdentityClient {
|
|
|
1413
1421
|
/**
|
|
1414
1422
|
* Give positive feedback (shorthand)
|
|
1415
1423
|
*/
|
|
1416
|
-
|
|
1424
|
+
givePositiveFeedback(agentId: bigint, value?: number, tags?: {
|
|
1417
1425
|
tag1?: string;
|
|
1418
1426
|
tag2?: string;
|
|
1419
1427
|
}): Promise<string>;
|
|
@@ -1567,4 +1575,26 @@ declare function getMorphoBlueAddress(chainId: ChainId): string;
|
|
|
1567
1575
|
*/
|
|
1568
1576
|
declare function getContractAddresses(chainId: ChainId): ContractAddresses;
|
|
1569
1577
|
|
|
1570
|
-
|
|
1578
|
+
/**
|
|
1579
|
+
* Retry utility with exponential backoff for network operations.
|
|
1580
|
+
*
|
|
1581
|
+
* Phase 2: Added to handle transient RPC failures, rate limits,
|
|
1582
|
+
* and network timeouts gracefully instead of failing immediately.
|
|
1583
|
+
*/
|
|
1584
|
+
interface RetryOptions {
|
|
1585
|
+
/** Maximum number of attempts (default: 3) */
|
|
1586
|
+
maxRetries?: number;
|
|
1587
|
+
/** Base delay in ms (default: 1000) */
|
|
1588
|
+
baseDelay?: number;
|
|
1589
|
+
/** Maximum delay in ms (default: 15000) */
|
|
1590
|
+
maxDelay?: number;
|
|
1591
|
+
/** Called before each retry with attempt number and error */
|
|
1592
|
+
onRetry?: (attempt: number, error: Error) => void;
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Execute an async function with retry and exponential backoff.
|
|
1596
|
+
* Only retries on transient network errors, not business logic errors.
|
|
1597
|
+
*/
|
|
1598
|
+
declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
1599
|
+
|
|
1600
|
+
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
|
|
|
@@ -618,13 +619,64 @@ var AgetherClient = class _AgetherClient {
|
|
|
618
619
|
return this.agether4337Factory.accountExists(id);
|
|
619
620
|
}
|
|
620
621
|
// ════════════════════════════════════════════════════════
|
|
622
|
+
// Token Discovery (for dynamic balance queries)
|
|
623
|
+
// ════════════════════════════════════════════════════════
|
|
624
|
+
/**
|
|
625
|
+
* Discover token addresses from active Morpho Blue positions.
|
|
626
|
+
* Queries the Morpho GraphQL API for markets involving this agent's account,
|
|
627
|
+
* then extracts collateral and loan token info.
|
|
628
|
+
*/
|
|
629
|
+
async _discoverPositionTokens() {
|
|
630
|
+
const tokens = {};
|
|
631
|
+
try {
|
|
632
|
+
const acctAddr = await this.getAccountAddress();
|
|
633
|
+
const chainId = this.config.chainId;
|
|
634
|
+
const query = `{
|
|
635
|
+
marketPositions(
|
|
636
|
+
where: { userAddress_in: ["${acctAddr.toLowerCase()}"], chainId_in: [${chainId}] }
|
|
637
|
+
first: 20
|
|
638
|
+
) {
|
|
639
|
+
items {
|
|
640
|
+
market {
|
|
641
|
+
collateralAsset { address symbol decimals }
|
|
642
|
+
loanAsset { address symbol decimals }
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}`;
|
|
647
|
+
const resp = await fetch("https://blue-api.morpho.org/graphql", {
|
|
648
|
+
method: "POST",
|
|
649
|
+
headers: { "Content-Type": "application/json" },
|
|
650
|
+
body: JSON.stringify({ query }),
|
|
651
|
+
signal: AbortSignal.timeout(5e3)
|
|
652
|
+
});
|
|
653
|
+
if (!resp.ok) return tokens;
|
|
654
|
+
const data = await resp.json();
|
|
655
|
+
const items = data?.data?.marketPositions?.items ?? [];
|
|
656
|
+
for (const item of items) {
|
|
657
|
+
const col = item?.market?.collateralAsset;
|
|
658
|
+
const loan = item?.market?.loanAsset;
|
|
659
|
+
if (col?.symbol && col?.address) {
|
|
660
|
+
tokens[col.symbol] = { address: col.address, symbol: col.symbol, decimals: col.decimals ?? 18 };
|
|
661
|
+
}
|
|
662
|
+
if (loan?.symbol && loan?.address) {
|
|
663
|
+
tokens[loan.symbol] = { address: loan.address, symbol: loan.symbol, decimals: loan.decimals ?? 18 };
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
} catch {
|
|
667
|
+
}
|
|
668
|
+
return tokens;
|
|
669
|
+
}
|
|
670
|
+
// ════════════════════════════════════════════════════════
|
|
621
671
|
// Balances
|
|
622
672
|
// ════════════════════════════════════════════════════════
|
|
623
673
|
/**
|
|
624
|
-
* Get ETH, USDC, and
|
|
674
|
+
* Get ETH, USDC, and all token balances for EOA and Safe account.
|
|
625
675
|
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
676
|
+
* Tokens are resolved from:
|
|
677
|
+
* 1. Built-in registry of well-known tokens (WETH, wstETH, cbETH)
|
|
678
|
+
* 2. Dynamic discovery from active Morpho positions (loan + collateral tokens)
|
|
679
|
+
* This ensures tokens like LCAP or any new Morpho market tokens appear in balances.
|
|
628
680
|
*/
|
|
629
681
|
async getBalances() {
|
|
630
682
|
const provider = this.signer.provider;
|
|
@@ -632,7 +684,18 @@ var AgetherClient = class _AgetherClient {
|
|
|
632
684
|
const usdc = new import_ethers.Contract(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
633
685
|
const ethBal = await provider.getBalance(eoaAddr);
|
|
634
686
|
const usdcBal = await usdc.balanceOf(eoaAddr);
|
|
635
|
-
const knownTokens =
|
|
687
|
+
const knownTokens = {
|
|
688
|
+
...KNOWN_TOKENS[this.config.chainId] ?? {}
|
|
689
|
+
};
|
|
690
|
+
try {
|
|
691
|
+
const positions = await this._discoverPositionTokens();
|
|
692
|
+
for (const [symbol, info] of Object.entries(positions)) {
|
|
693
|
+
if (!knownTokens[symbol]) {
|
|
694
|
+
knownTokens[symbol] = info;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
} catch {
|
|
698
|
+
}
|
|
636
699
|
const eoaCollateral = {};
|
|
637
700
|
for (const [symbol, info] of Object.entries(knownTokens)) {
|
|
638
701
|
try {
|
|
@@ -1200,6 +1263,53 @@ var AgetherClient = class _AgetherClient {
|
|
|
1200
1263
|
// src/clients/MorphoClient.ts
|
|
1201
1264
|
var import_ethers2 = require("ethers");
|
|
1202
1265
|
var import_axios2 = __toESM(require("axios"));
|
|
1266
|
+
|
|
1267
|
+
// src/utils/retry.ts
|
|
1268
|
+
var RETRIABLE_PATTERNS = [
|
|
1269
|
+
"ECONNRESET",
|
|
1270
|
+
"ECONNREFUSED",
|
|
1271
|
+
"ENOTFOUND",
|
|
1272
|
+
"ETIMEDOUT",
|
|
1273
|
+
"fetch failed",
|
|
1274
|
+
"network error",
|
|
1275
|
+
"socket hang up",
|
|
1276
|
+
"rate limit",
|
|
1277
|
+
"429",
|
|
1278
|
+
"502",
|
|
1279
|
+
"503",
|
|
1280
|
+
"504",
|
|
1281
|
+
"timeout"
|
|
1282
|
+
];
|
|
1283
|
+
function isRetriable(error) {
|
|
1284
|
+
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
1285
|
+
return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
|
|
1286
|
+
}
|
|
1287
|
+
async function withRetry(fn, options = {}) {
|
|
1288
|
+
const {
|
|
1289
|
+
maxRetries = 3,
|
|
1290
|
+
baseDelay = 1e3,
|
|
1291
|
+
maxDelay = 15e3,
|
|
1292
|
+
onRetry
|
|
1293
|
+
} = options;
|
|
1294
|
+
let lastError;
|
|
1295
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
1296
|
+
try {
|
|
1297
|
+
return await fn();
|
|
1298
|
+
} catch (error) {
|
|
1299
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
1300
|
+
if (attempt >= maxRetries || !isRetriable(error)) {
|
|
1301
|
+
throw lastError;
|
|
1302
|
+
}
|
|
1303
|
+
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
1304
|
+
const jitter = delay * (0.5 + Math.random() * 0.5);
|
|
1305
|
+
onRetry?.(attempt, lastError);
|
|
1306
|
+
await new Promise((resolve) => setTimeout(resolve, jitter));
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
throw lastError;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// src/clients/MorphoClient.ts
|
|
1203
1313
|
var MORPHO_API_URL2 = "https://api.morpho.org/graphql";
|
|
1204
1314
|
var MODE_SINGLE2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
1205
1315
|
var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
|
|
@@ -1346,7 +1456,10 @@ var MorphoClient = class {
|
|
|
1346
1456
|
}
|
|
1347
1457
|
}`;
|
|
1348
1458
|
try {
|
|
1349
|
-
const resp = await
|
|
1459
|
+
const resp = await withRetry(
|
|
1460
|
+
() => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
|
|
1461
|
+
{ maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
|
|
1462
|
+
);
|
|
1350
1463
|
const items = resp.data?.data?.markets?.items ?? [];
|
|
1351
1464
|
this._discoveredMarkets = items.map((m) => ({
|
|
1352
1465
|
uniqueKey: m.uniqueKey,
|
|
@@ -1530,7 +1643,10 @@ var MorphoClient = class {
|
|
|
1530
1643
|
}
|
|
1531
1644
|
}
|
|
1532
1645
|
}`;
|
|
1533
|
-
const resp = await
|
|
1646
|
+
const resp = await withRetry(
|
|
1647
|
+
() => import_axios2.default.post(MORPHO_API_URL2, { query: posQuery }, { timeout: 15e3 }),
|
|
1648
|
+
{ maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho position query retry ${n}:`, e.message) }
|
|
1649
|
+
);
|
|
1534
1650
|
const items = resp.data?.data?.marketPositions?.items ?? [];
|
|
1535
1651
|
for (const item of items) {
|
|
1536
1652
|
const supplyShares = BigInt(item.supplyShares ?? "0");
|
|
@@ -1749,7 +1865,10 @@ var MorphoClient = class {
|
|
|
1749
1865
|
}
|
|
1750
1866
|
}`;
|
|
1751
1867
|
try {
|
|
1752
|
-
const resp = await
|
|
1868
|
+
const resp = await withRetry(
|
|
1869
|
+
() => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
|
|
1870
|
+
{ maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
|
|
1871
|
+
);
|
|
1753
1872
|
let items = resp.data?.data?.markets?.items ?? [];
|
|
1754
1873
|
if (searchTerm && collateralSymbolOrAddress && !collateralSymbolOrAddress.startsWith("0x")) {
|
|
1755
1874
|
const sym = collateralSymbolOrAddress.toUpperCase();
|
|
@@ -1815,7 +1934,10 @@ var MorphoClient = class {
|
|
|
1815
1934
|
}
|
|
1816
1935
|
}`;
|
|
1817
1936
|
try {
|
|
1818
|
-
const resp = await
|
|
1937
|
+
const resp = await withRetry(
|
|
1938
|
+
() => import_axios2.default.post(MORPHO_API_URL2, { query }, { timeout: 1e4 }),
|
|
1939
|
+
{ maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
|
|
1940
|
+
);
|
|
1819
1941
|
let items = resp.data?.data?.markets?.items ?? [];
|
|
1820
1942
|
items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress);
|
|
1821
1943
|
const searchUpper = search.toUpperCase();
|
|
@@ -3826,7 +3948,7 @@ var AgentIdentityClient = class {
|
|
|
3826
3948
|
/**
|
|
3827
3949
|
* Give positive feedback (shorthand)
|
|
3828
3950
|
*/
|
|
3829
|
-
async
|
|
3951
|
+
async givePositiveFeedback(agentId, value = 100, tags = {}) {
|
|
3830
3952
|
return this.giveFeedback({
|
|
3831
3953
|
agentId,
|
|
3832
3954
|
value: Math.abs(value),
|
|
@@ -4032,5 +4154,6 @@ function rateToBps(rate) {
|
|
|
4032
4154
|
getMorphoBlueAddress,
|
|
4033
4155
|
getUSDCAddress,
|
|
4034
4156
|
parseUnits,
|
|
4035
|
-
rateToBps
|
|
4157
|
+
rateToBps,
|
|
4158
|
+
withRetry
|
|
4036
4159
|
});
|