Skip to content

Commit bebafcf

Browse files
committed
release: 1.8.8
1 parent ae64133 commit bebafcf

19 files changed

Lines changed: 1843 additions & 140 deletions

README.md

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Evalanche
22

3-
**Multi-EVM agent wallet SDK with onchain identity (ERC-8004), full agent identity resolution, payment rails (x402), cross-chain liquidity (Li.Fi bridging + DEX aggregation + DeFi Composer), gas funding (Gas.zip), market intelligence (CoinGecko), prediction markets (Polymarket CLOB), agent economy primitives, DeFi operations, and perpetual futures (dYdX v4)**
3+
**Multi-EVM agent wallet SDK with onchain identity (ERC-8004), unified wallet holdings discovery, full agent identity resolution, payment rails (x402), cross-chain liquidity (Li.Fi bridging + DEX aggregation + DeFi Composer), gas funding (Gas.zip), market intelligence (CoinGecko), prediction markets (Polymarket CLOB), agent economy primitives, DeFi operations, and perpetual futures (dYdX v4 + Hyperliquid)**
44

5-
Evalanche gives AI agents a **non-custodial** wallet on **any EVM chain** — Ethereum, Base, Arbitrum, Optimism, Polygon, BSC, Avalanche, and 15+ more — with built-in onchain identity, ERC-8004 full registration resolution, payment capabilities, cross-chain bridging, same-chain DEX swaps (31+ aggregators), CoinGecko market data, Polymarket market discovery and execution, agent economy primitives (discovery, negotiation, settlement, escrow, memory), DeFi operations, and perpetual futures on dYdX. No browser, no popups, no human in the loop.
5+
Evalanche gives AI agents a **non-custodial** wallet on **any EVM chain** — Ethereum, Base, Arbitrum, Optimism, Polygon, BSC, Avalanche, and 15+ more — with built-in onchain identity, ERC-8004 full registration resolution, payment capabilities, unified holdings scanning, cross-chain bridging, same-chain DEX swaps (31+ aggregators), CoinGecko market data, Polymarket market discovery and execution, agent economy primitives (discovery, negotiation, settlement, escrow, memory), DeFi operations, and perpetual futures on dYdX + Hyperliquid. No browser, no popups, no human in the loop.
66

77
## Install
88

