@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 up2itnow0822
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @elizaos/plugin-wallet
|
|
2
|
+
|
|
3
|
+
Unified non-custodial wallet for elizaOS agents. Replaces the legacy fan-out across `plugin-evm`, `plugin-solana`, `plugin-raydium`, `plugin-orca`, `plugin-meteora`, `plugin-jupiter`, `plugin-lp-manager`, `plugin-clanker`, and the former `elizaos-plugin-agentwallet` stub with one canonical action+provider surface governed by [`docs/architecture/wallet-and-trading.md`](../../../docs/architecture/wallet-and-trading.md).
|
|
4
|
+
|
|
5
|
+
## Surface
|
|
6
|
+
|
|
7
|
+
The plugin exposes **10 canonical planner-visible actions**:
|
|
8
|
+
|
|
9
|
+
| Action | Purpose |
|
|
10
|
+
|--------|---------|
|
|
11
|
+
| `TRADE` | Open positions, swap, bridge. Discriminated by `kind`: `perp` (Hyperliquid), `prediction` (Polymarket), `spot` / `swap` (Li.Fi on EVM, Jupiter on Solana), `bridge` (Li.Fi / CCTP). |
|
|
12
|
+
| `MANAGE_POSITION` | Close, modify, cancel orders. |
|
|
13
|
+
| `QUERY_MARKET` | Read-only price / depth / funding / chart / news / sentiment. No wallet required. |
|
|
14
|
+
| `QUERY_PORTFOLIO` | Balances, positions, P&L, history. |
|
|
15
|
+
| `LEND` | Supply / borrow / repay / withdraw on Aave or Morpho. |
|
|
16
|
+
| `MANAGE_LP` | Open / close / collect / rebalance LP positions. EVM (Uniswap V3, Aerodrome) + Solana (Raydium, Orca Whirlpools, Meteora DLMM) behind one surface. |
|
|
17
|
+
| `TRANSFER` | Move value to an arbitrary external address. EVM + Solana. Always policy-checked. |
|
|
18
|
+
| `SET_AUTOMATION` | DCA, threshold triggers, P&L exits. |
|
|
19
|
+
| `MANAGE_AUTOMATION` | List / pause / resume / delete automations. |
|
|
20
|
+
| `MINT` | Token launches via Clanker on Base. |
|
|
21
|
+
|
|
22
|
+
These dispatch into **typed providers** (one per venue / data source). Adding a new venue means adding a provider, **not** a new planner verb.
|
|
23
|
+
|
|
24
|
+
## Wallet abstraction
|
|
25
|
+
|
|
26
|
+
Two backends behind `WalletBackend`:
|
|
27
|
+
|
|
28
|
+
- **`LocalEoaBackend`** — desktop default. EOA private keys hydrated from the OS keychain. Optional ERC-6551 token-bound account mode (via the bundled SDK at `./sdk`) for on-chain spend policy enforcement.
|
|
29
|
+
- **`StewardBackend`** — cloud + mobile default. Multi-tenant Steward service is the only custody primitive in cloud. No fallback to local.
|
|
30
|
+
|
|
31
|
+
See `src/wallet/` for interface and impls. `ELIZA_WALLET_BACKEND=local|steward|auto` selects at runtime.
|
|
32
|
+
|
|
33
|
+
## Layout
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/
|
|
37
|
+
index.ts # Plugin export
|
|
38
|
+
plugin.ts # Plugin object: actions + providers + services
|
|
39
|
+
sdk/ # Lifted from agent-wallet-sdk (ERC-6551, x402, CCTP, swap, escrow, identity, multi-token, payment router)
|
|
40
|
+
wallet/ # WalletBackend interface + LocalEoa + Steward
|
|
41
|
+
policy/ # PolicyModule (local + steward bridge)
|
|
42
|
+
providers/ # Canonical providers (one per venue / data source)
|
|
43
|
+
actions/ # Canonical actions (TRADE, MANAGE_POSITION, ...)
|
|
44
|
+
audit/ # Append-only hash-chained audit log
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `sdk/` subtree carries forward primitives from [agent-wallet-sdk](https://github.com/up2itnow0822/agent-wallet-sdk) (MIT). See `SDK-LICENSE`. The wallet/policy/providers/actions/audit subtrees implement the canonical architecture in the spec.
|
|
48
|
+
|
|
49
|
+
## Migration status
|
|
50
|
+
|
|
51
|
+
This plugin is being built incrementally. Tracked phases:
|
|
52
|
+
|
|
53
|
+
- **Phase 0** — interfaces (`WalletBackend`, `CanonicalProvider`, `CanonicalAction`, `PolicyModule`, audit log schema, failure-code unions).
|
|
54
|
+
- **Phase 1** — backend impls + `@elizaos/plugin-wallet` composes legacy `plugin-evm` + `plugin-solana`; migrate call sites to consume `WalletBackend` only.
|
|
55
|
+
- **Phase 2** — provider lifts (13+ providers).
|
|
56
|
+
- **Phase 3** — canonical action implementations.
|
|
57
|
+
- **Phase 4** — approval-queue surface (SSE + decision endpoint + tray + Capacitor bridge).
|
|
58
|
+
- **Phase 5** — EVM + Solana chain implementations live under `src/chains/`; migrate remaining callsites to `WalletBackend` only; expand test coverage.
|
|
59
|
+
|
|
60
|
+
See `docs/architecture/wallet-and-trading.md` §I for the dependency graph.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT. Source code under `src/sdk/` originates from [agent-wallet-sdk](https://github.com/up2itnow0822/agent-wallet-sdk) (MIT, attribution preserved in `SDK-LICENSE`).
|
package/auto-enable.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Auto-enable check for @elizaos/plugin-wallet.
|
|
2
|
+
//
|
|
3
|
+
// Plugin manifest entry-point — referenced by package.json's
|
|
4
|
+
// `elizaos.plugin.autoEnableModule`. Keep this module light: env reads only,
|
|
5
|
+
// no service init, no transitive imports of the full plugin runtime. The
|
|
6
|
+
// auto-enable engine loads dozens of these per boot.
|
|
7
|
+
//
|
|
8
|
+
// EVM detection mirrors `evmAutoEnableReasonFromCapability` in
|
|
9
|
+
// packages/agent/src/services/evm-signing-capability.ts — kept inline so this
|
|
10
|
+
// module has no cross-package import that would pull in agent/runtime code.
|
|
11
|
+
import type { PluginAutoEnableContext } from "@elizaos/core";
|
|
12
|
+
|
|
13
|
+
const PLACEHOLDER_RE =
|
|
14
|
+
/^\[?\s*(REDACTED|PLACEHOLDER|T(?:O)D(?:O)|CHANGEME|EMPTY)\s*]?$/i;
|
|
15
|
+
|
|
16
|
+
function isConcreteValue(value: string | undefined): boolean {
|
|
17
|
+
const trimmed = value?.trim();
|
|
18
|
+
return Boolean(trimmed) && !PLACEHOLDER_RE.test(trimmed as string);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** True when any EVM signing path is available (local key or Steward). */
|
|
22
|
+
function hasEvmSigningPath(env: NodeJS.ProcessEnv): boolean {
|
|
23
|
+
if (isConcreteValue(env.EVM_PRIVATE_KEY)) return true;
|
|
24
|
+
const stewardUrl = env.STEWARD_API_URL?.trim();
|
|
25
|
+
const stewardToken = env.STEWARD_AGENT_TOKEN?.trim();
|
|
26
|
+
return Boolean(stewardUrl && stewardToken);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** True when a Solana private key is set. */
|
|
30
|
+
function hasSolanaSigningPath(env: NodeJS.ProcessEnv): boolean {
|
|
31
|
+
return (
|
|
32
|
+
typeof env.SOLANA_PRIVATE_KEY === "string" &&
|
|
33
|
+
env.SOLANA_PRIVATE_KEY.trim().length > 0
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** True when cloud-provisioned Steward credentials are present. */
|
|
38
|
+
function hasCloudStewardWallet(env: NodeJS.ProcessEnv): boolean {
|
|
39
|
+
return (
|
|
40
|
+
env.ELIZA_CLOUD_PROVISIONED === "1" &&
|
|
41
|
+
Boolean(env.STEWARD_API_URL?.trim()) &&
|
|
42
|
+
Boolean(env.STEWARD_AGENT_TOKEN?.trim())
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Enable plugin-wallet when ANY signing path is available:
|
|
48
|
+
* - EVM (local key or self-hosted/cloud Steward)
|
|
49
|
+
* - Solana local key
|
|
50
|
+
* - cloud-provisioned Steward
|
|
51
|
+
*
|
|
52
|
+
* Honors `ELIZA_AGENT_WALLET_AUTO_ENABLE === "0"` opt-out, and respects an
|
|
53
|
+
* explicit `enabled: false` on any of plugin-wallet's legacy entry names
|
|
54
|
+
* (`wallet`, `agent-wallet`, `evm`, `solana`). The central engine only
|
|
55
|
+
* checks the canonical short id (`wallet`); the legacy aliases need to be
|
|
56
|
+
* honored here.
|
|
57
|
+
*/
|
|
58
|
+
export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
|
|
59
|
+
const { env, config } = ctx;
|
|
60
|
+
|
|
61
|
+
if (env.ELIZA_AGENT_WALLET_AUTO_ENABLE === "0") return false;
|
|
62
|
+
|
|
63
|
+
const entries = (config?.plugins as Record<string, unknown> | undefined)
|
|
64
|
+
?.entries as Record<string, { enabled?: boolean } | undefined> | undefined;
|
|
65
|
+
if (entries) {
|
|
66
|
+
for (const id of ["wallet", "agent-wallet", "evm", "solana"] as const) {
|
|
67
|
+
if (entries[id]?.enabled === false) return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
hasEvmSigningPath(env) ||
|
|
73
|
+
hasSolanaSigningPath(env) ||
|
|
74
|
+
hasCloudStewardWallet(env)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { ILpService, logger } from "@elizaos/core";
|
|
2
|
+
//#region src/lp/services/LpManagementService.ts
|
|
3
|
+
const LP_MANAGEMENT_SERVICE_TYPE = "lp-management";
|
|
4
|
+
var NoMatchingLpProtocolError = class extends Error {
|
|
5
|
+
code = "NO_MATCHING_LP_PROTOCOL";
|
|
6
|
+
constructor(request) {
|
|
7
|
+
const details = [
|
|
8
|
+
request.chain ? `chain=${request.chain}` : void 0,
|
|
9
|
+
request.dex ? `dex=${request.dex}` : void 0,
|
|
10
|
+
request.chainId ? `chainId=${request.chainId}` : void 0
|
|
11
|
+
].filter(Boolean).join(", ");
|
|
12
|
+
super(`No registered LP protocol matches ${details || "the request"}`);
|
|
13
|
+
this.name = "NoMatchingLpProtocolError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function normalizeDex(dex) {
|
|
17
|
+
return dex?.trim().toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
function normalizeChain(chain) {
|
|
20
|
+
return chain?.trim().toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
function protocolKey(chain, dex) {
|
|
23
|
+
return `${normalizeChain(chain)}:${normalizeDex(dex)}`;
|
|
24
|
+
}
|
|
25
|
+
function poolId(pool) {
|
|
26
|
+
if (!pool) return void 0;
|
|
27
|
+
if (typeof pool === "string") return pool;
|
|
28
|
+
return pool.poolAddress || pool.id || pool.address;
|
|
29
|
+
}
|
|
30
|
+
function amountValue(params, key, fallback = "0") {
|
|
31
|
+
const amount = params.amount;
|
|
32
|
+
if (key === "value" && [
|
|
33
|
+
"string",
|
|
34
|
+
"number",
|
|
35
|
+
"bigint"
|
|
36
|
+
].includes(typeof amount)) return String(amount);
|
|
37
|
+
if (amount && typeof amount === "object" && key in amount) {
|
|
38
|
+
const value = amount[key];
|
|
39
|
+
if (value !== void 0 && value !== null) return String(value);
|
|
40
|
+
}
|
|
41
|
+
const nested = params.amounts?.[key];
|
|
42
|
+
if (nested !== void 0 && nested !== null) return String(nested);
|
|
43
|
+
return fallback;
|
|
44
|
+
}
|
|
45
|
+
function bigintAmount(value, fallback = 0n) {
|
|
46
|
+
if (typeof value === "bigint") return value;
|
|
47
|
+
if (typeof value === "number" && Number.isFinite(value)) return BigInt(Math.trunc(value));
|
|
48
|
+
if (typeof value === "string" && value.trim()) return BigInt(value.trim());
|
|
49
|
+
return fallback;
|
|
50
|
+
}
|
|
51
|
+
function unsupported(protocol, operation) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
error: `${operation} is not implemented for ${protocol.dex} on ${protocol.chain}`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
var LpManagementService = class LpManagementService extends ILpService {
|
|
58
|
+
static serviceType = LP_MANAGEMENT_SERVICE_TYPE;
|
|
59
|
+
capabilityDescription = "Aggregates registered DEX liquidity pool protocol providers across chains.";
|
|
60
|
+
protocols = /* @__PURE__ */ new Map();
|
|
61
|
+
static async start(runtime) {
|
|
62
|
+
const service = new LpManagementService(runtime);
|
|
63
|
+
logger.info("[LpManagementService] started");
|
|
64
|
+
return service;
|
|
65
|
+
}
|
|
66
|
+
async stop() {
|
|
67
|
+
this.protocols.clear();
|
|
68
|
+
logger.info("[LpManagementService] stopped");
|
|
69
|
+
}
|
|
70
|
+
getDexName() {
|
|
71
|
+
return "lp-management";
|
|
72
|
+
}
|
|
73
|
+
registerProtocol(provider) {
|
|
74
|
+
const key = protocolKey(provider.chain, provider.dex);
|
|
75
|
+
const normalizedProvider = {
|
|
76
|
+
...provider,
|
|
77
|
+
id: provider.id || key,
|
|
78
|
+
chain: normalizeChain(provider.chain),
|
|
79
|
+
dex: normalizeDex(provider.dex)
|
|
80
|
+
};
|
|
81
|
+
if (this.protocols.has(key)) logger.warn(`[LpManagementService] Replacing LP protocol provider ${key}`);
|
|
82
|
+
this.protocols.set(key, normalizedProvider);
|
|
83
|
+
}
|
|
84
|
+
unregisterProtocol(request) {
|
|
85
|
+
if (!request.chain || !request.dex) return false;
|
|
86
|
+
return this.protocols.delete(protocolKey(request.chain, request.dex));
|
|
87
|
+
}
|
|
88
|
+
listProtocols(request = {}) {
|
|
89
|
+
return this.matchingProtocols(request);
|
|
90
|
+
}
|
|
91
|
+
async listPools(params = {}) {
|
|
92
|
+
const requireMatch = Boolean(params.chain || params.dex || params.chainId);
|
|
93
|
+
const protocols = this.matchingProtocols(params);
|
|
94
|
+
if (protocols.length === 0) {
|
|
95
|
+
if (requireMatch) throw new NoMatchingLpProtocolError(params);
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
return (await Promise.all(protocols.map(async (protocol) => {
|
|
99
|
+
try {
|
|
100
|
+
return await protocol.listPools(params);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
logger.warn(`[LpManagementService] Failed to list pools for ${protocol.chain}:${protocol.dex}`, error instanceof Error ? error.message : String(error));
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}))).flat();
|
|
106
|
+
}
|
|
107
|
+
async openPosition(params) {
|
|
108
|
+
return this.resolveProtocol(params).openPosition(params);
|
|
109
|
+
}
|
|
110
|
+
async closePosition(params) {
|
|
111
|
+
return this.resolveProtocol(params).closePosition(params);
|
|
112
|
+
}
|
|
113
|
+
async repositionPosition(params) {
|
|
114
|
+
const protocol = this.resolveProtocol(params);
|
|
115
|
+
if (!protocol.repositionPosition) return unsupported(protocol, "reposition");
|
|
116
|
+
return protocol.repositionPosition(params);
|
|
117
|
+
}
|
|
118
|
+
async getPosition(params) {
|
|
119
|
+
return this.resolveProtocol(params).getPosition?.(params) ?? null;
|
|
120
|
+
}
|
|
121
|
+
async listPositions(params = {}) {
|
|
122
|
+
const protocols = this.matchingProtocols(params);
|
|
123
|
+
return (await Promise.all(protocols.map((protocol) => protocol.listPositions?.(params) ?? []))).flat();
|
|
124
|
+
}
|
|
125
|
+
async getPools(tokenAMint, tokenBMint) {
|
|
126
|
+
return this.listPools({
|
|
127
|
+
tokenA: tokenAMint,
|
|
128
|
+
tokenB: tokenBMint
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async addLiquidity(params) {
|
|
132
|
+
return this.openPosition({
|
|
133
|
+
chain: params.chain || "solana",
|
|
134
|
+
dex: params.dexName,
|
|
135
|
+
userVault: params.userVault,
|
|
136
|
+
pool: params.poolId,
|
|
137
|
+
amount: {
|
|
138
|
+
tokenA: params.tokenAAmountLamports,
|
|
139
|
+
tokenB: params.tokenBAmountLamports
|
|
140
|
+
},
|
|
141
|
+
range: {
|
|
142
|
+
tickLowerIndex: params.tickLowerIndex,
|
|
143
|
+
tickUpperIndex: params.tickUpperIndex
|
|
144
|
+
},
|
|
145
|
+
slippageBps: params.slippageBps
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async removeLiquidity(params) {
|
|
149
|
+
return this.closePosition({
|
|
150
|
+
chain: params.chain || "solana",
|
|
151
|
+
dex: params.dexName,
|
|
152
|
+
userVault: params.userVault,
|
|
153
|
+
pool: params.poolId,
|
|
154
|
+
amount: { lpToken: params.lpTokenAmountLamports },
|
|
155
|
+
slippageBps: params.slippageBps
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async getLpPositionDetails(userAccountPublicKey, poolOrPositionIdentifier) {
|
|
159
|
+
for (const protocol of this.protocols.values()) {
|
|
160
|
+
if (!protocol.getPosition) continue;
|
|
161
|
+
const position = await protocol.getPosition({
|
|
162
|
+
owner: userAccountPublicKey,
|
|
163
|
+
pool: poolOrPositionIdentifier,
|
|
164
|
+
position: poolOrPositionIdentifier
|
|
165
|
+
});
|
|
166
|
+
if (position) return position;
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
async getMarketDataForPools(poolIds) {
|
|
171
|
+
const marketData = await Promise.all(Array.from(this.protocols.values()).map((protocol) => protocol.getMarketData?.(poolIds) ?? {}));
|
|
172
|
+
return Object.assign({}, ...marketData);
|
|
173
|
+
}
|
|
174
|
+
matchingProtocols(request) {
|
|
175
|
+
const requestedChain = normalizeChain(request.chain);
|
|
176
|
+
const requestedDex = normalizeDex(request.dex);
|
|
177
|
+
return Array.from(this.protocols.values()).filter((protocol) => {
|
|
178
|
+
if (requestedChain && protocol.chain !== requestedChain) return false;
|
|
179
|
+
if (requestedDex && protocol.dex !== requestedDex) return false;
|
|
180
|
+
if (request.chainId !== void 0 && protocol.supportedChainIds?.length && !protocol.supportedChainIds.includes(request.chainId)) return false;
|
|
181
|
+
return protocol.supportsRequest?.(request) ?? true;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
resolveProtocol(request) {
|
|
185
|
+
const matches = this.matchingProtocols(request);
|
|
186
|
+
if (matches.length === 0) throw new NoMatchingLpProtocolError(request);
|
|
187
|
+
if (matches.length > 1) throw new Error(`Multiple LP protocols match this request (${matches.map((protocol) => `${protocol.chain}:${protocol.dex}`).join(", ")}). Specify chain and dex.`);
|
|
188
|
+
return matches[0];
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
async function getLpManagementService(runtime) {
|
|
192
|
+
const existing = runtime.getService(LP_MANAGEMENT_SERVICE_TYPE);
|
|
193
|
+
if (existing) return existing;
|
|
194
|
+
if (typeof runtime.getServiceLoadPromise === "function") return await runtime.getServiceLoadPromise("lp-management") ?? null;
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
async function registerLpProtocolProvider(runtime, provider) {
|
|
198
|
+
const registry = await getLpManagementService(runtime);
|
|
199
|
+
if (!registry) {
|
|
200
|
+
logger.warn(`[LpManagementService] Cannot register ${provider.chain}:${provider.dex}; registry service is unavailable`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
registry.registerProtocol(provider);
|
|
204
|
+
}
|
|
205
|
+
function createSolanaLpProtocolProvider({ dex, label, service }) {
|
|
206
|
+
const provider = {
|
|
207
|
+
id: `solana:${normalizeDex(dex)}`,
|
|
208
|
+
chain: "solana",
|
|
209
|
+
dex: normalizeDex(dex),
|
|
210
|
+
label,
|
|
211
|
+
service,
|
|
212
|
+
supportsRequest: (request) => (!request.chain || normalizeChain(request.chain) === "solana") && (!request.dex || normalizeDex(request.dex) === normalizeDex(dex)),
|
|
213
|
+
listPools: async (params) => {
|
|
214
|
+
if (typeof service.getPools !== "function") return [];
|
|
215
|
+
return service.getPools(params.tokenA, params.tokenB);
|
|
216
|
+
},
|
|
217
|
+
openPosition: async (params) => {
|
|
218
|
+
if (typeof service.addLiquidity !== "function") return unsupported(provider, "open");
|
|
219
|
+
const id = poolId(params.pool);
|
|
220
|
+
if (!id) return {
|
|
221
|
+
success: false,
|
|
222
|
+
error: "Pool is required"
|
|
223
|
+
};
|
|
224
|
+
return service.addLiquidity({
|
|
225
|
+
userVault: params.userVault,
|
|
226
|
+
poolId: id,
|
|
227
|
+
tokenAAmountLamports: amountValue(params, "tokenA", amountValue(params, "value")),
|
|
228
|
+
tokenBAmountLamports: amountValue(params, "tokenB", void 0),
|
|
229
|
+
slippageBps: params.slippageBps ?? 50,
|
|
230
|
+
tickLowerIndex: params.range?.tickLowerIndex ?? params.range?.tickLower,
|
|
231
|
+
tickUpperIndex: params.range?.tickUpperIndex ?? params.range?.tickUpper
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
closePosition: async (params) => {
|
|
235
|
+
if (typeof service.removeLiquidity !== "function") return unsupported(provider, "close");
|
|
236
|
+
const id = poolId(params.pool) || params.position;
|
|
237
|
+
if (!id) return {
|
|
238
|
+
success: false,
|
|
239
|
+
error: "Pool or position is required"
|
|
240
|
+
};
|
|
241
|
+
return service.removeLiquidity({
|
|
242
|
+
userVault: params.userVault,
|
|
243
|
+
poolId: id,
|
|
244
|
+
lpTokenAmountLamports: amountValue(params, "lpToken", amountValue(params, "value")),
|
|
245
|
+
slippageBps: params.slippageBps ?? 50
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
getPosition: async (params) => {
|
|
249
|
+
if (typeof service.getLpPositionDetails !== "function") return null;
|
|
250
|
+
const identifier = params.position || poolId(params.pool);
|
|
251
|
+
if (!params.owner || !identifier) return null;
|
|
252
|
+
return service.getLpPositionDetails(params.owner, identifier);
|
|
253
|
+
},
|
|
254
|
+
getMarketData: async (poolIds) => {
|
|
255
|
+
if (typeof service.getMarketDataForPools !== "function") return {};
|
|
256
|
+
return service.getMarketDataForPools(poolIds);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
if (typeof service.repositionPosition === "function") provider.repositionPosition = (params) => service.repositionPosition(params);
|
|
260
|
+
return provider;
|
|
261
|
+
}
|
|
262
|
+
function createEvmLpProtocolProvider({ dex, label, service }) {
|
|
263
|
+
const supportedChainIds = typeof service.getSupportedChainIds === "function" ? service.getSupportedChainIds() : [];
|
|
264
|
+
const provider = {
|
|
265
|
+
id: `evm:${normalizeDex(dex)}`,
|
|
266
|
+
chain: "evm",
|
|
267
|
+
dex: normalizeDex(dex),
|
|
268
|
+
label,
|
|
269
|
+
service,
|
|
270
|
+
supportedChainIds,
|
|
271
|
+
supportsRequest: (request) => {
|
|
272
|
+
if (request.chain && normalizeChain(request.chain) !== "evm") return false;
|
|
273
|
+
if (request.dex && normalizeDex(request.dex) !== normalizeDex(dex)) return false;
|
|
274
|
+
if (request.chainId !== void 0 && supportedChainIds.length > 0) return supportedChainIds.includes(request.chainId);
|
|
275
|
+
return true;
|
|
276
|
+
},
|
|
277
|
+
listPools: async (params) => {
|
|
278
|
+
const chainIds = params.chainId ? [params.chainId] : supportedChainIds;
|
|
279
|
+
return (await Promise.all(chainIds.map((chainId) => service.getPools(chainId, params.tokenA, params.tokenB, params.feeTier)))).flat();
|
|
280
|
+
},
|
|
281
|
+
openPosition: async (params) => {
|
|
282
|
+
if (!params.wallet) return {
|
|
283
|
+
success: false,
|
|
284
|
+
error: "EVM wallet is required"
|
|
285
|
+
};
|
|
286
|
+
if (!params.chainId) return {
|
|
287
|
+
success: false,
|
|
288
|
+
error: "EVM chainId is required"
|
|
289
|
+
};
|
|
290
|
+
const id = poolId(params.pool);
|
|
291
|
+
if (!id) return {
|
|
292
|
+
success: false,
|
|
293
|
+
error: "Pool address is required"
|
|
294
|
+
};
|
|
295
|
+
const evmParams = {
|
|
296
|
+
wallet: params.wallet,
|
|
297
|
+
chainId: params.chainId,
|
|
298
|
+
poolAddress: id,
|
|
299
|
+
tokenAAmount: bigintAmount(amountValue(params, "tokenA", amountValue(params, "value"))),
|
|
300
|
+
tokenBAmount: bigintAmount(amountValue(params, "tokenB", void 0), void 0),
|
|
301
|
+
slippageBps: params.slippageBps ?? 50,
|
|
302
|
+
tickLower: params.range?.tickLower ?? params.range?.tickLowerIndex,
|
|
303
|
+
tickUpper: params.range?.tickUpper ?? params.range?.tickUpperIndex,
|
|
304
|
+
deadline: params.deadline
|
|
305
|
+
};
|
|
306
|
+
return service.addLiquidity(evmParams);
|
|
307
|
+
},
|
|
308
|
+
closePosition: async (params) => {
|
|
309
|
+
if (!params.wallet) return {
|
|
310
|
+
success: false,
|
|
311
|
+
error: "EVM wallet is required"
|
|
312
|
+
};
|
|
313
|
+
if (!params.chainId) return {
|
|
314
|
+
success: false,
|
|
315
|
+
error: "EVM chainId is required"
|
|
316
|
+
};
|
|
317
|
+
const id = poolId(params.pool);
|
|
318
|
+
if (!id) return {
|
|
319
|
+
success: false,
|
|
320
|
+
error: "Pool address is required"
|
|
321
|
+
};
|
|
322
|
+
const evmParams = {
|
|
323
|
+
wallet: params.wallet,
|
|
324
|
+
chainId: params.chainId,
|
|
325
|
+
poolAddress: id,
|
|
326
|
+
tokenId: params.tokenId !== void 0 ? bigintAmount(params.tokenId) : params.position ? bigintAmount(params.position) : void 0,
|
|
327
|
+
lpTokenAmount: bigintAmount(amountValue(params, "lpToken", amountValue(params, "value")), void 0),
|
|
328
|
+
percentageToRemove: typeof params.amount === "object" ? params.amount?.percentage : void 0,
|
|
329
|
+
slippageBps: params.slippageBps ?? 50,
|
|
330
|
+
deadline: params.deadline
|
|
331
|
+
};
|
|
332
|
+
return service.removeLiquidity(evmParams);
|
|
333
|
+
},
|
|
334
|
+
getPosition: async (params) => {
|
|
335
|
+
if (!params.owner || !params.chainId) return null;
|
|
336
|
+
const id = poolId(params.pool);
|
|
337
|
+
if (!id) return null;
|
|
338
|
+
return service.getPositionDetails(params.chainId, params.owner, id, params.tokenId !== void 0 ? bigintAmount(params.tokenId) : params.position ? bigintAmount(params.position) : void 0);
|
|
339
|
+
},
|
|
340
|
+
listPositions: async (params) => {
|
|
341
|
+
if (!params.owner || !params.chainId) return [];
|
|
342
|
+
return service.getAllPositions(params.chainId, params.owner);
|
|
343
|
+
},
|
|
344
|
+
getMarketData: async (poolIds) => {
|
|
345
|
+
if (typeof service.getMarketData !== "function") return {};
|
|
346
|
+
return service.getMarketData(poolIds);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
if (typeof service.repositionPosition === "function") provider.repositionPosition = (params) => service.repositionPosition(params);
|
|
350
|
+
return provider;
|
|
351
|
+
}
|
|
352
|
+
//#endregion
|
|
353
|
+
export { getLpManagementService as a, createSolanaLpProtocolProvider as i, NoMatchingLpProtocolError as n, registerLpProtocolProvider as o, createEvmLpProtocolProvider as r, LpManagementService as t };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { a as getLpManagementService, i as createSolanaLpProtocolProvider } from "./LpManagementService-BWrQ5-cO.mjs";
|
|
2
|
+
import { Service } from "@elizaos/core";
|
|
3
|
+
//#region src/lp/services/__tests__/MockLpService.ts
|
|
4
|
+
var MockLpService = class extends Service {
|
|
5
|
+
capabilityDescription = "Test-only LP service for registry scenarios.";
|
|
6
|
+
positions = /* @__PURE__ */ new Map();
|
|
7
|
+
constructor(runtime, dexName = "mock-dex") {
|
|
8
|
+
super(runtime);
|
|
9
|
+
this.dexName = dexName;
|
|
10
|
+
}
|
|
11
|
+
getDexName() {
|
|
12
|
+
return this.dexName;
|
|
13
|
+
}
|
|
14
|
+
async getPools(tokenAMint, tokenBMint) {
|
|
15
|
+
const pools = [{
|
|
16
|
+
id: `${this.dexName}-sol-usdc`,
|
|
17
|
+
displayName: `${this.dexName} SOL/USDC`,
|
|
18
|
+
dex: this.dexName,
|
|
19
|
+
tokenA: {
|
|
20
|
+
mint: "So11111111111111111111111111111111111111112",
|
|
21
|
+
symbol: "SOL",
|
|
22
|
+
decimals: 9
|
|
23
|
+
},
|
|
24
|
+
tokenB: {
|
|
25
|
+
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
26
|
+
symbol: "USDC",
|
|
27
|
+
decimals: 6
|
|
28
|
+
},
|
|
29
|
+
apr: 12,
|
|
30
|
+
tvl: 1e6
|
|
31
|
+
}];
|
|
32
|
+
if (!tokenAMint && !tokenBMint) return pools;
|
|
33
|
+
return pools.filter((pool) => {
|
|
34
|
+
const mints = [pool.tokenA?.mint, pool.tokenB?.mint];
|
|
35
|
+
return (!tokenAMint || mints.includes(tokenAMint)) && (!tokenBMint || mints.includes(tokenBMint));
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async addLiquidity(config) {
|
|
39
|
+
const owner = config.userVault?.publicKey?.toBase58?.() || "test-owner";
|
|
40
|
+
const position = {
|
|
41
|
+
poolId: config.poolId,
|
|
42
|
+
dex: this.dexName,
|
|
43
|
+
lpTokenBalance: {
|
|
44
|
+
address: `lp-${config.poolId}`,
|
|
45
|
+
balance: "1000",
|
|
46
|
+
decimals: 6,
|
|
47
|
+
symbol: "LP"
|
|
48
|
+
},
|
|
49
|
+
underlyingTokens: [],
|
|
50
|
+
accruedFees: [],
|
|
51
|
+
rewards: [],
|
|
52
|
+
valueUsd: 100
|
|
53
|
+
};
|
|
54
|
+
this.positions.set(owner, [...this.positions.get(owner) || [], position]);
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
transactionId: `mock-open-${this.dexName}`,
|
|
58
|
+
data: { poolId: config.poolId }
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async removeLiquidity(config) {
|
|
62
|
+
const owner = config.userVault?.publicKey?.toBase58?.() || "test-owner";
|
|
63
|
+
this.positions.set(owner, (this.positions.get(owner) || []).filter((position) => position.poolId !== config.poolId));
|
|
64
|
+
return {
|
|
65
|
+
success: true,
|
|
66
|
+
transactionId: `mock-close-${this.dexName}`,
|
|
67
|
+
data: { poolId: config.poolId }
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async getLpPositionDetails(owner, poolOrPositionIdentifier) {
|
|
71
|
+
return (this.positions.get(owner) || []).find((position) => position.poolId === poolOrPositionIdentifier) || null;
|
|
72
|
+
}
|
|
73
|
+
async getMarketDataForPools(poolIds) {
|
|
74
|
+
return Object.fromEntries(poolIds.map((poolId) => [poolId, {
|
|
75
|
+
apr: 12,
|
|
76
|
+
tvl: 1e6
|
|
77
|
+
}]));
|
|
78
|
+
}
|
|
79
|
+
async start() {}
|
|
80
|
+
async stop() {}
|
|
81
|
+
};
|
|
82
|
+
async function registerMockDexServices(runtime) {
|
|
83
|
+
const registry = await getLpManagementService(runtime);
|
|
84
|
+
if (!registry) return;
|
|
85
|
+
for (const dex of [
|
|
86
|
+
"raydium",
|
|
87
|
+
"orca",
|
|
88
|
+
"meteora"
|
|
89
|
+
]) {
|
|
90
|
+
const service = new MockLpService(runtime, dex);
|
|
91
|
+
registry.registerProtocol(createSolanaLpProtocolProvider({
|
|
92
|
+
dex,
|
|
93
|
+
label: dex,
|
|
94
|
+
service
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
export { registerMockDexServices };
|