@elizaos/plugin-wallet 2.0.0-beta.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/LICENSE +21 -0
- package/README.md +64 -0
- package/auto-enable.ts +76 -0
- package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
- package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
- package/dist/aerodrome-CfnESC32.mjs +890 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/index.d.mts +34727 -0
- package/dist/index.mjs +21590 -0
- package/dist/lib/server-wallet-trade.d.mts +34 -0
- package/dist/lib/server-wallet-trade.mjs +306 -0
- package/dist/meteora-BPX39hZo.mjs +22640 -0
- package/dist/orca-Bybp1HXO.mjs +249 -0
- package/dist/pancakeswp-CkEXlXti.mjs +604 -0
- package/dist/plugin-ZO_MTyd0.mjs +529 -0
- package/dist/raydium-rfaM9yEf.mjs +539 -0
- package/dist/sdk/index.d.mts +32492 -0
- package/dist/sdk/index.mjs +6415 -0
- package/dist/types-D5252NZk.mjs +487 -0
- package/dist/uniswap-CReXgXVN.mjs +573 -0
- package/dist/wallet-action.d.mts +6 -0
- package/dist/wallet-action.mjs +820 -0
- package/package.json +152 -0
- package/src/actions/failure-codes.ts +79 -0
- package/src/actions/index.ts +1 -0
- package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
- package/src/analytics/birdeye/birdeye-task.ts +175 -0
- package/src/analytics/birdeye/birdeye.ts +813 -0
- package/src/analytics/birdeye/constants.ts +74 -0
- package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
- package/src/analytics/birdeye/providers/market.ts +227 -0
- package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
- package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
- package/src/analytics/birdeye/providers/trending.ts +365 -0
- package/src/analytics/birdeye/providers/wallet.ts +14 -0
- package/src/analytics/birdeye/search-category.test.ts +207 -0
- package/src/analytics/birdeye/search-category.ts +506 -0
- package/src/analytics/birdeye/service.ts +992 -0
- package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
- package/src/analytics/birdeye/types/api/common.ts +305 -0
- package/src/analytics/birdeye/types/api/defi.ts +220 -0
- package/src/analytics/birdeye/types/api/pair.ts +200 -0
- package/src/analytics/birdeye/types/api/search.ts +86 -0
- package/src/analytics/birdeye/types/api/token.ts +635 -0
- package/src/analytics/birdeye/types/api/trader.ts +76 -0
- package/src/analytics/birdeye/types/api/wallet.ts +181 -0
- package/src/analytics/birdeye/types/shared.ts +106 -0
- package/src/analytics/birdeye/utils.ts +700 -0
- package/src/analytics/dexscreener/errors.ts +28 -0
- package/src/analytics/dexscreener/index.ts +3 -0
- package/src/analytics/dexscreener/search-category.test.ts +49 -0
- package/src/analytics/dexscreener/search-category.ts +42 -0
- package/src/analytics/dexscreener/service.ts +595 -0
- package/src/analytics/dexscreener/types.ts +128 -0
- package/src/analytics/lpinfo/index.d.ts +7 -0
- package/src/analytics/lpinfo/index.ts +52 -0
- package/src/analytics/lpinfo/kamino/README.md +102 -0
- package/src/analytics/lpinfo/kamino/index.ts +24 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
- package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
- package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
- package/src/analytics/lpinfo/steer/README.md +169 -0
- package/src/analytics/lpinfo/steer/index.ts +23 -0
- package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
- package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
- package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
- package/src/analytics/news/index.ts +52 -0
- package/src/analytics/news/interfaces/types.ts +222 -0
- package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
- package/src/analytics/news/services/newsDataService.ts +332 -0
- package/src/analytics/news/utils/formatters.ts +151 -0
- package/src/analytics/token-info/action.ts +240 -0
- package/src/analytics/token-info/index.ts +3 -0
- package/src/analytics/token-info/params.ts +215 -0
- package/src/analytics/token-info/providers.ts +681 -0
- package/src/analytics/token-info/service.ts +168 -0
- package/src/analytics/token-info/types.ts +74 -0
- package/src/audit/audit-log.ts +45 -0
- package/src/browser-shim/build-shim.ts +123 -0
- package/src/browser-shim/index.ts +5 -0
- package/src/browser-shim/shim.template.js +563 -0
- package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
- package/src/chains/evm/LICENSE +21 -0
- package/src/chains/evm/README.md +106 -0
- package/src/chains/evm/actions/helpers.ts +147 -0
- package/src/chains/evm/actions/swap.ts +839 -0
- package/src/chains/evm/actions/transfer.ts +254 -0
- package/src/chains/evm/biome.json +61 -0
- package/src/chains/evm/bridge-router.ts +660 -0
- package/src/chains/evm/build.ts +89 -0
- package/src/chains/evm/chain-handler.ts +416 -0
- package/src/chains/evm/constants.ts +23 -0
- package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
- package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
- package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
- package/src/chains/evm/dex/aerodrome/index.ts +34 -0
- package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
- package/src/chains/evm/dex/aerodrome/types.ts +318 -0
- package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
- package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
- package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
- package/src/chains/evm/dex/uniswap/index.ts +35 -0
- package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
- package/src/chains/evm/dex/uniswap/types.ts +390 -0
- package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
- package/src/chains/evm/generated/specs/specs.ts +151 -0
- package/src/chains/evm/gov-router.ts +250 -0
- package/src/chains/evm/index.browser.ts +16 -0
- package/src/chains/evm/index.ts +31 -0
- package/src/chains/evm/prompts.ts +193 -0
- package/src/chains/evm/providers/get-balance.ts +123 -0
- package/src/chains/evm/providers/wallet.ts +715 -0
- package/src/chains/evm/routes/sign.ts +333 -0
- package/src/chains/evm/rpc-providers.ts +410 -0
- package/src/chains/evm/service.ts +140 -0
- package/src/chains/evm/templates/index.ts +10 -0
- package/src/chains/evm/types/index.ts +432 -0
- package/src/chains/evm/vitest.config.ts +18 -0
- package/src/chains/registry.ts +668 -0
- package/src/chains/solana/README.md +367 -0
- package/src/chains/wallet-action.ts +533 -0
- package/src/chains/wallet-router.test.ts +296 -0
- package/src/contracts.ts +65 -0
- package/src/core-augmentation.ts +10 -0
- package/src/index.ts +71 -0
- package/src/lib/server-wallet-trade.ts +192 -0
- package/src/lib/wallet-export-guard.ts +330 -0
- package/src/lp/actions/liquidity.ts +827 -0
- package/src/lp/e2e/real-token-tests.ts +428 -0
- package/src/lp/e2e/scenarios.ts +470 -0
- package/src/lp/e2e/test-utils.ts +145 -0
- package/src/lp/lp-manager-entry.ts +303 -0
- package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
- package/src/lp/services/DexInteractionService.ts +226 -0
- package/src/lp/services/LpManagementService.test.ts +148 -0
- package/src/lp/services/LpManagementService.ts +632 -0
- package/src/lp/services/UserLpProfileService.ts +163 -0
- package/src/lp/services/VaultService.ts +153 -0
- package/src/lp/services/YieldOptimizationService.ts +344 -0
- package/src/lp/services/__tests__/MockLpService.ts +146 -0
- package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
- package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
- package/src/lp/types.ts +582 -0
- package/src/lp/utils/solanaClient.ts +143 -0
- package/src/plugin.ts +125 -0
- package/src/policy/policy.ts +19 -0
- package/src/providers/canonical-provider.ts +27 -0
- package/src/providers/unified-wallet-provider.ts +79 -0
- package/src/register-routes.ts +11 -0
- package/src/routes/plugin.ts +47 -0
- package/src/routes/wallet-market-overview-route.ts +869 -0
- package/src/sdk/abi.ts +258 -0
- package/src/sdk/bridge/abis.ts +126 -0
- package/src/sdk/bridge/client.ts +518 -0
- package/src/sdk/bridge/index.ts +56 -0
- package/src/sdk/bridge/solana.ts +604 -0
- package/src/sdk/bridge/types.ts +202 -0
- package/src/sdk/convenience.ts +347 -0
- package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
- package/src/sdk/escrow/types.ts +64 -0
- package/src/sdk/escrow/verifiers.ts +73 -0
- package/src/sdk/identity/erc8004.ts +692 -0
- package/src/sdk/identity/reputation.ts +449 -0
- package/src/sdk/identity/uaid.ts +497 -0
- package/src/sdk/identity/validation.ts +372 -0
- package/src/sdk/index.ts +763 -0
- package/src/sdk/policy/SpendingPolicy.ts +260 -0
- package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
- package/src/sdk/router/PaymentRouter.ts +215 -0
- package/src/sdk/router/index.ts +8 -0
- package/src/sdk/swap/SwapModule.ts +310 -0
- package/src/sdk/swap/abi.ts +117 -0
- package/src/sdk/swap/index.ts +34 -0
- package/src/sdk/swap/types.ts +135 -0
- package/src/sdk/tokens/decimals.ts +140 -0
- package/src/sdk/tokens/registry.ts +911 -0
- package/src/sdk/tokens/solana.ts +419 -0
- package/src/sdk/tokens/transfers.ts +327 -0
- package/src/sdk/types.ts +158 -0
- package/src/sdk/wallet-core.ts +115 -0
- package/src/sdk/x402/budget.ts +168 -0
- package/src/sdk/x402/chains/abstract/index.ts +280 -0
- package/src/sdk/x402/client.ts +320 -0
- package/src/sdk/x402/index.ts +46 -0
- package/src/sdk/x402/middleware.ts +92 -0
- package/src/sdk/x402/multi-asset.ts +144 -0
- package/src/sdk/x402/types.ts +156 -0
- package/src/services/wallet-backend-service.ts +328 -0
- package/src/types/wallet-router.ts +227 -0
- package/src/utils/intent-trajectory.ts +106 -0
- package/src/wallet/backend.ts +62 -0
- package/src/wallet/errors.ts +49 -0
- package/src/wallet/index.ts +27 -0
- package/src/wallet/local-eoa-backend.ts +201 -0
- package/src/wallet/pending.ts +60 -0
- package/src/wallet/select-backend.ts +47 -0
- package/src/wallet/steward-backend.ts +161 -0
- package/src/wallet-action.ts +1 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ERC-8004: Trustless Agents — Identity Registry Integration
|
|
3
|
+
*
|
|
4
|
+
* Implements the Identity Registry component of ERC-8004, which provides every
|
|
5
|
+
* AI agent with a portable, censorship-resistant on-chain identifier using ERC-721
|
|
6
|
+
* with URIStorage extension.
|
|
7
|
+
*
|
|
8
|
+
* Spec: https://eips.ethereum.org/EIPS/eip-8004
|
|
9
|
+
* Status: DRAFT (August 2025). No official mainnet singleton deployed yet.
|
|
10
|
+
* Key Principle: Non-custodial. All signing happens locally via WalletClient.
|
|
11
|
+
*/
|
|
12
|
+
import {
|
|
13
|
+
type Address,
|
|
14
|
+
type Chain,
|
|
15
|
+
createPublicClient,
|
|
16
|
+
getContract,
|
|
17
|
+
type Hash,
|
|
18
|
+
type Hex,
|
|
19
|
+
http,
|
|
20
|
+
type PublicClient,
|
|
21
|
+
type WalletClient,
|
|
22
|
+
} from "viem";
|
|
23
|
+
import {
|
|
24
|
+
arbitrum,
|
|
25
|
+
arbitrumSepolia,
|
|
26
|
+
base,
|
|
27
|
+
baseSepolia,
|
|
28
|
+
mainnet,
|
|
29
|
+
polygon,
|
|
30
|
+
} from "viem/chains";
|
|
31
|
+
|
|
32
|
+
// ─── ABI ─────────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
export const ERC8004IdentityRegistryAbi = [
|
|
35
|
+
// register() — no args
|
|
36
|
+
{
|
|
37
|
+
name: "register",
|
|
38
|
+
type: "function",
|
|
39
|
+
stateMutability: "nonpayable",
|
|
40
|
+
inputs: [],
|
|
41
|
+
outputs: [{ name: "agentId", type: "uint256" }],
|
|
42
|
+
},
|
|
43
|
+
// register(string) — URI only
|
|
44
|
+
{
|
|
45
|
+
name: "register",
|
|
46
|
+
type: "function",
|
|
47
|
+
stateMutability: "nonpayable",
|
|
48
|
+
inputs: [{ name: "agentURI", type: "string" }],
|
|
49
|
+
outputs: [{ name: "agentId", type: "uint256" }],
|
|
50
|
+
},
|
|
51
|
+
// register(string,tuple[]) — URI + metadata
|
|
52
|
+
{
|
|
53
|
+
name: "register",
|
|
54
|
+
type: "function",
|
|
55
|
+
stateMutability: "nonpayable",
|
|
56
|
+
inputs: [
|
|
57
|
+
{ name: "agentURI", type: "string" },
|
|
58
|
+
{
|
|
59
|
+
name: "metadata",
|
|
60
|
+
type: "tuple[]",
|
|
61
|
+
components: [
|
|
62
|
+
{ name: "metadataKey", type: "string" },
|
|
63
|
+
{ name: "metadataValue", type: "bytes" },
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
outputs: [{ name: "agentId", type: "uint256" }],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "setAgentURI",
|
|
71
|
+
type: "function",
|
|
72
|
+
stateMutability: "nonpayable",
|
|
73
|
+
inputs: [
|
|
74
|
+
{ name: "agentId", type: "uint256" },
|
|
75
|
+
{ name: "newURI", type: "string" },
|
|
76
|
+
],
|
|
77
|
+
outputs: [],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "tokenURI",
|
|
81
|
+
type: "function",
|
|
82
|
+
stateMutability: "view",
|
|
83
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
84
|
+
outputs: [{ name: "", type: "string" }],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "getMetadata",
|
|
88
|
+
type: "function",
|
|
89
|
+
stateMutability: "view",
|
|
90
|
+
inputs: [
|
|
91
|
+
{ name: "agentId", type: "uint256" },
|
|
92
|
+
{ name: "metadataKey", type: "string" },
|
|
93
|
+
],
|
|
94
|
+
outputs: [{ name: "", type: "bytes" }],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "setMetadata",
|
|
98
|
+
type: "function",
|
|
99
|
+
stateMutability: "nonpayable",
|
|
100
|
+
inputs: [
|
|
101
|
+
{ name: "agentId", type: "uint256" },
|
|
102
|
+
{ name: "metadataKey", type: "string" },
|
|
103
|
+
{ name: "metadataValue", type: "bytes" },
|
|
104
|
+
],
|
|
105
|
+
outputs: [],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "getAgentWallet",
|
|
109
|
+
type: "function",
|
|
110
|
+
stateMutability: "view",
|
|
111
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
112
|
+
outputs: [{ name: "", type: "address" }],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "setAgentWallet",
|
|
116
|
+
type: "function",
|
|
117
|
+
stateMutability: "nonpayable",
|
|
118
|
+
inputs: [
|
|
119
|
+
{ name: "agentId", type: "uint256" },
|
|
120
|
+
{ name: "newWallet", type: "address" },
|
|
121
|
+
{ name: "deadline", type: "uint256" },
|
|
122
|
+
{ name: "signature", type: "bytes" },
|
|
123
|
+
],
|
|
124
|
+
outputs: [],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "unsetAgentWallet",
|
|
128
|
+
type: "function",
|
|
129
|
+
stateMutability: "nonpayable",
|
|
130
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
131
|
+
outputs: [],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "ownerOf",
|
|
135
|
+
type: "function",
|
|
136
|
+
stateMutability: "view",
|
|
137
|
+
inputs: [{ name: "tokenId", type: "uint256" }],
|
|
138
|
+
outputs: [{ name: "", type: "address" }],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "Registered",
|
|
142
|
+
type: "event",
|
|
143
|
+
inputs: [
|
|
144
|
+
{ name: "agentId", type: "uint256", indexed: true },
|
|
145
|
+
{ name: "agentURI", type: "string", indexed: false },
|
|
146
|
+
{ name: "owner", type: "address", indexed: true },
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "URIUpdated",
|
|
151
|
+
type: "event",
|
|
152
|
+
inputs: [
|
|
153
|
+
{ name: "agentId", type: "uint256", indexed: true },
|
|
154
|
+
{ name: "newURI", type: "string", indexed: false },
|
|
155
|
+
{ name: "updatedBy", type: "address", indexed: true },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "MetadataSet",
|
|
160
|
+
type: "event",
|
|
161
|
+
inputs: [
|
|
162
|
+
{ name: "agentId", type: "uint256", indexed: true },
|
|
163
|
+
{ name: "indexedMetadataKey", type: "string", indexed: true },
|
|
164
|
+
{ name: "metadataKey", type: "string", indexed: false },
|
|
165
|
+
{ name: "metadataValue", type: "bytes", indexed: false },
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
] as const;
|
|
169
|
+
|
|
170
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
export interface AgentServiceEndpoint {
|
|
173
|
+
name: string;
|
|
174
|
+
endpoint: string;
|
|
175
|
+
version?: string;
|
|
176
|
+
skills?: string[];
|
|
177
|
+
domains?: string[];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type SupportedTrustMechanism =
|
|
181
|
+
| "reputation"
|
|
182
|
+
| "crypto-economic"
|
|
183
|
+
| "tee-attestation"
|
|
184
|
+
| "zkml"
|
|
185
|
+
| string;
|
|
186
|
+
|
|
187
|
+
export interface AgentRegistrationRef {
|
|
188
|
+
agentId: number;
|
|
189
|
+
agentRegistry: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface AgentRegistrationFile {
|
|
193
|
+
type: string;
|
|
194
|
+
name: string;
|
|
195
|
+
description: string;
|
|
196
|
+
image?: string;
|
|
197
|
+
services?: AgentServiceEndpoint[];
|
|
198
|
+
x402Support?: boolean;
|
|
199
|
+
active?: boolean;
|
|
200
|
+
registrations?: AgentRegistrationRef[];
|
|
201
|
+
supportedTrust?: SupportedTrustMechanism[];
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface AgentModelMetadata {
|
|
206
|
+
model?: string;
|
|
207
|
+
provider?: string;
|
|
208
|
+
version?: string;
|
|
209
|
+
capabilities?: string[];
|
|
210
|
+
framework?: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface AgentIdentity {
|
|
214
|
+
agentId: bigint;
|
|
215
|
+
owner: Address;
|
|
216
|
+
agentURI: string;
|
|
217
|
+
agentWallet: Address;
|
|
218
|
+
registrationFile: AgentRegistrationFile | null;
|
|
219
|
+
modelMetadata: AgentModelMetadata | null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface MetadataEntry {
|
|
223
|
+
metadataKey: string;
|
|
224
|
+
metadataValue: Hex;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export type SupportedChain =
|
|
228
|
+
| "base"
|
|
229
|
+
| "base-sepolia"
|
|
230
|
+
| "ethereum"
|
|
231
|
+
| "arbitrum"
|
|
232
|
+
| "polygon"
|
|
233
|
+
| "arbitrum-sepolia";
|
|
234
|
+
|
|
235
|
+
export interface ERC8004ClientConfig {
|
|
236
|
+
registryAddress?: Address;
|
|
237
|
+
chain: SupportedChain;
|
|
238
|
+
rpcUrl?: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface RegistrationResult {
|
|
242
|
+
txHash: Hash;
|
|
243
|
+
agentId: bigint | null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
247
|
+
|
|
248
|
+
export const METADATA_KEYS = {
|
|
249
|
+
AGENT_WALLET: "agentWallet",
|
|
250
|
+
MODEL: "agentModel",
|
|
251
|
+
MODEL_PROVIDER: "agentModelProvider",
|
|
252
|
+
VERSION: "agentVersion",
|
|
253
|
+
CAPABILITIES: "agentCapabilities",
|
|
254
|
+
FRAMEWORK: "agentFramework",
|
|
255
|
+
} as const;
|
|
256
|
+
|
|
257
|
+
export const REGISTRATION_FILE_TYPE =
|
|
258
|
+
"https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
259
|
+
|
|
260
|
+
export const KNOWN_REGISTRY_ADDRESSES: Record<
|
|
261
|
+
string,
|
|
262
|
+
{ identity: Address; reputation: Address; validation?: Address }
|
|
263
|
+
> = {
|
|
264
|
+
ethereum: {
|
|
265
|
+
identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
266
|
+
reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
|
|
267
|
+
},
|
|
268
|
+
base: {
|
|
269
|
+
identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
270
|
+
reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
|
|
271
|
+
},
|
|
272
|
+
arbitrum: {
|
|
273
|
+
identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
274
|
+
reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
|
|
275
|
+
},
|
|
276
|
+
polygon: {
|
|
277
|
+
identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
278
|
+
reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
|
|
279
|
+
},
|
|
280
|
+
"base-sepolia": {
|
|
281
|
+
identity: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
|
|
282
|
+
reputation: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
|
|
283
|
+
},
|
|
284
|
+
"arbitrum-sepolia": {
|
|
285
|
+
identity: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
|
|
286
|
+
reputation: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const CHAINS: Record<string, Chain> = {
|
|
291
|
+
base,
|
|
292
|
+
"base-sepolia": baseSepolia,
|
|
293
|
+
ethereum: mainnet,
|
|
294
|
+
arbitrum,
|
|
295
|
+
polygon,
|
|
296
|
+
"arbitrum-sepolia": arbitrumSepolia,
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const REGISTERED_TOPIC =
|
|
300
|
+
"0xca52e62c367d81bb2e328eb795f7c7ba24afb478408a26c0e201d155c449bc4a";
|
|
301
|
+
|
|
302
|
+
// ─── Client ──────────────────────────────────────────────────────────────────
|
|
303
|
+
|
|
304
|
+
export class ERC8004Client {
|
|
305
|
+
private readonly publicClient: PublicClient;
|
|
306
|
+
private readonly config: ERC8004ClientConfig & { registryAddress: Address };
|
|
307
|
+
private readonly chain: Chain;
|
|
308
|
+
|
|
309
|
+
constructor(config: ERC8004ClientConfig) {
|
|
310
|
+
// Auto-resolve registry address from KNOWN_REGISTRY_ADDRESSES if not explicitly provided
|
|
311
|
+
const resolvedAddress =
|
|
312
|
+
config.registryAddress ??
|
|
313
|
+
KNOWN_REGISTRY_ADDRESSES[config.chain]?.identity;
|
|
314
|
+
if (!resolvedAddress) {
|
|
315
|
+
throw new Error(
|
|
316
|
+
`ERC8004Client: No registry address provided and no known address for chain "${config.chain}"`,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
this.config = { ...config, registryAddress: resolvedAddress };
|
|
320
|
+
const chain = CHAINS[config.chain];
|
|
321
|
+
if (!chain)
|
|
322
|
+
throw new Error(`ERC8004Client: Unsupported chain "${config.chain}"`);
|
|
323
|
+
this.chain = chain;
|
|
324
|
+
this.publicClient = createPublicClient({
|
|
325
|
+
chain,
|
|
326
|
+
transport: http(config.rpcUrl),
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private getReadContract() {
|
|
331
|
+
return getContract({
|
|
332
|
+
address: this.config.registryAddress,
|
|
333
|
+
abi: ERC8004IdentityRegistryAbi,
|
|
334
|
+
client: this.publicClient,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
private getWriteContract(walletClient: WalletClient) {
|
|
339
|
+
return getContract({
|
|
340
|
+
address: this.config.registryAddress,
|
|
341
|
+
abi: ERC8004IdentityRegistryAbi,
|
|
342
|
+
client: { public: this.publicClient, wallet: walletClient },
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async registerAgent(
|
|
347
|
+
walletClient: WalletClient,
|
|
348
|
+
metadata: Omit<AgentRegistrationFile, "type">,
|
|
349
|
+
agentURI?: string,
|
|
350
|
+
onChainMetadata?: Record<string, string>,
|
|
351
|
+
): Promise<RegistrationResult> {
|
|
352
|
+
if (!walletClient.account)
|
|
353
|
+
throw new Error("ERC8004Client: WalletClient has no account");
|
|
354
|
+
|
|
355
|
+
const registrationFile = {
|
|
356
|
+
type: REGISTRATION_FILE_TYPE,
|
|
357
|
+
...metadata,
|
|
358
|
+
} as AgentRegistrationFile;
|
|
359
|
+
const resolvedURI = agentURI ?? buildDataURI(registrationFile);
|
|
360
|
+
const contract = this.getWriteContract(walletClient);
|
|
361
|
+
|
|
362
|
+
let txHash: Hash;
|
|
363
|
+
if (onChainMetadata && Object.keys(onChainMetadata).length > 0) {
|
|
364
|
+
const entries = encodeMetadataEntries(onChainMetadata);
|
|
365
|
+
txHash = await contract.write.register([resolvedURI, entries], {
|
|
366
|
+
account: walletClient.account,
|
|
367
|
+
chain: this.chain,
|
|
368
|
+
});
|
|
369
|
+
} else {
|
|
370
|
+
txHash = await contract.write.register([resolvedURI], {
|
|
371
|
+
account: walletClient.account,
|
|
372
|
+
chain: this.chain,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let agentId: bigint | null = null;
|
|
377
|
+
try {
|
|
378
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
379
|
+
hash: txHash,
|
|
380
|
+
});
|
|
381
|
+
const registeredEvent = receipt.logs.find(
|
|
382
|
+
(log) =>
|
|
383
|
+
log.address.toLowerCase() ===
|
|
384
|
+
this.config.registryAddress.toLowerCase() &&
|
|
385
|
+
log.topics[0] === REGISTERED_TOPIC,
|
|
386
|
+
);
|
|
387
|
+
if (registeredEvent?.topics[1]) {
|
|
388
|
+
agentId = BigInt(registeredEvent.topics[1]);
|
|
389
|
+
}
|
|
390
|
+
} catch {
|
|
391
|
+
// agentId remains null
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return { txHash, agentId };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async lookupAgentIdentity(agentId: bigint): Promise<AgentIdentity> {
|
|
398
|
+
const contract = this.getReadContract();
|
|
399
|
+
const [owner, agentURI, agentWallet] = await Promise.all([
|
|
400
|
+
contract.read.ownerOf([agentId]),
|
|
401
|
+
contract.read.tokenURI([agentId]),
|
|
402
|
+
contract.read.getAgentWallet([agentId]),
|
|
403
|
+
]);
|
|
404
|
+
|
|
405
|
+
let registrationFile: AgentRegistrationFile | null = null;
|
|
406
|
+
try {
|
|
407
|
+
registrationFile = await resolveAgentURI(agentURI as string);
|
|
408
|
+
} catch {
|
|
409
|
+
/* unavailable */
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const modelMetadata = await this.readModelMetadata(agentId);
|
|
413
|
+
|
|
414
|
+
return {
|
|
415
|
+
agentId,
|
|
416
|
+
owner: owner as Address,
|
|
417
|
+
agentURI: agentURI as string,
|
|
418
|
+
agentWallet: agentWallet as Address,
|
|
419
|
+
registrationFile,
|
|
420
|
+
modelMetadata,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
async lookupAgentByOwner(
|
|
425
|
+
ownerAddress: Address,
|
|
426
|
+
fromBlock: bigint = 0n,
|
|
427
|
+
): Promise<AgentIdentity | null> {
|
|
428
|
+
const logs = await this.publicClient.getLogs({
|
|
429
|
+
address: this.config.registryAddress,
|
|
430
|
+
event: {
|
|
431
|
+
type: "event",
|
|
432
|
+
name: "Registered",
|
|
433
|
+
inputs: [
|
|
434
|
+
{ name: "agentId", type: "uint256", indexed: true },
|
|
435
|
+
{ name: "agentURI", type: "string", indexed: false },
|
|
436
|
+
{ name: "owner", type: "address", indexed: true },
|
|
437
|
+
],
|
|
438
|
+
},
|
|
439
|
+
args: { owner: ownerAddress },
|
|
440
|
+
fromBlock,
|
|
441
|
+
toBlock: "latest",
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
if (logs.length === 0) return null;
|
|
445
|
+
const latestLog = logs[logs.length - 1];
|
|
446
|
+
const agentId = BigInt(latestLog.args?.agentId ?? 0);
|
|
447
|
+
return this.lookupAgentIdentity(agentId);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async updateAgentURI(
|
|
451
|
+
walletClient: WalletClient,
|
|
452
|
+
agentId: bigint,
|
|
453
|
+
newURI: string,
|
|
454
|
+
): Promise<Hash> {
|
|
455
|
+
if (!walletClient.account)
|
|
456
|
+
throw new Error("ERC8004Client: WalletClient has no account");
|
|
457
|
+
const contract = this.getWriteContract(walletClient);
|
|
458
|
+
return contract.write.setAgentURI([agentId, newURI], {
|
|
459
|
+
account: walletClient.account,
|
|
460
|
+
chain: this.chain,
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async getOnChainMetadata(agentId: bigint, key: string): Promise<Hex | null> {
|
|
465
|
+
const contract = this.getReadContract();
|
|
466
|
+
const value = await contract.read.getMetadata([agentId, key]);
|
|
467
|
+
return value === "0x" || value === null ? null : (value as Hex);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
async setOnChainMetadata(
|
|
471
|
+
walletClient: WalletClient,
|
|
472
|
+
agentId: bigint,
|
|
473
|
+
key: string,
|
|
474
|
+
value: string,
|
|
475
|
+
): Promise<Hash> {
|
|
476
|
+
if (!walletClient.account)
|
|
477
|
+
throw new Error("ERC8004Client: WalletClient has no account");
|
|
478
|
+
if (key === METADATA_KEYS.AGENT_WALLET) {
|
|
479
|
+
throw new Error(
|
|
480
|
+
'ERC8004Client: "agentWallet" is reserved — use setAgentWallet() instead',
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
const contract = this.getWriteContract(walletClient);
|
|
484
|
+
const hexValue = stringToHex(value);
|
|
485
|
+
return contract.write.setMetadata([agentId, key, hexValue], {
|
|
486
|
+
account: walletClient.account,
|
|
487
|
+
chain: this.chain,
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
async setModelMetadata(
|
|
492
|
+
walletClient: WalletClient,
|
|
493
|
+
agentId: bigint,
|
|
494
|
+
model: AgentModelMetadata,
|
|
495
|
+
): Promise<Hash[]> {
|
|
496
|
+
const hashes: Hash[] = [];
|
|
497
|
+
const entries: [string, string][] = [];
|
|
498
|
+
if (model.model) entries.push([METADATA_KEYS.MODEL, model.model]);
|
|
499
|
+
if (model.provider)
|
|
500
|
+
entries.push([METADATA_KEYS.MODEL_PROVIDER, model.provider]);
|
|
501
|
+
if (model.version) entries.push([METADATA_KEYS.VERSION, model.version]);
|
|
502
|
+
if (model.framework)
|
|
503
|
+
entries.push([METADATA_KEYS.FRAMEWORK, model.framework]);
|
|
504
|
+
if (model.capabilities?.length)
|
|
505
|
+
entries.push([
|
|
506
|
+
METADATA_KEYS.CAPABILITIES,
|
|
507
|
+
JSON.stringify(model.capabilities),
|
|
508
|
+
]);
|
|
509
|
+
|
|
510
|
+
for (const [key, val] of entries) {
|
|
511
|
+
const hash = await this.setOnChainMetadata(
|
|
512
|
+
walletClient,
|
|
513
|
+
agentId,
|
|
514
|
+
key,
|
|
515
|
+
val,
|
|
516
|
+
);
|
|
517
|
+
hashes.push(hash);
|
|
518
|
+
}
|
|
519
|
+
return hashes;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
async readModelMetadata(agentId: bigint): Promise<AgentModelMetadata | null> {
|
|
523
|
+
const keys = [
|
|
524
|
+
METADATA_KEYS.MODEL,
|
|
525
|
+
METADATA_KEYS.MODEL_PROVIDER,
|
|
526
|
+
METADATA_KEYS.VERSION,
|
|
527
|
+
METADATA_KEYS.FRAMEWORK,
|
|
528
|
+
METADATA_KEYS.CAPABILITIES,
|
|
529
|
+
];
|
|
530
|
+
const values = await Promise.all(
|
|
531
|
+
keys.map((k) => this.getOnChainMetadata(agentId, k)),
|
|
532
|
+
);
|
|
533
|
+
const [modelHex, providerHex, versionHex, frameworkHex, capabilitiesHex] =
|
|
534
|
+
values;
|
|
535
|
+
|
|
536
|
+
if (
|
|
537
|
+
!modelHex &&
|
|
538
|
+
!providerHex &&
|
|
539
|
+
!versionHex &&
|
|
540
|
+
!frameworkHex &&
|
|
541
|
+
!capabilitiesHex
|
|
542
|
+
)
|
|
543
|
+
return null;
|
|
544
|
+
|
|
545
|
+
const result: AgentModelMetadata = {};
|
|
546
|
+
if (modelHex) result.model = hexToString(modelHex);
|
|
547
|
+
if (providerHex) result.provider = hexToString(providerHex);
|
|
548
|
+
if (versionHex) result.version = hexToString(versionHex);
|
|
549
|
+
if (frameworkHex) result.framework = hexToString(frameworkHex);
|
|
550
|
+
if (capabilitiesHex) {
|
|
551
|
+
try {
|
|
552
|
+
result.capabilities = JSON.parse(hexToString(capabilitiesHex));
|
|
553
|
+
} catch {
|
|
554
|
+
result.capabilities = [];
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return result;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
async getAgentWallet(agentId: bigint): Promise<Address> {
|
|
561
|
+
const contract = this.getReadContract();
|
|
562
|
+
return contract.read.getAgentWallet([agentId]) as Promise<Address>;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
async setAgentWallet(
|
|
566
|
+
walletClient: WalletClient,
|
|
567
|
+
agentId: bigint,
|
|
568
|
+
newWallet: Address,
|
|
569
|
+
deadline: bigint,
|
|
570
|
+
signature: Hex,
|
|
571
|
+
): Promise<Hash> {
|
|
572
|
+
if (!walletClient.account)
|
|
573
|
+
throw new Error("ERC8004Client: WalletClient has no account");
|
|
574
|
+
const contract = this.getWriteContract(walletClient);
|
|
575
|
+
return contract.write.setAgentWallet(
|
|
576
|
+
[agentId, newWallet, deadline, signature],
|
|
577
|
+
{
|
|
578
|
+
account: walletClient.account,
|
|
579
|
+
chain: this.chain,
|
|
580
|
+
},
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
async unsetAgentWallet(
|
|
585
|
+
walletClient: WalletClient,
|
|
586
|
+
agentId: bigint,
|
|
587
|
+
): Promise<Hash> {
|
|
588
|
+
if (!walletClient.account)
|
|
589
|
+
throw new Error("ERC8004Client: WalletClient has no account");
|
|
590
|
+
const contract = this.getWriteContract(walletClient);
|
|
591
|
+
return contract.write.unsetAgentWallet([agentId], {
|
|
592
|
+
account: walletClient.account,
|
|
593
|
+
chain: this.chain,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// ─── Standalone helpers ───────────────────────────────────────────────────────
|
|
599
|
+
|
|
600
|
+
export function buildDataURI(registrationFile: AgentRegistrationFile): string {
|
|
601
|
+
const payload = { ...registrationFile, type: REGISTRATION_FILE_TYPE };
|
|
602
|
+
const json = JSON.stringify(payload);
|
|
603
|
+
const b64 = btoa(unescape(encodeURIComponent(json)));
|
|
604
|
+
return `data:application/json;base64,${b64}`;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export function parseDataURI(uri: string): AgentRegistrationFile {
|
|
608
|
+
if (uri.startsWith("data:application/json;base64,")) {
|
|
609
|
+
const b64 = uri.replace("data:application/json;base64,", "");
|
|
610
|
+
const json = decodeURIComponent(escape(atob(b64)));
|
|
611
|
+
return JSON.parse(json);
|
|
612
|
+
}
|
|
613
|
+
if (uri.startsWith("{")) return JSON.parse(uri);
|
|
614
|
+
throw new Error(
|
|
615
|
+
`parseDataURI: Cannot parse URI scheme: ${uri.substring(0, 50)}`,
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export async function resolveAgentURI(
|
|
620
|
+
uri: string,
|
|
621
|
+
): Promise<AgentRegistrationFile> {
|
|
622
|
+
if (uri.startsWith("data:")) return parseDataURI(uri);
|
|
623
|
+
if (uri.startsWith("https://") || uri.startsWith("http://")) {
|
|
624
|
+
const response = await fetch(uri);
|
|
625
|
+
if (!response.ok)
|
|
626
|
+
throw new Error(`resolveAgentURI: HTTP ${response.status} for ${uri}`);
|
|
627
|
+
return response.json();
|
|
628
|
+
}
|
|
629
|
+
throw new Error(`resolveAgentURI: Unsupported URI scheme: ${uri}`);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function validateRegistrationFile(
|
|
633
|
+
file: AgentRegistrationFile,
|
|
634
|
+
): string[] {
|
|
635
|
+
const errors: string[] = [];
|
|
636
|
+
if (file.type !== REGISTRATION_FILE_TYPE)
|
|
637
|
+
errors.push(`type must be "${REGISTRATION_FILE_TYPE}"`);
|
|
638
|
+
if (!file.name || typeof file.name !== "string" || file.name.trim() === "")
|
|
639
|
+
errors.push("name is required");
|
|
640
|
+
if (!file.description || typeof file.description !== "string")
|
|
641
|
+
errors.push("description is required");
|
|
642
|
+
if (file.services) {
|
|
643
|
+
file.services.forEach((svc, i) => {
|
|
644
|
+
if (!svc.name) errors.push(`services[${i}].name is required`);
|
|
645
|
+
if (!svc.endpoint) errors.push(`services[${i}].endpoint is required`);
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
if (file.registrations) {
|
|
649
|
+
file.registrations.forEach((reg, i) => {
|
|
650
|
+
if (reg.agentId === undefined)
|
|
651
|
+
errors.push(`registrations[${i}].agentId is required`);
|
|
652
|
+
if (!reg.agentRegistry)
|
|
653
|
+
errors.push(`registrations[${i}].agentRegistry is required`);
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
return errors;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export function formatAgentRegistry(
|
|
660
|
+
chainId: number,
|
|
661
|
+
registryAddress: Address,
|
|
662
|
+
): string {
|
|
663
|
+
return `eip155:${chainId}:${registryAddress}`;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// ─── Internal utilities ───────────────────────────────────────────────────────
|
|
667
|
+
|
|
668
|
+
function stringToHex(str: string): Hex {
|
|
669
|
+
const bytes = new TextEncoder().encode(str);
|
|
670
|
+
const hexStr = Array.from(bytes)
|
|
671
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
672
|
+
.join("");
|
|
673
|
+
return `0x${hexStr}` as Hex;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function hexToString(hex: Hex): string {
|
|
677
|
+
const stripped = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
678
|
+
const pairs = stripped.match(/.{1,2}/g);
|
|
679
|
+
const bytes = new Uint8Array(
|
|
680
|
+
pairs?.map((byte) => Number.parseInt(byte, 16)) ?? [],
|
|
681
|
+
);
|
|
682
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function encodeMetadataEntries(
|
|
686
|
+
entries: Record<string, string>,
|
|
687
|
+
): MetadataEntry[] {
|
|
688
|
+
return Object.entries(entries).map(([key, value]) => ({
|
|
689
|
+
metadataKey: key,
|
|
690
|
+
metadataValue: stringToHex(value),
|
|
691
|
+
}));
|
|
692
|
+
}
|