@@ -383,6 +383,45 @@ await baseVaults.deposit(YOUSD, '1000'); // approve + deposit in one call
383383
await baseVaults.withdraw(YOUSD, '998.1'); // redeem shares
384384
```
385385

386+
### Unified Holdings (universal registry + scanner)
387+
388+
Evalanche now ships a universal in-repo holdings registry and a one-pass holdings scanner. The scanner combines:
389+
390+
- native balances across supported chains
391+
- seeded ERC-20 balances
392+
- DeFi positions such as ERC-4626 vaults and liquid staking receipts
393+
- Polymarket positions
394+
- perp venue positions on Hyperliquid and dYdX
395+
396+
```typescript
397+
const agent = new Evalanche({ privateKey: '0x...', network: 'base' });
398+
399+
const portfolio = await agent.holdings().scan();
400+
401+
console.log(portfolio.summary);
402+
// → { totalHoldings, byType, byChain, byProtocol }
403+
404+
const filtered = await agent.holdings().scan({
405+
chains: ['polygon', 'base', 'avalanche', 'hyperliquid'],
406+
include: ['native', 'token', 'defi', 'prediction', 'perp'],
407+
protocols: ['polymarket', 'avantis', 'yousd'],
408+
});
409+
410+
console.log(filtered.holdings[0]);
411+
// → {
412+
// holdingType: 'vault' | 'token' | 'prediction' | 'perp' | ...,
413+
// protocolId: 'yousd-vault',
414+
// protocolName: 'yoUSD Vault',
415+
// chain: 'base',
416+
// symbol: 'yoUSD',
417+
// displayBalance: '24.917987',
418+
// underlyingValue: '26.771162',
419+
// ...
420+
// }
421+
```
422+
423+
The universal registry is checked into the repo and shared by every agent. It is seeded with local canonical records, a vendored AvaPilot Avalanche snapshot, and DefiLlama import tooling. Runtime holdings truth still comes from live onchain reads and venue APIs.
424+
386425
### Prediction Markets: Polymarket (v1.5.0+)
387426

388427
Polymarket support is exposed in two ways:
@@ -644,6 +683,9 @@ AGENT_PRIVATE_KEY=0x... evalanche-mcp --http --port 3402
644683
|------|-------------|
645684
| `get_address` | Get agent wallet address |
646685
| `get_balance` | Get native token balance |
686+
| `get_holdings` | Unified wallet holdings scan across tokens, DeFi, predictions, and perps |
687+
| `search_registry` | Search the universal in-repo holdings registry |
688+
| `registry_status` | Get universal registry counts and detector coverage |
647689
| `send_avax` | Send native tokens |
648690
| `call_contract` | Call a contract method |
649691
| `sign_message` | Sign a message |
@@ -893,7 +935,13 @@ For live operator validation, use the runbook in [docs/live-smoke-checklist.md](
893935
- market search, market details, order book access, balance and position discovery
894936
- expanded Evalanche into prediction market workflows alongside DeFi + perps
895937

896-
### v1.8.6 (current)
938+
### v1.8.8 (current)
939+
- **Universal holdings + live verification**
940+
- unified holdings scanning now combines native balances, seeded ERC-20s, DeFi positions, Polymarket positions, and perp venue positions behind `agent.holdings().scan()` and the MCP `get_holdings` tool
941+
- the in-repo universal registry now seeds both DeFi routing and holdings discovery, with local canonical records taking precedence over AvaPilot and DefiLlama-enriched metadata
942+
- npm-facing documentation now reflects the current package surface instead of the older DeFi-routing-only model
943+
944+
### v1.8.6
897945
- **Report-closure remediation**
898946
- DeFi MCP tools now resolve known protocols to canonical chains, support interoperable address inputs, and fail clearly on explicit wrong-chain requests
899947
- Avalanche dapp resolution is enriched by a vendored AvaPilot-backed registry provider without introducing runtime GitHub/network dependency

RELEASE_NOTES_1.8.8.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Evalanche v1.8.8
2+
3+
## Highlights
4+
5+
- Added a universal in-repo holdings registry shared by all agents
6+
- Added unified holdings scanning through `agent.holdings().scan()`
7+
- Added MCP tools:
8+
- `get_holdings`
9+
- `search_registry`
10+
- `registry_status`
11+
- Unified DeFi routing and holdings discovery onto the same universal registry
12+
- Added DefiLlama import tooling for maintainers via `npm run sync:defillama-registry`
13+
- Updated the README and npm package metadata to match the shipped package surface
14+
15+
## Holdings Coverage
16+
17+
The unified scanner now covers:
18+
19+
- native balances across supported EVM chains
20+
- seeded ERC-20 balances
21+
- ERC-4626 vault positions such as yoUSD and Avantis `avUSDC`
22+
- liquid staking receipts such as sAVAX
23+
- Polymarket positions
24+
- Hyperliquid and dYdX perp positions
25+
26+
## Notes
27+
28+
- The registry source of truth remains the repo
29+
- DefiLlama is used for seed/enrichment, not runtime wallet ownership
30+
- Wallet ownership is always confirmed through live onchain or venue reads

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "evalanche",
3-
"version": "1.8.7",
4-
"description": "Multi-EVM agent wallet SDK with onchain identity (ERC-8004), payment rails (x402), cross-chain bridging (Li.Fi + Gas.zip), and perpetual futures (dYdX v4)",
3+
"version": "1.8.8",
4+
"description": "Multi-EVM agent wallet SDK with unified holdings discovery, onchain identity (ERC-8004), x402 payments, cross-chain liquidity (Li.Fi + Gas.zip), prediction markets, DeFi, and perpetual futures",
55
"main": "./dist/index.cjs",
66
"module": "./dist/index.js",
77
"types": "./dist/index.d.ts",
@@ -23,7 +23,8 @@
2323
"build": "tsup",
2424
"typecheck": "tsc --noEmit",
2525
"test": "vitest run",
26-
"test:watch": "vitest"
26+
"test:watch": "vitest",
27+
"sync:defillama-registry": "node scripts/sync-defillama-registry.mjs"
2728
},
2829
"keywords": [
2930
"avalanche",
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'node:fs/promises';
4+
import path from 'node:path';
5+
import { fileURLToPath } from 'node:url';
6+
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
8+
const root = path.resolve(__dirname, '..');
9+
const seedDir = path.join(root, 'src', 'holdings', 'registry', 'seed');
10+
const protocolOut = path.join(seedDir, 'defillama.protocols.generated.json');
11+
const sourcesOut = path.join(seedDir, 'defillama.sources.generated.json');
12+
13+
const SUPPORTED_CHAINS = new Map([
14+
['ethereum', 'ethereum'],
15+
['base', 'base'],
16+
['arbitrum', 'arbitrum'],
17+
['optimism', 'optimism'],
18+
['polygon', 'polygon'],
19+
['avalanche', 'avalanche'],
20+
['bsc', 'bsc'],
21+
['gnosis', 'gnosis'],
22+
['fantom', 'fantom'],
23+
['linea', 'linea'],
24+
['scroll', 'scroll'],
25+
['celo', 'celo'],
26+
['mantle', 'mantle'],
27+
]);
28+
29+
function normalizeSlug(value) {
30+
return String(value ?? '')
31+
.trim()
32+
.toLowerCase()
33+
.replace(/[^a-z0-9]+/g, '-')
34+
.replace(/^-|-$/g, '');
35+
}
36+
37+
function normalizeChain(value) {
38+
const lowered = String(value ?? '').trim().toLowerCase();
39+
return SUPPORTED_CHAINS.get(lowered);
40+
}
41+
42+
function protocolRecord(protocol) {
43+
const chains = Array.from(new Set(
44+
(Array.isArray(protocol.chains) ? protocol.chains : [])
45+
.map(normalizeChain)
46+
.filter(Boolean),
47+
));
48+
if (chains.length === 0) return null;
49+
50+
return {
51+
protocolId: normalizeSlug(protocol.slug || protocol.name),
52+
name: String(protocol.name),
53+
slug: normalizeSlug(protocol.slug || protocol.name),
54+
category: String(protocol.category ?? 'defi').toLowerCase(),
55+
chains,
56+
website: typeof protocol.url === 'string' ? protocol.url : undefined,
57+
aliases: [protocol.slug, protocol.symbol].filter(Boolean).map((value) => String(value).toLowerCase()),
58+
source: 'defillama',
59+
};
60+
}
61+
62+
function sourceRecord(pool) {
63+
const chain = normalizeChain(pool.chain);
64+
const protocolId = normalizeSlug(pool.project);
65+
if (!chain || !protocolId) return null;
66+
const tokens = Array.isArray(pool.underlyingTokens) ? pool.underlyingTokens : [];
67+
const lowerTokens = tokens.filter((item) => typeof item === 'string' && item.startsWith('0x'));
68+
if (lowerTokens.length === 0) return null;
69+
70+
return {
71+
sourceId: `defillama-${protocolId}-${normalizeSlug(pool.poolMeta || pool.symbol || pool.pool) || pool.pool}`,
72+
protocolId,
73+
chain,
74+
sourceKind: 'lp_receipt',
75+
detectorId: 'lp_receipt_detector',
76+
role: pool.poolMeta || pool.symbol || 'pool',
77+
underlyingTokens: lowerTokens.map((token) => `${chain}:${token}`),
78+
priority: 10,
79+
source: 'defillama',
80+
};
81+
}
82+
83+
async function main() {
84+
const [protocols, poolsPayload] = await Promise.all([
85+
fetch('https://api.llama.fi/protocols').then((res) => res.json()),
86+
fetch('https://yields.llama.fi/pools').then((res) => res.json()),
87+
]);
88+
89+
const normalizedProtocols = Array.from(new Map(
90+
protocols
91+
.map(protocolRecord)
92+
.filter(Boolean)
93+
.map((record) => [record.protocolId, record]),
94+
).values());
95+
96+
const normalizedSources = Array.from(new Map(
97+
(Array.isArray(poolsPayload?.data) ? poolsPayload.data : [])
98+
.map(sourceRecord)
99+
.filter(Boolean)
100+
.map((record) => [record.sourceId, record]),
101+
).values());
102+
103+
await fs.mkdir(seedDir, { recursive: true });
104+
await fs.writeFile(protocolOut, `${JSON.stringify(normalizedProtocols, null, 2)}\n`);
105+
await fs.writeFile(sourcesOut, `${JSON.stringify(normalizedSources, null, 2)}\n`);
106+
107+
console.log(JSON.stringify({
108+
protocols: normalizedProtocols.length,
109+
sources: normalizedSources.length,
110+
protocolOut,
111+
sourcesOut,
112+
}, null, 2));
113+
}
114+
115+
main().catch((error) => {
116+
console.error(error instanceof Error ? error.stack || error.message : String(error));
117+
process.exitCode = 1;
118+
});

src/agent.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import type { PlatformCLI as PlatformCLIType } from './avalanche/platform-cli';
3232
import type { InteropIdentityResolver as InteropResolverType } from './interop/identity';
3333
import type { LiquidStakingClient } from './defi/liquid-staking';
3434
import type { VaultClient } from './defi/vaults';
35+
import type { PolymarketClient } from './polymarket';
36+
import type { HoldingsClient } from './holdings/client';
3537

3638
/** Configuration for the Evalanche agent */
3739
export interface EvalancheConfig {
@@ -86,6 +88,8 @@ export class Evalanche {
8688
private _interopResolver?: InteropResolverType;
8789
private _defiStaking?: LiquidStakingClient;
8890
private _defiVaults?: VaultClient;
91+
private _polymarketClient?: PolymarketClient;
92+
private _holdingsClient?: HoldingsClient;
8993
private readonly _mnemonic?: string;
9094
private readonly _multiVM: boolean;
9195
private _multiVMInitialized = false;
@@ -636,6 +640,29 @@ export class Evalanche {
636640
return { staking: this._defiStaking, vaults: this._defiVaults };
637641
}
638642

643+
/**
644+
* Get or create the Polymarket client (lazy-initialized).
645+
*/
646+
async polymarket(): Promise<PolymarketClient> {
647+
if (!this._polymarketClient) {
648+
const { PolymarketClient } = await import('./polymarket/client');
649+
this._polymarketClient = new PolymarketClient(this.wallet, 137);
650+
}
651+
return this._polymarketClient;
652+
}
653+
654+
/**
655+
* Get the unified holdings scanner backed by the universal registry.
656+
*/
657+
holdings(): HoldingsClient {
658+
if (!this._holdingsClient) {
659+
// eslint-disable-next-line @typescript-eslint/no-var-requires
660+
const { HoldingsClient: HC } = require('./holdings/client') as typeof import('./holdings/client');
661+
this._holdingsClient = new HC(this);
662+
}
663+
return this._holdingsClient;
664+
}
665+
639666
/**
640667
* Find a perpetual market ticker across connected perp venues.
641668
*/

0 commit comments

Comments
 (0)