@clonegod/ttd-bsc-common 1.0.39 → 1.0.41

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.
@@ -8,8 +8,8 @@ export declare class SimpleRedisClient {
8
8
  constructor(lock_prefix: string);
9
9
  getRedisClient(): Promise<RedisClientType>;
10
10
  private getLockKey;
11
- private acquireLock;
12
- private releaseLock;
11
+ acquireLock(lock_key: string, lock_value: string, expireSeconds?: number): Promise<boolean>;
12
+ releaseLock(lock_key: string, lock_value: string): Promise<boolean>;
13
13
  withLock<T>(lock_identifier: string, callback: () => Promise<T>, release_lock_delay_ms?: number): Promise<T>;
14
14
  getValue(key: string): Promise<string>;
15
15
  setValue(key: string, value: string, expireSeconds: number): Promise<any>;
@@ -279,115 +279,137 @@ class AbstractEvmDexTradePlus extends dist_1.AbastrcatTrade {
279
279
  if (this.getWalletMode() === 'single') {
280
280
  return this.getSingleWallet();
281
281
  }
282
- const { inputToken } = this.determineInputOutputTokens(context.order_msg, context.pool_info);
283
- console.log('inputToken', inputToken);
284
- const requiredAmount = new decimal_js_1.default(context.order_msg.amount);
285
- const wallet_assets = yield this.redisClient.hgetall(`${this.chainNameLower}:wallet:assets`);
286
- if (!wallet_assets || Object.keys(wallet_assets).length === 0) {
287
- throw new Error('没有找到钱包资产信息,请确保钱包监控服务正在运行');
288
- }
289
- const wallet_assets_map = {};
290
- for (const [walletAddress, assetsJson] of Object.entries(wallet_assets)) {
291
- try {
292
- wallet_assets_map[walletAddress] = JSON.parse(assetsJson);
293
- }
294
- catch (error) {
295
- console.warn(`解析钱包资产数据失败: ${walletAddress}`, error);
282
+ const lockIdentifier = `choose_wallet`;
283
+ const lockKey = `${this.chainNameLower}:lock:${lockIdentifier}`;
284
+ const lockValue = `${Math.random().toString(36).substring(2, 15)}`;
285
+ let lockAcquired = false;
286
+ const start_time = Date.now();
287
+ const maxRetryTime = 1000;
288
+ const retryDelay = 100;
289
+ do {
290
+ lockAcquired = yield this.redisClient.acquireLock(lockKey, lockValue, 1);
291
+ if (lockAcquired) {
292
+ break;
296
293
  }
294
+ yield (0, dist_1.sleep)(retryDelay);
295
+ } while (!lockAcquired && Date.now() - start_time < maxRetryTime);
296
+ if (!lockAcquired) {
297
+ throw new Error(`choose wallet, acquire lock failed: ${lockKey}, took ${Date.now() - start_time}ms`);
297
298
  }
298
- const availableWallets = [];
299
- const allWallets = [];
300
- for (const [walletAddress, assets] of Object.entries(wallet_assets_map)) {
301
- try {
302
- const wallet = (_a = this.group_wallets) === null || _a === void 0 ? void 0 : _a.find(w => w.address.toLowerCase() === walletAddress.toLowerCase());
303
- if (!wallet) {
304
- continue;
299
+ (0, dist_1.log_info)(`choose wallet, acquire lock success: ${lockKey}, took ${Date.now() - start_time}ms`);
300
+ try {
301
+ const { inputToken } = this.determineInputOutputTokens(context.order_msg, context.pool_info);
302
+ const requiredAmount = new decimal_js_1.default(context.order_msg.amount);
303
+ const wallet_assets = yield this.redisClient.hgetall(`${this.chainNameLower}:wallet:assets`);
304
+ if (!wallet_assets || Object.keys(wallet_assets).length === 0) {
305
+ throw new Error('没有找到钱包资产信息,请确保钱包监控服务正在运行');
306
+ }
307
+ const wallet_assets_map = {};
308
+ for (const [walletAddress, assetsJson] of Object.entries(wallet_assets)) {
309
+ try {
310
+ wallet_assets_map[walletAddress] = JSON.parse(assetsJson);
305
311
  }
306
- const tokenAsset = (_b = assets.tokens) === null || _b === void 0 ? void 0 : _b.find((token) => token.tokenaddr.toLowerCase() === inputToken.address.toLowerCase());
307
- let tokenBalance = (tokenAsset === null || tokenAsset === void 0 ? void 0 : tokenAsset.balance) || '0';
308
- const balanceDecimal = new decimal_js_1.default(tokenBalance);
309
- if (balanceDecimal.gte(requiredAmount)) {
310
- availableWallets.push({
312
+ catch (error) {
313
+ console.warn(`解析钱包资产数据失败: ${walletAddress}`, error);
314
+ }
315
+ }
316
+ const availableWallets = [];
317
+ const allWallets = [];
318
+ for (const [walletAddress, assets] of Object.entries(wallet_assets_map)) {
319
+ try {
320
+ const wallet = (_a = this.group_wallets) === null || _a === void 0 ? void 0 : _a.find(w => w.address.toLowerCase() === walletAddress.toLowerCase());
321
+ if (!wallet) {
322
+ continue;
323
+ }
324
+ const tokenAsset = (_b = assets.tokens) === null || _b === void 0 ? void 0 : _b.find((token) => token.tokenaddr.toLowerCase() === inputToken.address.toLowerCase());
325
+ let tokenBalance = (tokenAsset === null || tokenAsset === void 0 ? void 0 : tokenAsset.balance) || '0';
326
+ const balanceDecimal = new decimal_js_1.default(tokenBalance);
327
+ if (balanceDecimal.gte(requiredAmount)) {
328
+ availableWallets.push({
329
+ wallet,
330
+ balance: tokenBalance
331
+ });
332
+ }
333
+ else {
334
+ console.log(`钱包 ${walletAddress} 余额不足: ${tokenBalance} ${inputToken.symbol} < ${requiredAmount} ${inputToken.symbol}`);
335
+ }
336
+ allWallets.push({
311
337
  wallet,
312
338
  balance: tokenBalance
313
339
  });
314
340
  }
315
- else {
316
- console.log(`钱包 ${walletAddress} 余额不足: ${tokenBalance} ${inputToken.symbol} < ${requiredAmount} ${inputToken.symbol}`);
341
+ catch (error) {
342
+ console.warn(`处理钱包资产时出错: ${walletAddress}`, error);
317
343
  }
318
- allWallets.push({
319
- wallet,
320
- balance: tokenBalance
321
- });
322
344
  }
323
- catch (error) {
324
- console.warn(`处理钱包资产时出错: ${walletAddress}`, error);
345
+ if (availableWallets.length === 0) {
346
+ let error_msg = `all wallets are insufficient, required: ${requiredAmount} ${inputToken.symbol}`;
347
+ (0, dist_1.log_warn)(error_msg);
348
+ allWallets.forEach((walletInfo, index) => {
349
+ const shortAddress = walletInfo.wallet.address.substring(0, 6) + '...' + walletInfo.wallet.address.substring(walletInfo.wallet.address.length - 4);
350
+ console.log(`${index + 1}. ${shortAddress}: ${walletInfo.balance} ${inputToken.symbol}`);
351
+ });
352
+ throw new Error(error_msg);
325
353
  }
326
- }
327
- if (availableWallets.length === 0) {
328
- let error_msg = `all wallets are insufficient, required: ${requiredAmount} ${inputToken.symbol}`;
329
- (0, dist_1.log_warn)(error_msg);
330
- allWallets.forEach((walletInfo, index) => {
331
- const shortAddress = walletInfo.wallet.address.substring(0, 6) + '...' + walletInfo.wallet.address.substring(walletInfo.wallet.address.length - 4);
332
- console.log(`${index + 1}. ${shortAddress}: ${walletInfo.balance} ${inputToken.symbol}`);
333
- });
334
- throw new Error(error_msg);
335
- }
336
- console.log('availableWallets', availableWallets.map(w => w.wallet.address));
337
- const wallet_last_used = yield this.redisClient.hgetall(`${this.chainNameLower}:wallet:last_used`);
338
- for (const availableWallet of availableWallets) {
339
- const lastUsedData = wallet_last_used === null || wallet_last_used === void 0 ? void 0 : wallet_last_used[availableWallet.wallet.address];
340
- if (lastUsedData) {
341
- try {
342
- const lastUsedInfo = JSON.parse(lastUsedData);
343
- availableWallet.lastUsedAt = lastUsedInfo.lastUsedAt;
354
+ console.log('availableWallets', availableWallets.map(w => w.wallet.address));
355
+ const wallet_last_used = yield this.redisClient.hgetall(`${this.chainNameLower}:wallet:last_used`);
356
+ for (const availableWallet of availableWallets) {
357
+ const lastUsedData = wallet_last_used === null || wallet_last_used === void 0 ? void 0 : wallet_last_used[availableWallet.wallet.address];
358
+ if (lastUsedData) {
359
+ try {
360
+ const lastUsedInfo = JSON.parse(lastUsedData);
361
+ availableWallet.lastUsedAt = lastUsedInfo.lastUsedAt;
362
+ }
363
+ catch (error) {
364
+ console.warn(`解析钱包最后使用时间失败: ${availableWallet.wallet.address}`, error);
365
+ }
344
366
  }
345
- catch (error) {
346
- console.warn(`解析钱包最后使用时间失败: ${availableWallet.wallet.address}`, error);
367
+ else {
368
+ yield this.redisClient.hsetValue(`${this.chainNameLower}:wallet:last_used`, availableWallet.wallet.address, JSON.stringify({
369
+ lastUsedAt: 0,
370
+ lastUsedTime: new Date(0).toISOString()
371
+ }), 24 * 60 * 60);
372
+ availableWallet.lastUsedAt = 0;
347
373
  }
348
374
  }
349
- else {
350
- yield this.redisClient.hsetValue(`${this.chainNameLower}:wallet:last_used`, availableWallet.wallet.address, JSON.stringify({
351
- lastUsedAt: 0,
352
- lastUsedTime: new Date(0).toISOString()
353
- }), 24 * 60 * 60);
354
- availableWallet.lastUsedAt = 0;
355
- }
356
- }
357
- let selectedWallet;
358
- let selectionStrategy;
359
- if (availableWallets.length === 1) {
360
- selectedWallet = availableWallets[0].wallet;
361
- selectionStrategy = 'OnlyOne';
362
- }
363
- else {
364
- const hasUsageHistory = wallet_last_used && Object.keys(wallet_last_used).length > 0;
365
- if (hasUsageHistory) {
366
- availableWallets.sort((a, b) => {
367
- const aTime = a.lastUsedAt || 0;
368
- const bTime = b.lastUsedAt || 0;
369
- return aTime - bTime;
370
- });
375
+ let selectedWallet;
376
+ let selectionStrategy;
377
+ if (availableWallets.length === 1) {
371
378
  selectedWallet = availableWallets[0].wallet;
372
- selectionStrategy = 'MaxLastUsed';
379
+ selectionStrategy = 'OnlyOne';
373
380
  }
374
381
  else {
375
- availableWallets.sort((a, b) => {
376
- const aBalance = new decimal_js_1.default(a.balance);
377
- const bBalance = new decimal_js_1.default(b.balance);
378
- return bBalance.cmp(aBalance);
379
- });
380
- selectedWallet = availableWallets[0].wallet;
381
- selectionStrategy = 'MaxBalance';
382
+ const hasUsageHistory = wallet_last_used && Object.keys(wallet_last_used).length > 0;
383
+ if (hasUsageHistory) {
384
+ availableWallets.sort((a, b) => {
385
+ const aTime = a.lastUsedAt || 0;
386
+ const bTime = b.lastUsedAt || 0;
387
+ return aTime - bTime;
388
+ });
389
+ selectedWallet = availableWallets[0].wallet;
390
+ selectionStrategy = 'MaxLastUsed';
391
+ }
392
+ else {
393
+ availableWallets.sort((a, b) => {
394
+ const aBalance = new decimal_js_1.default(a.balance);
395
+ const bBalance = new decimal_js_1.default(b.balance);
396
+ return bBalance.cmp(aBalance);
397
+ });
398
+ selectedWallet = availableWallets[0].wallet;
399
+ selectionStrategy = 'MaxBalance';
400
+ }
382
401
  }
402
+ yield this.redisClient.hsetValue(`${this.chainNameLower}:wallet:last_used`, selectedWallet.address, JSON.stringify({
403
+ lastUsedAt: Date.now(),
404
+ lastUsedTime: new Date().toISOString()
405
+ }), 24 * 60 * 60);
406
+ const selectedWalletInfo = availableWallets.find(w => w.wallet.address === selectedWallet.address);
407
+ (0, dist_1.log_info)(`Choose wallet: ${selectionStrategy} -> ${selectedWallet.address}, balance: ${selectedWalletInfo === null || selectedWalletInfo === void 0 ? void 0 : selectedWalletInfo.balance} ${inputToken.symbol}, required: ${requiredAmount} ${inputToken.symbol}`);
408
+ return selectedWallet;
409
+ }
410
+ finally {
411
+ yield this.redisClient.releaseLock(lockKey, lockValue);
383
412
  }
384
- yield this.redisClient.hsetValue(`${this.chainNameLower}:wallet:last_used`, selectedWallet.address, JSON.stringify({
385
- lastUsedAt: Date.now(),
386
- lastUsedTime: new Date().toISOString()
387
- }), 24 * 60 * 60);
388
- const selectedWalletInfo = availableWallets.find(w => w.wallet.address === selectedWallet.address);
389
- (0, dist_1.log_info)(`Choose wallet: ${selectionStrategy} -> ${selectedWallet.address}, balance: ${selectedWalletInfo === null || selectedWalletInfo === void 0 ? void 0 : selectedWalletInfo.balance} ${inputToken.symbol}, required: ${requiredAmount} ${inputToken.symbol}`);
390
- return selectedWallet;
391
413
  });
392
414
  }
393
415
  determineInputOutputTokens(order_msg, pool_info) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-bsc-common",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "BSC common library",
5
5
  "license": "UNLICENSED",
6
6
  "main": "dist/index.js",