@elizaos/plugin-dummy-services 1.0.8
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/dist/index.d.ts +67 -0
- package/dist/index.js +667 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shaw Walters and elizaOS Contributors
|
|
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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Service, ITokenDataService, IAgentRuntime, TokenData, ILpService, PoolInfo, TransactionResult, TokenBalance, LpPositionDetails, IWalletService, AgentRuntime, WalletPortfolio, Plugin } from '@elizaos/core';
|
|
2
|
+
|
|
3
|
+
declare class DummyTokenDataService extends Service implements ITokenDataService {
|
|
4
|
+
readonly serviceName = "dummy-token-data";
|
|
5
|
+
static readonly serviceType: "token_data";
|
|
6
|
+
readonly capabilityDescription = "Provides dummy token data for testing and development purposes.";
|
|
7
|
+
constructor(runtime?: IAgentRuntime);
|
|
8
|
+
private generateDummyToken;
|
|
9
|
+
getTokenDetails(address: string, chain: string): Promise<TokenData | null>;
|
|
10
|
+
getTrendingTokens(chain?: string, limit?: number, _timePeriod?: string): Promise<TokenData[]>;
|
|
11
|
+
searchTokens(query: string, chain?: string, limit?: number): Promise<TokenData[]>;
|
|
12
|
+
getTokensByAddresses(addresses: string[], chain: string): Promise<TokenData[]>;
|
|
13
|
+
static start(runtime: IAgentRuntime): Promise<DummyTokenDataService>;
|
|
14
|
+
static stop(runtime: IAgentRuntime): Promise<void>;
|
|
15
|
+
start(): Promise<void>;
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare class DummyLpService extends ILpService {
|
|
20
|
+
getDexName(): string;
|
|
21
|
+
static start(runtime: IAgentRuntime): Promise<DummyLpService>;
|
|
22
|
+
static stop(runtime: IAgentRuntime): Promise<void>;
|
|
23
|
+
start(runtime: IAgentRuntime): Promise<void>;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
getPools(tokenAMint?: string, tokenBMint?: string): Promise<PoolInfo[]>;
|
|
26
|
+
addLiquidity(params: {
|
|
27
|
+
userVault: any;
|
|
28
|
+
poolId: string;
|
|
29
|
+
tokenAAmountLamports: string;
|
|
30
|
+
tokenBAmountLamports?: string;
|
|
31
|
+
slippageBps: number;
|
|
32
|
+
}): Promise<TransactionResult & {
|
|
33
|
+
lpTokensReceived?: TokenBalance;
|
|
34
|
+
}>;
|
|
35
|
+
removeLiquidity(params: {
|
|
36
|
+
userVault: any;
|
|
37
|
+
poolId: string;
|
|
38
|
+
lpTokenAmountLamports: string;
|
|
39
|
+
slippageBps: number;
|
|
40
|
+
}): Promise<TransactionResult & {
|
|
41
|
+
tokensReceived?: TokenBalance[];
|
|
42
|
+
}>;
|
|
43
|
+
getLpPositionDetails(userAccountPublicKey: string, poolOrPositionIdentifier: string): Promise<LpPositionDetails | null>;
|
|
44
|
+
getMarketDataForPools(poolIds: string[]): Promise<Record<string, Partial<PoolInfo>>>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
declare class DummyWalletService extends Service implements IWalletService {
|
|
48
|
+
static readonly serviceType: "wallet";
|
|
49
|
+
readonly capabilityDescription = "Provides standardized access to wallet balances and portfolios.";
|
|
50
|
+
private balances;
|
|
51
|
+
private positions;
|
|
52
|
+
private quoteAssetSymbol;
|
|
53
|
+
constructor(runtime: AgentRuntime);
|
|
54
|
+
transferSol(from: any, to: any, lamports: number): Promise<string>;
|
|
55
|
+
static start(runtime: AgentRuntime): Promise<DummyWalletService>;
|
|
56
|
+
start(): Promise<void>;
|
|
57
|
+
stop(): Promise<void>;
|
|
58
|
+
addFunds(assetSymbolOrAddress: string, amount: number, _walletAddress?: string): Promise<void>;
|
|
59
|
+
setPortfolioHolding(assetSymbolOrAddress: string, quantity: number, averagePrice: number, _walletAddress?: string): Promise<void>;
|
|
60
|
+
resetWallet(initialCashAmount: number, cashAssetSymbol?: string, _walletAddress?: string): Promise<void>;
|
|
61
|
+
getBalance(assetSymbolOrAddress: string, _walletAddress?: string): Promise<number>;
|
|
62
|
+
getPortfolio(_walletAddress?: string): Promise<WalletPortfolio>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
declare const dummyServicesPlugin: Plugin;
|
|
66
|
+
|
|
67
|
+
export { DummyLpService, DummyTokenDataService, DummyWalletService, dummyServicesPlugin as default, dummyServicesPlugin };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
// src/tokenData/service.ts
|
|
2
|
+
import {
|
|
3
|
+
Service,
|
|
4
|
+
ServiceType,
|
|
5
|
+
logger
|
|
6
|
+
} from "@elizaos/core";
|
|
7
|
+
import { v4 as uuidv4 } from "uuid";
|
|
8
|
+
var DummyTokenDataService = class _DummyTokenDataService extends Service {
|
|
9
|
+
serviceName = "dummy-token-data";
|
|
10
|
+
static serviceType = ServiceType.TOKEN_DATA;
|
|
11
|
+
capabilityDescription = "Provides dummy token data for testing and development purposes.";
|
|
12
|
+
constructor(runtime) {
|
|
13
|
+
super(runtime);
|
|
14
|
+
logger.info("DummyTokenDataService initialized");
|
|
15
|
+
}
|
|
16
|
+
generateDummyToken(chain, address, query) {
|
|
17
|
+
const randomAddress = address || `0x${uuidv4().replace(/-/g, "")}`;
|
|
18
|
+
const symbol = query ? query.toUpperCase() : randomAddress.substring(2, 6).toUpperCase();
|
|
19
|
+
return {
|
|
20
|
+
id: `${chain}:${randomAddress}`,
|
|
21
|
+
symbol,
|
|
22
|
+
name: `Dummy Token ${symbol}`,
|
|
23
|
+
address: randomAddress,
|
|
24
|
+
chain,
|
|
25
|
+
sourceProvider: "dummy",
|
|
26
|
+
price: Math.random() * 100,
|
|
27
|
+
priceChange24hPercent: (Math.random() - 0.5) * 20,
|
|
28
|
+
volume24hUSD: Math.random() * 1e6,
|
|
29
|
+
marketCapUSD: Math.random() * 1e8,
|
|
30
|
+
liquidity: Math.random() * 5e5,
|
|
31
|
+
holders: Math.floor(Math.random() * 1e4),
|
|
32
|
+
logoURI: "https://via.placeholder.com/150",
|
|
33
|
+
decimals: 18,
|
|
34
|
+
lastUpdatedAt: /* @__PURE__ */ new Date(),
|
|
35
|
+
raw: {
|
|
36
|
+
dummyData: true
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async getTokenDetails(address, chain) {
|
|
41
|
+
logger.debug(`DummyTokenDataService: getTokenDetails for ${address} on ${chain}`);
|
|
42
|
+
return this.generateDummyToken(chain, address);
|
|
43
|
+
}
|
|
44
|
+
async getTrendingTokens(chain = "solana", limit = 10, _timePeriod = "24h") {
|
|
45
|
+
logger.debug(`DummyTokenDataService: getTrendingTokens on ${chain}`);
|
|
46
|
+
return Array.from({ length: limit }, () => this.generateDummyToken(chain));
|
|
47
|
+
}
|
|
48
|
+
async searchTokens(query, chain = "solana", limit = 5) {
|
|
49
|
+
logger.debug(`DummyTokenDataService: searchTokens for "${query}" on ${chain}`);
|
|
50
|
+
return Array.from({ length: limit }, () => this.generateDummyToken(chain, void 0, query));
|
|
51
|
+
}
|
|
52
|
+
async getTokensByAddresses(addresses, chain) {
|
|
53
|
+
logger.debug(`DummyTokenDataService: getTokensByAddresses on ${chain} for`, addresses);
|
|
54
|
+
return addresses.map((addr) => this.generateDummyToken(chain, addr));
|
|
55
|
+
}
|
|
56
|
+
static async start(runtime) {
|
|
57
|
+
const service = new _DummyTokenDataService(runtime);
|
|
58
|
+
return service;
|
|
59
|
+
}
|
|
60
|
+
static async stop(runtime) {
|
|
61
|
+
const service = runtime.getService(_DummyTokenDataService.serviceType);
|
|
62
|
+
if (service) {
|
|
63
|
+
await service.stop();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async start() {
|
|
67
|
+
logger.info(`[${this.serviceName}] Service started.`);
|
|
68
|
+
}
|
|
69
|
+
async stop() {
|
|
70
|
+
logger.info(`[${this.serviceName}] Service stopped.`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/lp/service.ts
|
|
75
|
+
import {
|
|
76
|
+
ILpService
|
|
77
|
+
} from "@elizaos/core";
|
|
78
|
+
var DummyLpService = class _DummyLpService extends ILpService {
|
|
79
|
+
getDexName() {
|
|
80
|
+
return "dummy";
|
|
81
|
+
}
|
|
82
|
+
static async start(runtime) {
|
|
83
|
+
const service = new _DummyLpService(runtime);
|
|
84
|
+
return service;
|
|
85
|
+
}
|
|
86
|
+
static async stop(runtime) {
|
|
87
|
+
const service = runtime.getService(_DummyLpService.serviceType);
|
|
88
|
+
if (service) {
|
|
89
|
+
await service.stop();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async start(runtime) {
|
|
93
|
+
console.log("[DummyLpService] started.");
|
|
94
|
+
}
|
|
95
|
+
async stop() {
|
|
96
|
+
console.log("[DummyLpService] stopped.");
|
|
97
|
+
}
|
|
98
|
+
async getPools(tokenAMint, tokenBMint) {
|
|
99
|
+
console.log(`[DummyLpService] getPools called with: ${tokenAMint}, ${tokenBMint}`);
|
|
100
|
+
const SOL_MINT = "So11111111111111111111111111111111111111112";
|
|
101
|
+
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a";
|
|
102
|
+
const pools = [
|
|
103
|
+
{
|
|
104
|
+
id: "dummy-pool-1",
|
|
105
|
+
dex: "dummy",
|
|
106
|
+
tokenA: { mint: SOL_MINT, symbol: "SOL", name: "Solana", decimals: 9 },
|
|
107
|
+
tokenB: { mint: USDC_MINT, symbol: "USDC", name: "USD Coin", decimals: 6 },
|
|
108
|
+
apr: 0.12,
|
|
109
|
+
apy: 0.125,
|
|
110
|
+
tvl: 123456789e-2,
|
|
111
|
+
fee: 25e-4,
|
|
112
|
+
metadata: { name: "SOL/USDC Dummy Pool", isStable: false }
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "dummy-stable-pool-2",
|
|
116
|
+
dex: "dummy",
|
|
117
|
+
tokenA: { mint: USDC_MINT, symbol: "USDC", name: "USD Coin", decimals: 6 },
|
|
118
|
+
tokenB: {
|
|
119
|
+
mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
120
|
+
symbol: "USDT",
|
|
121
|
+
name: "Tether",
|
|
122
|
+
decimals: 6
|
|
123
|
+
},
|
|
124
|
+
apr: 0.08,
|
|
125
|
+
apy: 0.082,
|
|
126
|
+
tvl: 25e5,
|
|
127
|
+
fee: 5e-4,
|
|
128
|
+
metadata: { name: "USDC/USDT Dummy Stable Pool", isStable: true }
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
return pools.filter((p) => {
|
|
132
|
+
if (!tokenAMint && !tokenBMint) return true;
|
|
133
|
+
const hasTokenA = p.tokenA.mint === tokenAMint || p.tokenB.mint === tokenAMint;
|
|
134
|
+
const hasTokenB = p.tokenA.mint === tokenBMint || p.tokenB.mint === tokenBMint;
|
|
135
|
+
if (tokenAMint && tokenBMint) return hasTokenA && hasTokenB;
|
|
136
|
+
if (tokenAMint) return hasTokenA;
|
|
137
|
+
if (tokenBMint) return hasTokenB;
|
|
138
|
+
return false;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async addLiquidity(params) {
|
|
142
|
+
console.log(`[DummyLpService] addLiquidity called for pool: ${params.poolId}`);
|
|
143
|
+
return {
|
|
144
|
+
success: true,
|
|
145
|
+
transactionId: `dummy-tx-${Date.now()}`,
|
|
146
|
+
lpTokensReceived: {
|
|
147
|
+
address: `dummy-lp-mint-${params.poolId}`,
|
|
148
|
+
balance: "100000000",
|
|
149
|
+
// 100 LP tokens
|
|
150
|
+
symbol: "DUMMY-LP",
|
|
151
|
+
uiAmount: 100,
|
|
152
|
+
decimals: 6,
|
|
153
|
+
name: `Dummy LP Token for ${params.poolId}`
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
async removeLiquidity(params) {
|
|
158
|
+
console.log(`[DummyLpService] removeLiquidity called for pool: ${params.poolId}`);
|
|
159
|
+
return {
|
|
160
|
+
success: true,
|
|
161
|
+
transactionId: `dummy-tx-${Date.now()}`,
|
|
162
|
+
tokensReceived: [
|
|
163
|
+
{
|
|
164
|
+
address: "So11111111111111111111111111111111111111112",
|
|
165
|
+
balance: "500000000",
|
|
166
|
+
symbol: "SOL",
|
|
167
|
+
uiAmount: 0.5,
|
|
168
|
+
decimals: 9,
|
|
169
|
+
name: "Solana"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a",
|
|
173
|
+
balance: "500000000",
|
|
174
|
+
symbol: "USDC",
|
|
175
|
+
uiAmount: 500,
|
|
176
|
+
decimals: 6,
|
|
177
|
+
name: "USD Coin"
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async getLpPositionDetails(userAccountPublicKey, poolOrPositionIdentifier) {
|
|
183
|
+
console.log(
|
|
184
|
+
`[DummyLpService] getLpPositionDetails called for user: ${userAccountPublicKey}, identifier: ${poolOrPositionIdentifier}`
|
|
185
|
+
);
|
|
186
|
+
return {
|
|
187
|
+
poolId: "dummy-pool-1",
|
|
188
|
+
// Assuming the identifier maps back to a known pool
|
|
189
|
+
dex: "dummy",
|
|
190
|
+
lpTokenBalance: {
|
|
191
|
+
address: poolOrPositionIdentifier,
|
|
192
|
+
balance: "100000000",
|
|
193
|
+
symbol: "DUMMY-LP",
|
|
194
|
+
uiAmount: 100,
|
|
195
|
+
decimals: 6,
|
|
196
|
+
name: `Dummy LP Token`
|
|
197
|
+
},
|
|
198
|
+
underlyingTokens: [
|
|
199
|
+
{
|
|
200
|
+
address: "So11111111111111111111111111111111111111112",
|
|
201
|
+
balance: "500000000",
|
|
202
|
+
symbol: "SOL",
|
|
203
|
+
uiAmount: 0.5,
|
|
204
|
+
decimals: 9,
|
|
205
|
+
name: "Solana"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a",
|
|
209
|
+
balance: "500000000",
|
|
210
|
+
symbol: "USDC",
|
|
211
|
+
uiAmount: 500,
|
|
212
|
+
decimals: 6,
|
|
213
|
+
name: "USD Coin"
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
valueUsd: 1e3,
|
|
217
|
+
metadata: { apr: 0.12 }
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async getMarketDataForPools(poolIds) {
|
|
221
|
+
console.log(`[DummyLpService] getMarketDataForPools called for pools: ${poolIds.join(", ")}`);
|
|
222
|
+
const results = {};
|
|
223
|
+
for (const poolId of poolIds) {
|
|
224
|
+
results[poolId] = {
|
|
225
|
+
apy: Math.random() * 0.2,
|
|
226
|
+
tvl: Math.random() * 1e6,
|
|
227
|
+
apr: Math.random() * 0.18
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return results;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/wallet/service.ts
|
|
235
|
+
import { Service as Service3, ServiceType as ServiceType2 } from "@elizaos/core";
|
|
236
|
+
var DEFAULT_QUOTE_ASSET = "USDC";
|
|
237
|
+
var DummyWalletService = class _DummyWalletService extends Service3 {
|
|
238
|
+
static serviceType = ServiceType2.WALLET;
|
|
239
|
+
capabilityDescription = "Provides standardized access to wallet balances and portfolios.";
|
|
240
|
+
balances;
|
|
241
|
+
// assetSymbolOrAddress -> quantity
|
|
242
|
+
positions;
|
|
243
|
+
// assetSymbolOrAddress -> details for owned non-quote assets
|
|
244
|
+
quoteAssetSymbol;
|
|
245
|
+
constructor(runtime) {
|
|
246
|
+
super(runtime);
|
|
247
|
+
this.balances = /* @__PURE__ */ new Map();
|
|
248
|
+
this.positions = /* @__PURE__ */ new Map();
|
|
249
|
+
this.quoteAssetSymbol = DEFAULT_QUOTE_ASSET;
|
|
250
|
+
this.resetWallet(1e4, DEFAULT_QUOTE_ASSET);
|
|
251
|
+
}
|
|
252
|
+
async transferSol(from, to, lamports) {
|
|
253
|
+
console.log(
|
|
254
|
+
`[${_DummyWalletService.serviceType}] Mock transfer: ${lamports} lamports from ${from} to ${to}`
|
|
255
|
+
);
|
|
256
|
+
const solSymbol = "SOL";
|
|
257
|
+
const solAmount = lamports / 1e9;
|
|
258
|
+
const currentBalance = this.balances.get(solSymbol) || 0;
|
|
259
|
+
if (currentBalance < solAmount) {
|
|
260
|
+
throw new Error(`Insufficient SOL balance. Have ${currentBalance}, need ${solAmount}`);
|
|
261
|
+
}
|
|
262
|
+
this.balances.set(solSymbol, currentBalance - solAmount);
|
|
263
|
+
return `dummy-tx-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
264
|
+
}
|
|
265
|
+
static async start(runtime) {
|
|
266
|
+
console.log(`[${_DummyWalletService.serviceType}] static start called - creating instance.`);
|
|
267
|
+
const instance = new _DummyWalletService(runtime);
|
|
268
|
+
return instance;
|
|
269
|
+
}
|
|
270
|
+
async start() {
|
|
271
|
+
console.log(
|
|
272
|
+
`[${_DummyWalletService.serviceType}] instance start called. Initialized with ${this.balances.get(this.quoteAssetSymbol)} ${this.quoteAssetSymbol}.`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
async stop() {
|
|
276
|
+
console.log(`[${_DummyWalletService.serviceType}] instance stop called. Balances reset.`);
|
|
277
|
+
this.balances.clear();
|
|
278
|
+
this.positions.clear();
|
|
279
|
+
}
|
|
280
|
+
async addFunds(assetSymbolOrAddress, amount, _walletAddress) {
|
|
281
|
+
const currentBalance = this.balances.get(assetSymbolOrAddress) || 0;
|
|
282
|
+
this.balances.set(assetSymbolOrAddress, currentBalance + amount);
|
|
283
|
+
console.log(
|
|
284
|
+
`[${_DummyWalletService.serviceType}] Added ${amount} ${assetSymbolOrAddress}. New balance: ${this.balances.get(assetSymbolOrAddress)}`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
async setPortfolioHolding(assetSymbolOrAddress, quantity, averagePrice, _walletAddress) {
|
|
288
|
+
if (assetSymbolOrAddress === this.quoteAssetSymbol) {
|
|
289
|
+
console.warn(
|
|
290
|
+
`[${_DummyWalletService.serviceType}] Cannot set portfolio holding for quote asset directly, use addFunds.`
|
|
291
|
+
);
|
|
292
|
+
return this.addFunds(assetSymbolOrAddress, quantity * averagePrice);
|
|
293
|
+
}
|
|
294
|
+
this.balances.set(assetSymbolOrAddress, quantity);
|
|
295
|
+
this.positions.set(assetSymbolOrAddress, {
|
|
296
|
+
quantity,
|
|
297
|
+
averagePrice,
|
|
298
|
+
lots: [{ price: averagePrice, quantity, timestamp: Date.now() }]
|
|
299
|
+
// Create a single lot for simplicity
|
|
300
|
+
});
|
|
301
|
+
console.log(
|
|
302
|
+
`[${_DummyWalletService.serviceType}] Set holding for ${assetSymbolOrAddress}: ${quantity} @ ${averagePrice}`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
async resetWallet(initialCashAmount, cashAssetSymbol = DEFAULT_QUOTE_ASSET, _walletAddress) {
|
|
306
|
+
this.balances.clear();
|
|
307
|
+
this.positions.clear();
|
|
308
|
+
this.quoteAssetSymbol = cashAssetSymbol;
|
|
309
|
+
this.balances.set(this.quoteAssetSymbol, initialCashAmount);
|
|
310
|
+
console.log(
|
|
311
|
+
`[${_DummyWalletService.serviceType}] Wallet reset. Cash: ${initialCashAmount} ${this.quoteAssetSymbol}`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
async getBalance(assetSymbolOrAddress, _walletAddress) {
|
|
315
|
+
return this.balances.get(assetSymbolOrAddress) || 0;
|
|
316
|
+
}
|
|
317
|
+
async getPortfolio(_walletAddress) {
|
|
318
|
+
const assets = [];
|
|
319
|
+
let totalValueUsd = 0;
|
|
320
|
+
for (const [symbol, balance] of this.balances) {
|
|
321
|
+
const positionDetail = this.positions.get(symbol);
|
|
322
|
+
const isQuoteAsset = symbol === this.quoteAssetSymbol;
|
|
323
|
+
const averagePrice = positionDetail?.averagePrice || (isQuoteAsset ? 1 : 0);
|
|
324
|
+
const value = isQuoteAsset ? balance : positionDetail ? balance * positionDetail.averagePrice : 0;
|
|
325
|
+
assets.push({
|
|
326
|
+
address: symbol,
|
|
327
|
+
// Using symbol as address for dummy wallet
|
|
328
|
+
symbol,
|
|
329
|
+
balance: balance.toString(),
|
|
330
|
+
decimals: isQuoteAsset ? 6 : 9,
|
|
331
|
+
// Default decimals
|
|
332
|
+
quantity: balance,
|
|
333
|
+
averagePrice,
|
|
334
|
+
currentPrice: void 0,
|
|
335
|
+
value,
|
|
336
|
+
assetAddress: symbol
|
|
337
|
+
});
|
|
338
|
+
totalValueUsd += value;
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
totalValueUsd,
|
|
342
|
+
assets
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/e2e/scenarios.ts
|
|
348
|
+
import { ILpService as ILpService2, ServiceType as ServiceType3 } from "@elizaos/core";
|
|
349
|
+
import { strict as assert } from "assert";
|
|
350
|
+
var dummyServicesScenariosSuite = {
|
|
351
|
+
name: "Dummy Services Plugin E2E Scenarios",
|
|
352
|
+
tests: [
|
|
353
|
+
{
|
|
354
|
+
name: "Scenario 1: Should initialize dummy services and verify they are available",
|
|
355
|
+
fn: async (runtime) => {
|
|
356
|
+
console.log("Testing dummy services initialization...");
|
|
357
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
358
|
+
assert(lpService, "DummyLpService not found in runtime");
|
|
359
|
+
assert.equal(
|
|
360
|
+
lpService.getDexName(),
|
|
361
|
+
"dummy",
|
|
362
|
+
"DummyLpService should have correct DEX name"
|
|
363
|
+
);
|
|
364
|
+
const tokenDataService = runtime.getService(
|
|
365
|
+
DummyTokenDataService.serviceType
|
|
366
|
+
);
|
|
367
|
+
assert(tokenDataService, "DummyTokenDataService not found in runtime");
|
|
368
|
+
console.log("Successfully verified both dummy services are initialized and available.");
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
name: "Scenario 2: Should fetch pools from DummyLpService",
|
|
373
|
+
fn: async (runtime) => {
|
|
374
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
375
|
+
assert(lpService, "DummyLpService not found");
|
|
376
|
+
console.log("Fetching all pools from DummyLpService...");
|
|
377
|
+
const allPools = await lpService.getPools();
|
|
378
|
+
assert(Array.isArray(allPools), "getPools should return an array");
|
|
379
|
+
assert.equal(allPools.length, 2, "Should return 2 dummy pools");
|
|
380
|
+
const pool1 = allPools.find((p) => p.id === "dummy-pool-1");
|
|
381
|
+
assert(pool1, "dummy-pool-1 should exist");
|
|
382
|
+
assert.equal(pool1.dex, "dummy", "Pool should have correct DEX");
|
|
383
|
+
assert.equal(pool1.tokenA.symbol, "SOL", "Pool should have SOL as tokenA");
|
|
384
|
+
assert.equal(pool1.tokenB.symbol, "USDC", "Pool should have USDC as tokenB");
|
|
385
|
+
assert.equal(pool1.tvl, 123456789e-2, "Pool should have correct TVL");
|
|
386
|
+
console.log("Successfully fetched and verified pool data.");
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
name: "Scenario 3: Should filter pools by token mint",
|
|
391
|
+
fn: async (runtime) => {
|
|
392
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
393
|
+
assert(lpService, "DummyLpService not found");
|
|
394
|
+
const solMint = "So11111111111111111111111111111111111111112";
|
|
395
|
+
console.log(`Filtering pools containing SOL (${solMint})...`);
|
|
396
|
+
const solPools = await lpService.getPools(solMint);
|
|
397
|
+
assert(Array.isArray(solPools), "getPools with filter should return an array");
|
|
398
|
+
assert(solPools.length > 0, "Should find pools containing SOL");
|
|
399
|
+
solPools.forEach((pool) => {
|
|
400
|
+
const containsSol = pool.tokenA.mint === solMint || pool.tokenB.mint === solMint;
|
|
401
|
+
assert(containsSol, `Pool ${pool.id} should contain SOL`);
|
|
402
|
+
});
|
|
403
|
+
console.log(`Found ${solPools.length} pools containing SOL.`);
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: "Scenario 4: Should add liquidity to a dummy pool",
|
|
408
|
+
fn: async (runtime) => {
|
|
409
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
410
|
+
assert(lpService, "DummyLpService not found");
|
|
411
|
+
const mockVault = { publicKey: "dummy-public-key", secretKey: "dummy-secret-key" };
|
|
412
|
+
console.log("Testing add liquidity to dummy-pool-1...");
|
|
413
|
+
const result = await lpService.addLiquidity({
|
|
414
|
+
userVault: mockVault,
|
|
415
|
+
poolId: "dummy-pool-1",
|
|
416
|
+
tokenAAmountLamports: "1000000000",
|
|
417
|
+
// 1 SOL
|
|
418
|
+
slippageBps: 100
|
|
419
|
+
// 1% slippage
|
|
420
|
+
});
|
|
421
|
+
assert.equal(result.success, true, "Add liquidity should succeed");
|
|
422
|
+
assert(result.transactionId, "Should have a transaction ID");
|
|
423
|
+
assert.match(result.transactionId, /^dummy-tx-/, "Transaction ID should have dummy prefix");
|
|
424
|
+
assert(result.lpTokensReceived, "Should receive LP tokens");
|
|
425
|
+
assert.equal(
|
|
426
|
+
result.lpTokensReceived?.symbol,
|
|
427
|
+
"DUMMY-LP",
|
|
428
|
+
"LP token should have correct symbol"
|
|
429
|
+
);
|
|
430
|
+
assert.equal(
|
|
431
|
+
result.lpTokensReceived?.address,
|
|
432
|
+
"dummy-lp-mint-dummy-pool-1",
|
|
433
|
+
"LP token should have correct address"
|
|
434
|
+
);
|
|
435
|
+
console.log("Successfully added liquidity:", result);
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
name: "Scenario 5: Should remove liquidity from a dummy pool",
|
|
440
|
+
fn: async (runtime) => {
|
|
441
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
442
|
+
assert(lpService, "DummyLpService not found");
|
|
443
|
+
const mockVault = { publicKey: "dummy-public-key-2", secretKey: "dummy-secret-key-2" };
|
|
444
|
+
console.log("Testing remove liquidity from dummy-pool-1...");
|
|
445
|
+
const result = await lpService.removeLiquidity({
|
|
446
|
+
userVault: mockVault,
|
|
447
|
+
poolId: "dummy-pool-1",
|
|
448
|
+
lpTokenAmountLamports: "1000000",
|
|
449
|
+
// 1 LP token
|
|
450
|
+
slippageBps: 50
|
|
451
|
+
// 0.5% slippage
|
|
452
|
+
});
|
|
453
|
+
assert.equal(result.success, true, "Remove liquidity should succeed");
|
|
454
|
+
assert(result.transactionId, "Should have a transaction ID");
|
|
455
|
+
assert.match(result.transactionId, /^dummy-tx-/, "Transaction ID should have dummy prefix");
|
|
456
|
+
assert(result.tokensReceived, "Should receive tokens");
|
|
457
|
+
assert.equal(result.tokensReceived.length, 2, "Should receive 2 tokens");
|
|
458
|
+
const solToken = result.tokensReceived.find((t) => t.symbol === "SOL");
|
|
459
|
+
const usdcToken = result.tokensReceived.find((t) => t.symbol === "USDC");
|
|
460
|
+
assert(solToken, "Should receive SOL");
|
|
461
|
+
assert(usdcToken, "Should receive USDC");
|
|
462
|
+
assert.equal(solToken.uiAmount, 0.5, "Should receive 0.5 SOL");
|
|
463
|
+
assert.equal(usdcToken.uiAmount, 500, "Should receive 500 USDC");
|
|
464
|
+
console.log("Successfully removed liquidity:", result);
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
name: "Scenario 6: Should get LP position details",
|
|
469
|
+
fn: async (runtime) => {
|
|
470
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
471
|
+
assert(lpService, "DummyLpService not found");
|
|
472
|
+
const userPublicKey = "HtiYLjY9dGMrmpwjDcGmxQCo2VsCCAQiBgt5xPLanTJa";
|
|
473
|
+
const lpMint = "dummy-lp-mint-dummy-pool-1";
|
|
474
|
+
console.log(`Getting LP position details for user ${userPublicKey}...`);
|
|
475
|
+
const position = await lpService.getLpPositionDetails(userPublicKey, lpMint);
|
|
476
|
+
assert(position, "Should return LP position details");
|
|
477
|
+
assert.equal(position.poolId, "dummy-pool-1", "Position should reference correct pool");
|
|
478
|
+
assert.equal(position.dex, "dummy", "Position should have correct DEX");
|
|
479
|
+
assert.equal(position.valueUsd, 1e3, "Position should have correct USD value");
|
|
480
|
+
assert(position.lpTokenBalance, "Should have LP token balance");
|
|
481
|
+
assert.equal(
|
|
482
|
+
position.lpTokenBalance.symbol,
|
|
483
|
+
"DUMMY-LP",
|
|
484
|
+
"LP token should have correct symbol"
|
|
485
|
+
);
|
|
486
|
+
assert.equal(position.lpTokenBalance.uiAmount, 100, "Should have 100 LP tokens");
|
|
487
|
+
assert(position.underlyingTokens, "Should have underlying tokens");
|
|
488
|
+
assert.equal(position.underlyingTokens.length, 2, "Should have 2 underlying tokens");
|
|
489
|
+
const sol = position.underlyingTokens.find((t) => t.symbol === "SOL");
|
|
490
|
+
const usdc = position.underlyingTokens.find((t) => t.symbol === "USDC");
|
|
491
|
+
assert(sol, "Should have SOL in underlying tokens");
|
|
492
|
+
assert(usdc, "Should have USDC in underlying tokens");
|
|
493
|
+
assert.equal(sol.uiAmount, 0.5, "Should have 0.5 SOL");
|
|
494
|
+
assert.equal(usdc.uiAmount, 500, "Should have 500 USDC");
|
|
495
|
+
console.log("Successfully retrieved LP position details:", position);
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: "Scenario 7: Should get market data for pools",
|
|
500
|
+
fn: async (runtime) => {
|
|
501
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
502
|
+
assert(lpService, "DummyLpService not found");
|
|
503
|
+
const poolIds = ["dummy-pool-1", "dummy-stable-pool-2"];
|
|
504
|
+
console.log(`Getting market data for pools: ${poolIds.join(", ")}...`);
|
|
505
|
+
const marketData = await lpService.getMarketDataForPools(poolIds);
|
|
506
|
+
assert(marketData, "Should return market data");
|
|
507
|
+
assert.equal(Object.keys(marketData).length, 2, "Should have data for 2 pools");
|
|
508
|
+
poolIds.forEach((poolId) => {
|
|
509
|
+
const data = marketData[poolId];
|
|
510
|
+
assert(data, `Should have market data for ${poolId}`);
|
|
511
|
+
assert(typeof data.tvl === "number", "Should have TVL");
|
|
512
|
+
assert(typeof data.apy === "number", "Should have APY");
|
|
513
|
+
assert(typeof data.apr === "number", "Should have APR");
|
|
514
|
+
assert(data.tvl >= 0, "TVL should be non-negative");
|
|
515
|
+
assert(data.apy >= 0 && data.apy <= 1, "APY should be between 0 and 1");
|
|
516
|
+
assert(data.apr >= 0 && data.apr <= 1, "APR should be between 0 and 1");
|
|
517
|
+
});
|
|
518
|
+
console.log("Successfully retrieved market data:", marketData);
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
name: "Scenario 8: Should fetch token data from DummyTokenDataService",
|
|
523
|
+
fn: async (runtime) => {
|
|
524
|
+
const tokenDataService = runtime.getService(
|
|
525
|
+
DummyTokenDataService.serviceType
|
|
526
|
+
);
|
|
527
|
+
assert(tokenDataService, "DummyTokenDataService not found");
|
|
528
|
+
const solMint = "So11111111111111111111111111111111111111112";
|
|
529
|
+
console.log(`Fetching token data for SOL (${solMint})...`);
|
|
530
|
+
const tokenData = await tokenDataService.getTokenDetails(solMint, "solana");
|
|
531
|
+
assert(tokenData, "Should return token data");
|
|
532
|
+
assert(tokenData.symbol, "Should have symbol");
|
|
533
|
+
assert(tokenData.name, "Should have name");
|
|
534
|
+
assert.equal(tokenData.decimals, 18, "Should have decimals");
|
|
535
|
+
assert(typeof tokenData.price === "number", "Should have price");
|
|
536
|
+
console.log("Successfully fetched token data:", tokenData);
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
name: "Scenario 9: Should test trending tokens",
|
|
541
|
+
fn: async (runtime) => {
|
|
542
|
+
const tokenDataService = runtime.getService(
|
|
543
|
+
DummyTokenDataService.serviceType
|
|
544
|
+
);
|
|
545
|
+
assert(tokenDataService, "DummyTokenDataService not found");
|
|
546
|
+
console.log("Fetching trending tokens...");
|
|
547
|
+
const trendingTokens = await tokenDataService.getTrendingTokens("solana", 5);
|
|
548
|
+
assert(Array.isArray(trendingTokens), "Should return array of trending tokens");
|
|
549
|
+
assert.equal(trendingTokens.length, 5, "Should return requested number of tokens");
|
|
550
|
+
trendingTokens.forEach((token, i) => {
|
|
551
|
+
assert(token.symbol, `Token ${i} should have symbol`);
|
|
552
|
+
assert(token.name, `Token ${i} should have name`);
|
|
553
|
+
assert(typeof token.price === "number", `Token ${i} should have price`);
|
|
554
|
+
});
|
|
555
|
+
console.log("Successfully fetched trending tokens.");
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
name: "Scenario 10: Integration test - LP service with custom pool configuration",
|
|
560
|
+
fn: async (runtime) => {
|
|
561
|
+
const lpService = runtime.getService(ILpService2.serviceType);
|
|
562
|
+
assert(lpService, "DummyLpService not found");
|
|
563
|
+
console.log("Testing integration with multiple pools...");
|
|
564
|
+
const allPools = await lpService.getPools();
|
|
565
|
+
assert.equal(allPools.length, 2, "Should have 2 pools");
|
|
566
|
+
for (const pool of allPools) {
|
|
567
|
+
console.log(`Testing operations on pool ${pool.id}...`);
|
|
568
|
+
const addResult = await lpService.addLiquidity({
|
|
569
|
+
userVault: {},
|
|
570
|
+
poolId: pool.id,
|
|
571
|
+
tokenAAmountLamports: "1000000000",
|
|
572
|
+
slippageBps: 100
|
|
573
|
+
});
|
|
574
|
+
assert.equal(addResult.success, true, `Add liquidity should succeed for ${pool.id}`);
|
|
575
|
+
const removeResult = await lpService.removeLiquidity({
|
|
576
|
+
userVault: {},
|
|
577
|
+
poolId: pool.id,
|
|
578
|
+
lpTokenAmountLamports: "1000000",
|
|
579
|
+
slippageBps: 50
|
|
580
|
+
});
|
|
581
|
+
assert.equal(
|
|
582
|
+
removeResult.success,
|
|
583
|
+
true,
|
|
584
|
+
`Remove liquidity should succeed for ${pool.id}`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
console.log("Successfully tested operations on all pools.");
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
name: "Scenario 11: Should initialize wallet service and verify functionality",
|
|
592
|
+
fn: async (runtime) => {
|
|
593
|
+
console.log("Testing wallet service initialization...");
|
|
594
|
+
const walletService = runtime.getService(ServiceType3.WALLET);
|
|
595
|
+
assert(walletService, "DummyWalletService not found in runtime");
|
|
596
|
+
const initialBalance = await walletService.getBalance("USDC");
|
|
597
|
+
assert.equal(initialBalance, 1e4, "Should have initial USDC balance of 10000");
|
|
598
|
+
console.log("Successfully verified wallet service is initialized.");
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
name: "Scenario 12: Should test wallet operations",
|
|
603
|
+
fn: async (runtime) => {
|
|
604
|
+
const walletService = runtime.getService(ServiceType3.WALLET);
|
|
605
|
+
assert(walletService, "DummyWalletService not found");
|
|
606
|
+
console.log("Testing wallet operations...");
|
|
607
|
+
await walletService.addFunds("SOL", 5);
|
|
608
|
+
const solBalance = await walletService.getBalance("SOL");
|
|
609
|
+
assert.equal(solBalance, 5, "Should have 5 SOL after adding funds");
|
|
610
|
+
const portfolio = await walletService.getPortfolio();
|
|
611
|
+
assert(portfolio.totalValueUsd > 0, "Portfolio should have positive total value");
|
|
612
|
+
assert(Array.isArray(portfolio.assets), "Portfolio should have assets array");
|
|
613
|
+
assert(portfolio.assets.length >= 2, "Portfolio should have at least 2 assets");
|
|
614
|
+
const solAsset = portfolio.assets.find((a) => a.symbol === "SOL");
|
|
615
|
+
assert(solAsset, "SOL should be in portfolio");
|
|
616
|
+
assert.equal(solAsset.balance, "5", 'SOL balance string should be "5"');
|
|
617
|
+
console.log("Successfully tested wallet operations.");
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
name: "Scenario 13: Should test SOL transfers",
|
|
622
|
+
fn: async (runtime) => {
|
|
623
|
+
const walletService = runtime.getService(ServiceType3.WALLET);
|
|
624
|
+
assert(walletService, "DummyWalletService not found");
|
|
625
|
+
console.log("Testing SOL transfer functionality...");
|
|
626
|
+
await walletService.resetWallet(1e4, "USDC");
|
|
627
|
+
await walletService.addFunds("SOL", 10);
|
|
628
|
+
const txHash = await walletService.transferSol("dummy-from", "dummy-to", 3e9);
|
|
629
|
+
assert(txHash, "Should return transaction hash");
|
|
630
|
+
assert.match(txHash, /^dummy-tx-/, "Transaction hash should have dummy prefix");
|
|
631
|
+
const remainingBalance = await walletService.getBalance("SOL");
|
|
632
|
+
assert.equal(remainingBalance, 7, "Should have 7 SOL remaining after transfer");
|
|
633
|
+
try {
|
|
634
|
+
await walletService.transferSol("dummy-from", "dummy-to", 1e10);
|
|
635
|
+
assert.fail("Should throw error for insufficient balance");
|
|
636
|
+
} catch (error) {
|
|
637
|
+
assert.match(
|
|
638
|
+
error.message,
|
|
639
|
+
/Insufficient SOL balance/,
|
|
640
|
+
"Should throw insufficient balance error"
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
console.log("Successfully tested SOL transfers.");
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
]
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
// src/index.ts
|
|
650
|
+
var dummyServicesPlugin = {
|
|
651
|
+
name: "dummy-services",
|
|
652
|
+
description: "Load standard dummy services for testing purposes.",
|
|
653
|
+
services: [DummyTokenDataService, DummyLpService, DummyWalletService],
|
|
654
|
+
tests: [dummyServicesScenariosSuite],
|
|
655
|
+
init: async (runtime) => {
|
|
656
|
+
console.log("Dummy Services Plugin Initialized");
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
var index_default = dummyServicesPlugin;
|
|
660
|
+
export {
|
|
661
|
+
DummyLpService,
|
|
662
|
+
DummyTokenDataService,
|
|
663
|
+
DummyWalletService,
|
|
664
|
+
index_default as default,
|
|
665
|
+
dummyServicesPlugin
|
|
666
|
+
};
|
|
667
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tokenData/service.ts","../src/lp/service.ts","../src/wallet/service.ts","../src/e2e/scenarios.ts","../src/index.ts"],"sourcesContent":["import {\n ITokenDataService,\n TokenData,\n Service,\n IAgentRuntime,\n ServiceType,\n logger,\n} from '@elizaos/core';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport class DummyTokenDataService extends Service implements ITokenDataService {\n readonly serviceName = 'dummy-token-data';\n static readonly serviceType = ServiceType.TOKEN_DATA;\n readonly capabilityDescription =\n 'Provides dummy token data for testing and development purposes.';\n\n constructor(runtime?: IAgentRuntime) {\n super(runtime);\n logger.info('DummyTokenDataService initialized');\n }\n\n private generateDummyToken(chain: string, address?: string, query?: string): TokenData {\n const randomAddress = address || `0x${uuidv4().replace(/-/g, '')}`;\n const symbol = query ? query.toUpperCase() : randomAddress.substring(2, 6).toUpperCase();\n return {\n id: `${chain}:${randomAddress}`,\n symbol: symbol,\n name: `Dummy Token ${symbol}`,\n address: randomAddress,\n chain: chain,\n sourceProvider: 'dummy',\n price: Math.random() * 100,\n priceChange24hPercent: (Math.random() - 0.5) * 20,\n volume24hUSD: Math.random() * 1000000,\n marketCapUSD: Math.random() * 100000000,\n liquidity: Math.random() * 500000,\n holders: Math.floor(Math.random() * 10000),\n logoURI: 'https://via.placeholder.com/150',\n decimals: 18,\n lastUpdatedAt: new Date(),\n raw: {\n dummyData: true,\n },\n };\n }\n\n async getTokenDetails(address: string, chain: string): Promise<TokenData | null> {\n logger.debug(`DummyTokenDataService: getTokenDetails for ${address} on ${chain}`);\n return this.generateDummyToken(chain, address);\n }\n\n async getTrendingTokens(chain = 'solana', limit = 10, _timePeriod = '24h'): Promise<TokenData[]> {\n logger.debug(`DummyTokenDataService: getTrendingTokens on ${chain}`);\n return Array.from({ length: limit }, () => this.generateDummyToken(chain));\n }\n\n async searchTokens(query: string, chain = 'solana', limit = 5): Promise<TokenData[]> {\n logger.debug(`DummyTokenDataService: searchTokens for \"${query}\" on ${chain}`);\n return Array.from({ length: limit }, () => this.generateDummyToken(chain, undefined, query));\n }\n\n async getTokensByAddresses(addresses: string[], chain: string): Promise<TokenData[]> {\n logger.debug(`DummyTokenDataService: getTokensByAddresses on ${chain} for`, addresses);\n return addresses.map((addr) => this.generateDummyToken(chain, addr));\n }\n\n static async start(runtime: IAgentRuntime): Promise<DummyTokenDataService> {\n const service = new DummyTokenDataService(runtime);\n return service;\n }\n\n static async stop(runtime: IAgentRuntime): Promise<void> {\n const service = runtime.getService<DummyTokenDataService>(DummyTokenDataService.serviceType);\n if (service) {\n await service.stop();\n }\n }\n\n async start(): Promise<void> {\n logger.info(`[${this.serviceName}] Service started.`);\n }\n\n async stop(): Promise<void> {\n logger.info(`[${this.serviceName}] Service stopped.`);\n }\n}\n","import {\n IAgentRuntime,\n ILpService,\n LpPositionDetails,\n PoolInfo,\n TokenBalance,\n TransactionResult,\n Service,\n} from '@elizaos/core';\n\nexport class DummyLpService extends ILpService {\n public getDexName(): string {\n return 'dummy';\n }\n\n static async start(runtime: IAgentRuntime): Promise<DummyLpService> {\n const service = new DummyLpService(runtime);\n return service;\n }\n\n static async stop(runtime: IAgentRuntime): Promise<void> {\n const service = runtime.getService<DummyLpService>(DummyLpService.serviceType);\n if (service) {\n await service.stop();\n }\n }\n\n async start(runtime: IAgentRuntime): Promise<void> {\n console.log('[DummyLpService] started.');\n }\n\n async stop(): Promise<void> {\n console.log('[DummyLpService] stopped.');\n }\n\n public async getPools(tokenAMint?: string, tokenBMint?: string): Promise<PoolInfo[]> {\n console.log(`[DummyLpService] getPools called with: ${tokenAMint}, ${tokenBMint}`);\n\n const SOL_MINT = 'So11111111111111111111111111111111111111112';\n const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a';\n\n const pools = [\n {\n id: 'dummy-pool-1',\n dex: 'dummy',\n tokenA: { mint: SOL_MINT, symbol: 'SOL', name: 'Solana', decimals: 9 },\n tokenB: { mint: USDC_MINT, symbol: 'USDC', name: 'USD Coin', decimals: 6 },\n apr: 0.12,\n apy: 0.125,\n tvl: 1234567.89,\n fee: 0.0025,\n metadata: { name: 'SOL/USDC Dummy Pool', isStable: false },\n },\n {\n id: 'dummy-stable-pool-2',\n dex: 'dummy',\n tokenA: { mint: USDC_MINT, symbol: 'USDC', name: 'USD Coin', decimals: 6 },\n tokenB: {\n mint: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n symbol: 'USDT',\n name: 'Tether',\n decimals: 6,\n },\n apr: 0.08,\n apy: 0.082,\n tvl: 2500000.0,\n fee: 0.0005,\n metadata: { name: 'USDC/USDT Dummy Stable Pool', isStable: true },\n },\n ];\n\n return pools.filter((p) => {\n if (!tokenAMint && !tokenBMint) return true;\n const hasTokenA = p.tokenA.mint === tokenAMint || p.tokenB.mint === tokenAMint;\n const hasTokenB = p.tokenA.mint === tokenBMint || p.tokenB.mint === tokenBMint;\n if (tokenAMint && tokenBMint) return hasTokenA && hasTokenB;\n if (tokenAMint) return hasTokenA;\n if (tokenBMint) return hasTokenB;\n return false;\n });\n }\n\n public async addLiquidity(params: {\n userVault: any;\n poolId: string;\n tokenAAmountLamports: string;\n tokenBAmountLamports?: string;\n slippageBps: number;\n }): Promise<TransactionResult & { lpTokensReceived?: TokenBalance }> {\n console.log(`[DummyLpService] addLiquidity called for pool: ${params.poolId}`);\n return {\n success: true,\n transactionId: `dummy-tx-${Date.now()}`,\n lpTokensReceived: {\n address: `dummy-lp-mint-${params.poolId}`,\n balance: '100000000', // 100 LP tokens\n symbol: 'DUMMY-LP',\n uiAmount: 100,\n decimals: 6,\n name: `Dummy LP Token for ${params.poolId}`,\n },\n };\n }\n\n public async removeLiquidity(params: {\n userVault: any;\n poolId: string;\n lpTokenAmountLamports: string;\n slippageBps: number;\n }): Promise<TransactionResult & { tokensReceived?: TokenBalance[] }> {\n console.log(`[DummyLpService] removeLiquidity called for pool: ${params.poolId}`);\n return {\n success: true,\n transactionId: `dummy-tx-${Date.now()}`,\n tokensReceived: [\n {\n address: 'So11111111111111111111111111111111111111112',\n balance: '500000000',\n symbol: 'SOL',\n uiAmount: 0.5,\n decimals: 9,\n name: 'Solana',\n },\n {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a',\n balance: '500000000',\n symbol: 'USDC',\n uiAmount: 500,\n decimals: 6,\n name: 'USD Coin',\n },\n ],\n };\n }\n\n public async getLpPositionDetails(\n userAccountPublicKey: string,\n poolOrPositionIdentifier: string\n ): Promise<LpPositionDetails | null> {\n console.log(\n `[DummyLpService] getLpPositionDetails called for user: ${userAccountPublicKey}, identifier: ${poolOrPositionIdentifier}`\n );\n // This is a mock. In a real scenario, you'd look up position details based on the identifier.\n // The identifier could be the pool ID for a simple AMM or a position NFT mint for a CLMM.\n return {\n poolId: 'dummy-pool-1', // Assuming the identifier maps back to a known pool\n dex: 'dummy',\n lpTokenBalance: {\n address: poolOrPositionIdentifier,\n balance: '100000000',\n symbol: 'DUMMY-LP',\n uiAmount: 100,\n decimals: 6,\n name: `Dummy LP Token`,\n },\n underlyingTokens: [\n {\n address: 'So11111111111111111111111111111111111111112',\n balance: '500000000',\n symbol: 'SOL',\n uiAmount: 0.5,\n decimals: 9,\n name: 'Solana',\n },\n {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyB7u6a',\n balance: '500000000',\n symbol: 'USDC',\n uiAmount: 500,\n decimals: 6,\n name: 'USD Coin',\n },\n ],\n valueUsd: 1000,\n metadata: { apr: 0.12 },\n };\n }\n\n public async getMarketDataForPools(\n poolIds: string[]\n ): Promise<Record<string, Partial<PoolInfo>>> {\n console.log(`[DummyLpService] getMarketDataForPools called for pools: ${poolIds.join(', ')}`);\n const results: Record<string, Partial<PoolInfo>> = {};\n for (const poolId of poolIds) {\n results[poolId] = {\n apy: Math.random() * 0.2,\n tvl: Math.random() * 1000000,\n apr: Math.random() * 0.18,\n };\n }\n return results;\n }\n}\n","import { AgentRuntime, IWalletService, Service, ServiceType, WalletPortfolio } from '@elizaos/core';\n\nconst DEFAULT_QUOTE_ASSET = 'USDC'; // Default asset for cash\nconst DEFAULT_TRANSACTION_FEE_FIXED = 0.1; // Example fixed fee in quote asset\n\ninterface DummyPositionLot {\n price: number;\n quantity: number;\n timestamp: number;\n}\n\ninterface DummyAssetDetail {\n quantity: number;\n averagePrice: number; // Average price of current holdings\n lots: DummyPositionLot[]; // For FIFO P&L on sell\n}\n\nexport class DummyWalletService extends Service implements IWalletService {\n public static override readonly serviceType = ServiceType.WALLET;\n public readonly capabilityDescription =\n 'Provides standardized access to wallet balances and portfolios.';\n\n private balances: Map<string, number>; // assetSymbolOrAddress -> quantity\n private positions: Map<string, DummyAssetDetail>; // assetSymbolOrAddress -> details for owned non-quote assets\n private quoteAssetSymbol: string;\n\n constructor(runtime: AgentRuntime) {\n super(runtime);\n this.balances = new Map<string, number>();\n this.positions = new Map<string, DummyAssetDetail>();\n this.quoteAssetSymbol = DEFAULT_QUOTE_ASSET;\n this.resetWallet(10000, DEFAULT_QUOTE_ASSET); // Initialize with some default cash\n }\n async transferSol(from: any, to: any, lamports: number): Promise<string> {\n // This is a dummy implementation - no real transfer happens\n console.log(\n `[${DummyWalletService.serviceType}] Mock transfer: ${lamports} lamports from ${from} to ${to}`\n );\n\n // For dummy wallet, we just simulate the transfer\n const solSymbol = 'SOL';\n const solAmount = lamports / 1e9; // Convert lamports to SOL\n\n const currentBalance = this.balances.get(solSymbol) || 0;\n if (currentBalance < solAmount) {\n throw new Error(`Insufficient SOL balance. Have ${currentBalance}, need ${solAmount}`);\n }\n\n // Deduct from balance\n this.balances.set(solSymbol, currentBalance - solAmount);\n\n // Return a dummy transaction signature\n return `dummy-tx-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n }\n\n public static async start(runtime: AgentRuntime): Promise<DummyWalletService> {\n console.log(`[${DummyWalletService.serviceType}] static start called - creating instance.`);\n const instance = new DummyWalletService(runtime);\n // No further async init in instance.start() currently needed for this simple map-based wallet\n return instance;\n }\n\n public async start(): Promise<void> {\n console.log(\n `[${DummyWalletService.serviceType}] instance start called. Initialized with ${this.balances.get(this.quoteAssetSymbol)} ${this.quoteAssetSymbol}.`\n );\n }\n\n public async stop(): Promise<void> {\n console.log(`[${DummyWalletService.serviceType}] instance stop called. Balances reset.`);\n this.balances.clear();\n this.positions.clear();\n }\n\n async addFunds(\n assetSymbolOrAddress: string,\n amount: number,\n _walletAddress?: string\n ): Promise<void> {\n const currentBalance = this.balances.get(assetSymbolOrAddress) || 0;\n this.balances.set(assetSymbolOrAddress, currentBalance + amount);\n console.log(\n `[${DummyWalletService.serviceType}] Added ${amount} ${assetSymbolOrAddress}. New balance: ${this.balances.get(assetSymbolOrAddress)}`\n );\n }\n\n async setPortfolioHolding(\n assetSymbolOrAddress: string,\n quantity: number,\n averagePrice: number,\n _walletAddress?: string\n ): Promise<void> {\n if (assetSymbolOrAddress === this.quoteAssetSymbol) {\n console.warn(\n `[${DummyWalletService.serviceType}] Cannot set portfolio holding for quote asset directly, use addFunds.`\n );\n return this.addFunds(assetSymbolOrAddress, quantity * averagePrice); // Assuming quantity is amount of quote to add\n }\n this.balances.set(assetSymbolOrAddress, quantity);\n this.positions.set(assetSymbolOrAddress, {\n quantity: quantity,\n averagePrice: averagePrice,\n lots: [{ price: averagePrice, quantity: quantity, timestamp: Date.now() }], // Create a single lot for simplicity\n });\n console.log(\n `[${DummyWalletService.serviceType}] Set holding for ${assetSymbolOrAddress}: ${quantity} @ ${averagePrice}`\n );\n }\n\n async resetWallet(\n initialCashAmount: number,\n cashAssetSymbol: string = DEFAULT_QUOTE_ASSET,\n _walletAddress?: string\n ): Promise<void> {\n this.balances.clear();\n this.positions.clear();\n this.quoteAssetSymbol = cashAssetSymbol;\n this.balances.set(this.quoteAssetSymbol, initialCashAmount);\n console.log(\n `[${DummyWalletService.serviceType}] Wallet reset. Cash: ${initialCashAmount} ${this.quoteAssetSymbol}`\n );\n }\n\n async getBalance(assetSymbolOrAddress: string, _walletAddress?: string): Promise<number> {\n return this.balances.get(assetSymbolOrAddress) || 0;\n }\n\n async getPortfolio(_walletAddress?: string): Promise<WalletPortfolio> {\n const assets: any[] = [];\n let totalValueUsd = 0;\n\n for (const [symbol, balance] of this.balances) {\n const positionDetail = this.positions.get(symbol);\n const isQuoteAsset = symbol === this.quoteAssetSymbol;\n const averagePrice = positionDetail?.averagePrice || (isQuoteAsset ? 1 : 0);\n const value = isQuoteAsset\n ? balance\n : positionDetail\n ? balance * positionDetail.averagePrice\n : 0;\n\n // WalletAsset structure\n assets.push({\n address: symbol, // Using symbol as address for dummy wallet\n symbol,\n balance: balance.toString(),\n decimals: isQuoteAsset ? 6 : 9, // Default decimals\n quantity: balance,\n averagePrice,\n currentPrice: undefined,\n value,\n assetAddress: symbol,\n });\n\n totalValueUsd += value;\n }\n\n return {\n totalValueUsd,\n assets,\n };\n }\n}\n","import type { IAgentRuntime, TestSuite, IWalletService } from '@elizaos/core';\nimport { ILpService, ServiceType } from '@elizaos/core';\nimport { strict as assert } from 'node:assert';\nimport { DummyLpService } from '../lp/service';\nimport { DummyTokenDataService } from '../tokenData/service';\nimport { DummyWalletService } from '../wallet/service';\nimport { setupScenario } from './test-utils';\n\nexport const dummyServicesScenariosSuite: TestSuite = {\n name: 'Dummy Services Plugin E2E Scenarios',\n tests: [\n {\n name: 'Scenario 1: Should initialize dummy services and verify they are available',\n fn: async (runtime: IAgentRuntime) => {\n console.log('Testing dummy services initialization...');\n\n // Check DummyLpService\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found in runtime');\n assert.equal(\n lpService.getDexName(),\n 'dummy',\n 'DummyLpService should have correct DEX name'\n );\n\n // Check DummyTokenDataService\n const tokenDataService = runtime.getService<DummyTokenDataService>(\n DummyTokenDataService.serviceType\n );\n assert(tokenDataService, 'DummyTokenDataService not found in runtime');\n\n console.log('Successfully verified both dummy services are initialized and available.');\n },\n },\n {\n name: 'Scenario 2: Should fetch pools from DummyLpService',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n console.log('Fetching all pools from DummyLpService...');\n const allPools = await lpService.getPools();\n assert(Array.isArray(allPools), 'getPools should return an array');\n assert.equal(allPools.length, 2, 'Should return 2 dummy pools');\n\n // Verify pool structure\n const pool1 = allPools.find((p) => p.id === 'dummy-pool-1');\n assert(pool1, 'dummy-pool-1 should exist');\n assert.equal(pool1.dex, 'dummy', 'Pool should have correct DEX');\n assert.equal(pool1.tokenA.symbol, 'SOL', 'Pool should have SOL as tokenA');\n assert.equal(pool1.tokenB.symbol, 'USDC', 'Pool should have USDC as tokenB');\n assert.equal(pool1.tvl, 1234567.89, 'Pool should have correct TVL');\n\n console.log('Successfully fetched and verified pool data.');\n },\n },\n {\n name: 'Scenario 3: Should filter pools by token mint',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n const solMint = 'So11111111111111111111111111111111111111112';\n console.log(`Filtering pools containing SOL (${solMint})...`);\n\n const solPools = await lpService.getPools(solMint);\n assert(Array.isArray(solPools), 'getPools with filter should return an array');\n assert(solPools.length > 0, 'Should find pools containing SOL');\n\n // Verify all returned pools contain SOL\n solPools.forEach((pool) => {\n const containsSol = pool.tokenA.mint === solMint || pool.tokenB.mint === solMint;\n assert(containsSol, `Pool ${pool.id} should contain SOL`);\n });\n\n console.log(`Found ${solPools.length} pools containing SOL.`);\n },\n },\n {\n name: 'Scenario 4: Should add liquidity to a dummy pool',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n // Create a mock vault object\n const mockVault = { publicKey: 'dummy-public-key', secretKey: 'dummy-secret-key' };\n\n console.log('Testing add liquidity to dummy-pool-1...');\n const result = await lpService.addLiquidity({\n userVault: mockVault,\n poolId: 'dummy-pool-1',\n tokenAAmountLamports: '1000000000', // 1 SOL\n slippageBps: 100, // 1% slippage\n });\n\n assert.equal(result.success, true, 'Add liquidity should succeed');\n assert(result.transactionId, 'Should have a transaction ID');\n assert.match(result.transactionId, /^dummy-tx-/, 'Transaction ID should have dummy prefix');\n assert(result.lpTokensReceived, 'Should receive LP tokens');\n assert.equal(\n result.lpTokensReceived?.symbol,\n 'DUMMY-LP',\n 'LP token should have correct symbol'\n );\n assert.equal(\n result.lpTokensReceived?.address,\n 'dummy-lp-mint-dummy-pool-1',\n 'LP token should have correct address'\n );\n\n console.log('Successfully added liquidity:', result);\n },\n },\n {\n name: 'Scenario 5: Should remove liquidity from a dummy pool',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n // Create a mock vault object\n const mockVault = { publicKey: 'dummy-public-key-2', secretKey: 'dummy-secret-key-2' };\n\n console.log('Testing remove liquidity from dummy-pool-1...');\n const result = await lpService.removeLiquidity({\n userVault: mockVault,\n poolId: 'dummy-pool-1',\n lpTokenAmountLamports: '1000000', // 1 LP token\n slippageBps: 50, // 0.5% slippage\n });\n\n assert.equal(result.success, true, 'Remove liquidity should succeed');\n assert(result.transactionId, 'Should have a transaction ID');\n assert.match(result.transactionId, /^dummy-tx-/, 'Transaction ID should have dummy prefix');\n assert(result.tokensReceived, 'Should receive tokens');\n assert.equal(result.tokensReceived.length, 2, 'Should receive 2 tokens');\n\n // Verify underlying tokens\n const solToken = result.tokensReceived.find((t) => t.symbol === 'SOL');\n const usdcToken = result.tokensReceived.find((t) => t.symbol === 'USDC');\n assert(solToken, 'Should receive SOL');\n assert(usdcToken, 'Should receive USDC');\n assert.equal(solToken.uiAmount, 0.5, 'Should receive 0.5 SOL');\n assert.equal(usdcToken.uiAmount, 500, 'Should receive 500 USDC');\n\n console.log('Successfully removed liquidity:', result);\n },\n },\n {\n name: 'Scenario 6: Should get LP position details',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n const userPublicKey = 'HtiYLjY9dGMrmpwjDcGmxQCo2VsCCAQiBgt5xPLanTJa';\n const lpMint = 'dummy-lp-mint-dummy-pool-1';\n\n console.log(`Getting LP position details for user ${userPublicKey}...`);\n const position = await lpService.getLpPositionDetails(userPublicKey, lpMint);\n\n assert(position, 'Should return LP position details');\n assert.equal(position.poolId, 'dummy-pool-1', 'Position should reference correct pool');\n assert.equal(position.dex, 'dummy', 'Position should have correct DEX');\n assert.equal(position.valueUsd, 1000, 'Position should have correct USD value');\n\n // Verify LP token balance\n assert(position.lpTokenBalance, 'Should have LP token balance');\n assert.equal(\n position.lpTokenBalance.symbol,\n 'DUMMY-LP',\n 'LP token should have correct symbol'\n );\n assert.equal(position.lpTokenBalance.uiAmount, 100, 'Should have 100 LP tokens');\n\n // Verify underlying tokens\n assert(position.underlyingTokens, 'Should have underlying tokens');\n assert.equal(position.underlyingTokens.length, 2, 'Should have 2 underlying tokens');\n\n const sol = position.underlyingTokens.find((t) => t.symbol === 'SOL');\n const usdc = position.underlyingTokens.find((t) => t.symbol === 'USDC');\n assert(sol, 'Should have SOL in underlying tokens');\n assert(usdc, 'Should have USDC in underlying tokens');\n assert.equal(sol.uiAmount, 0.5, 'Should have 0.5 SOL');\n assert.equal(usdc.uiAmount, 500, 'Should have 500 USDC');\n\n console.log('Successfully retrieved LP position details:', position);\n },\n },\n {\n name: 'Scenario 7: Should get market data for pools',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n const poolIds = ['dummy-pool-1', 'dummy-stable-pool-2'];\n console.log(`Getting market data for pools: ${poolIds.join(', ')}...`);\n\n const marketData = await lpService.getMarketDataForPools(poolIds);\n assert(marketData, 'Should return market data');\n assert.equal(Object.keys(marketData).length, 2, 'Should have data for 2 pools');\n\n // Verify market data structure\n poolIds.forEach((poolId) => {\n const data = marketData[poolId];\n assert(data, `Should have market data for ${poolId}`);\n assert(typeof data.tvl === 'number', 'Should have TVL');\n assert(typeof data.apy === 'number', 'Should have APY');\n assert(typeof data.apr === 'number', 'Should have APR');\n\n // Verify reasonable ranges\n assert(data.tvl >= 0, 'TVL should be non-negative');\n assert(data.apy >= 0 && data.apy <= 1, 'APY should be between 0 and 1');\n assert(data.apr >= 0 && data.apr <= 1, 'APR should be between 0 and 1');\n });\n\n console.log('Successfully retrieved market data:', marketData);\n },\n },\n {\n name: 'Scenario 8: Should fetch token data from DummyTokenDataService',\n fn: async (runtime: IAgentRuntime) => {\n const tokenDataService = runtime.getService<DummyTokenDataService>(\n DummyTokenDataService.serviceType\n );\n assert(tokenDataService, 'DummyTokenDataService not found');\n\n const solMint = 'So11111111111111111111111111111111111111112';\n console.log(`Fetching token data for SOL (${solMint})...`);\n\n const tokenData = await tokenDataService.getTokenDetails(solMint, 'solana');\n assert(tokenData, 'Should return token data');\n assert(tokenData.symbol, 'Should have symbol');\n assert(tokenData.name, 'Should have name');\n assert.equal(tokenData.decimals, 18, 'Should have decimals');\n assert(typeof tokenData.price === 'number', 'Should have price');\n\n console.log('Successfully fetched token data:', tokenData);\n },\n },\n {\n name: 'Scenario 9: Should test trending tokens',\n fn: async (runtime: IAgentRuntime) => {\n const tokenDataService = runtime.getService<DummyTokenDataService>(\n DummyTokenDataService.serviceType\n );\n assert(tokenDataService, 'DummyTokenDataService not found');\n\n console.log('Fetching trending tokens...');\n\n const trendingTokens = await tokenDataService.getTrendingTokens('solana', 5);\n assert(Array.isArray(trendingTokens), 'Should return array of trending tokens');\n assert.equal(trendingTokens.length, 5, 'Should return requested number of tokens');\n\n trendingTokens.forEach((token, i) => {\n assert(token.symbol, `Token ${i} should have symbol`);\n assert(token.name, `Token ${i} should have name`);\n assert(typeof token.price === 'number', `Token ${i} should have price`);\n });\n\n console.log('Successfully fetched trending tokens.');\n },\n },\n {\n name: 'Scenario 10: Integration test - LP service with custom pool configuration',\n fn: async (runtime: IAgentRuntime) => {\n const lpService = runtime.getService<DummyLpService>(ILpService.serviceType);\n assert(lpService, 'DummyLpService not found');\n\n // Test that we can work with both pools\n console.log('Testing integration with multiple pools...');\n\n // Get all pools\n const allPools = await lpService.getPools();\n assert.equal(allPools.length, 2, 'Should have 2 pools');\n\n // Test operations on each pool\n for (const pool of allPools) {\n console.log(`Testing operations on pool ${pool.id}...`);\n\n // Add liquidity\n const addResult = await lpService.addLiquidity({\n userVault: {} as any,\n poolId: pool.id,\n tokenAAmountLamports: '1000000000',\n slippageBps: 100,\n });\n assert.equal(addResult.success, true, `Add liquidity should succeed for ${pool.id}`);\n\n // Remove liquidity\n const removeResult = await lpService.removeLiquidity({\n userVault: {} as any,\n poolId: pool.id,\n lpTokenAmountLamports: '1000000',\n slippageBps: 50,\n });\n assert.equal(\n removeResult.success,\n true,\n `Remove liquidity should succeed for ${pool.id}`\n );\n }\n\n console.log('Successfully tested operations on all pools.');\n },\n },\n {\n name: 'Scenario 11: Should initialize wallet service and verify functionality',\n fn: async (runtime: IAgentRuntime) => {\n console.log('Testing wallet service initialization...');\n\n // Check DummyWalletService\n const walletService = runtime.getService<DummyWalletService>(ServiceType.WALLET);\n assert(walletService, 'DummyWalletService not found in runtime');\n\n // Test initial balance\n const initialBalance = await walletService.getBalance('USDC');\n assert.equal(initialBalance, 10000, 'Should have initial USDC balance of 10000');\n\n console.log('Successfully verified wallet service is initialized.');\n },\n },\n {\n name: 'Scenario 12: Should test wallet operations',\n fn: async (runtime: IAgentRuntime) => {\n const walletService = runtime.getService<DummyWalletService>(ServiceType.WALLET);\n assert(walletService, 'DummyWalletService not found');\n\n console.log('Testing wallet operations...');\n\n // Add funds\n await walletService.addFunds('SOL', 5);\n const solBalance = await walletService.getBalance('SOL');\n assert.equal(solBalance, 5, 'Should have 5 SOL after adding funds');\n\n // Get portfolio\n const portfolio = await walletService.getPortfolio();\n assert(portfolio.totalValueUsd > 0, 'Portfolio should have positive total value');\n assert(Array.isArray(portfolio.assets), 'Portfolio should have assets array');\n assert(portfolio.assets.length >= 2, 'Portfolio should have at least 2 assets');\n\n // Find SOL in portfolio\n const solAsset = portfolio.assets.find((a) => a.symbol === 'SOL');\n assert(solAsset, 'SOL should be in portfolio');\n assert.equal(solAsset.balance, '5', 'SOL balance string should be \"5\"');\n\n console.log('Successfully tested wallet operations.');\n },\n },\n {\n name: 'Scenario 13: Should test SOL transfers',\n fn: async (runtime: IAgentRuntime) => {\n const walletService = runtime.getService<DummyWalletService>(ServiceType.WALLET);\n assert(walletService, 'DummyWalletService not found');\n\n console.log('Testing SOL transfer functionality...');\n\n // Reset wallet to ensure clean state\n await walletService.resetWallet(10000, 'USDC');\n\n // Add SOL to wallet\n await walletService.addFunds('SOL', 10);\n\n // Transfer some SOL\n const txHash = await walletService.transferSol('dummy-from', 'dummy-to', 3e9); // 3 SOL\n assert(txHash, 'Should return transaction hash');\n assert.match(txHash, /^dummy-tx-/, 'Transaction hash should have dummy prefix');\n\n // Check remaining balance\n const remainingBalance = await walletService.getBalance('SOL');\n assert.equal(remainingBalance, 7, 'Should have 7 SOL remaining after transfer');\n\n // Test insufficient balance\n try {\n await walletService.transferSol('dummy-from', 'dummy-to', 10e9); // 10 SOL\n assert.fail('Should throw error for insufficient balance');\n } catch (error: any) {\n assert.match(\n error.message,\n /Insufficient SOL balance/,\n 'Should throw insufficient balance error'\n );\n }\n\n console.log('Successfully tested SOL transfers.');\n },\n },\n ],\n};\n\nexport default dummyServicesScenariosSuite;\n","import { type Plugin } from '@elizaos/core';\nimport { DummyTokenDataService } from './tokenData/service';\nimport { DummyLpService } from './lp/service';\nimport { DummyWalletService } from './wallet/service';\nimport { dummyServicesScenariosSuite } from './e2e/scenarios';\n\nexport const dummyServicesPlugin: Plugin = {\n name: 'dummy-services',\n description: 'Load standard dummy services for testing purposes.',\n services: [DummyTokenDataService, DummyLpService, DummyWalletService],\n tests: [dummyServicesScenariosSuite],\n init: async (runtime) => {\n console.log('Dummy Services Plugin Initialized');\n },\n};\n\nexport default dummyServicesPlugin;\n\n// Export services for direct use\nexport { DummyTokenDataService, DummyLpService, DummyWalletService };\n"],"mappings":"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","names":["Service","ServiceType","Service","ServiceType","ILpService","ServiceType","ILpService","ServiceType"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-dummy-services",
|
|
3
|
+
"version": "1.0.8",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/elizaos-plugins/plugin-dummy-services.git"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
".": {
|
|
15
|
+
"import": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@elizaos/core": "1.0.8",
|
|
26
|
+
"typescript": "^5.8.3",
|
|
27
|
+
"uuid": "^9.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"prettier": "3.5.3",
|
|
31
|
+
"tsup": "8.5.0",
|
|
32
|
+
"vitest": "1.6.1"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"dev": "tsup --watch",
|
|
37
|
+
"test": "elizaos test",
|
|
38
|
+
"lint": "prettier --write ./src",
|
|
39
|
+
"clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo",
|
|
40
|
+
"format": "prettier --write ./src",
|
|
41
|
+
"format:check": "prettier --check ./src"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"whatwg-url": "7.1.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"gitHead": "928b3cadaf4fb6bd4337932f63c759fb34fc6964",
|
|
50
|
+
"agentConfig": {
|
|
51
|
+
"pluginType": "elizaos:plugin:1.0.0",
|
|
52
|
+
"pluginParameters": {
|
|
53
|
+
"DISCORD_APPLICATION_ID": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "Discord application/client ID used for authenticating the bot with Discord API.",
|
|
56
|
+
"required": true
|
|
57
|
+
},
|
|
58
|
+
"DISCORD_API_TOKEN": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "Discord bot token used to authenticate and connect to Discord API.",
|
|
61
|
+
"required": true
|
|
62
|
+
},
|
|
63
|
+
"CHANNEL_IDS": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Optional comma-separated list of Discord channel IDs the bot is allowed to operate in; if unset the bot works in all channels.",
|
|
66
|
+
"required": false
|
|
67
|
+
},
|
|
68
|
+
"DISCORD_TEST_CHANNEL_ID": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "Discord channel ID for running tests; used if not supplied in runtime settings.",
|
|
71
|
+
"required": false
|
|
72
|
+
},
|
|
73
|
+
"DISCORD_VOICE_CHANNEL_ID": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "Specifies the Discord voice channel ID that the bot should attempt to join before scanning for other available channels.",
|
|
76
|
+
"required": false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|