浏览代码

feat: only copy new positions added after startup

- Add initialization phase to record existing positions
- Store initial positions in memory, skip them during copying
- Only copy positions that appear after bot starts
- Log initial positions for monitoring visibility
- Maintain existing functionality for closing positions
zhangchunrui 1 月之前
父节点
当前提交
fd5abb9f88
共有 1 个文件被更改,包括 49 次插入3 次删除
  1. 49 3
      src/core/sniper.js

+ 49 - 3
src/core/sniper.js

@@ -6,6 +6,8 @@ export class SniperEngine {
   constructor() {
     this.copiedCache = new PositionCache('.copied-positions.json', CONFIG.DATA_DIR);
     this.closedCache = new PositionCache('.closed-positions.json', CONFIG.DATA_DIR);
+    this.initialPositions = new Set(); // Store positions at startup
+    this.hasInitialized = false; // Track if initialization is complete
     this.swapper = new JupiterSwapper();
     this.isRunning = false;
     this.myWallet = CONFIG.MY_WALLET || this.swapper.getWalletAddress();
@@ -123,6 +125,33 @@ export class SniperEngine {
     return success;
   }
 
+  async initialize() {
+    // Fetch all existing positions at startup and mark them as initial positions
+    logger.info('Initializing sniper - checking existing positions...');
+    
+    const { positions, poolMap } = await ByrealAPI.fetchTargetPositions(CONFIG.TARGET_WALLET);
+    
+    if (positions.length === 0) {
+      logger.info('No existing positions found at startup');
+    } else {
+      logger.info(`Found ${positions.length} existing positions at startup - will monitor for new ones only`);
+      
+      for (const position of positions) {
+        const positionAddress = position.positionAddress;
+        this.initialPositions.add(positionAddress);
+        
+        // Log existing positions
+        const poolInfo = poolMap[position.poolAddress];
+        const symbolA = poolInfo?.mintA?.symbol || '?';
+        const symbolB = poolInfo?.mintB?.symbol || '?';
+        logger.info(`  [INITIAL] ${positionAddress} - ${symbolA}/${symbolB} (will not copy)`);
+      }
+    }
+    
+    this.hasInitialized = true;
+    logger.success(`Initialization complete - monitoring for ${this.initialPositions.size} existing positions and new additions only\n`);
+  }
+
   async scanForNewPositions() {
     logger.info(`Scanning for target wallet positions: ${CONFIG.TARGET_WALLET}`);
     
@@ -133,22 +162,36 @@ export class SniperEngine {
       return;
     }
 
-    logger.info(`Found ${positions.length} positions, analyzing...`);
+    // Count new positions (not in initial set)
+    const newPositions = positions.filter(p => !this.initialPositions.has(p.positionAddress));
+    
+    if (newPositions.length === 0) {
+      logger.info(`Found ${positions.length} positions, 0 new - all are from initial scan`);
+      return;
+    }
+
+    logger.info(`Found ${positions.length} total positions, ${newPositions.length} new to analyze...`);
 
-    for (const position of positions) {
+    for (const position of newPositions) {
       const positionAddress = position.positionAddress;
       
+      // Skip if already processed (copied or closed)
       if (this.copiedCache.has(positionAddress) || this.closedCache.has(positionAddress)) {
         continue;
       }
 
+      // Skip if this was an initial position
+      if (this.initialPositions.has(positionAddress)) {
+        continue;
+      }
+
       const poolInfo = poolMap[position.poolAddress];
       if (!poolInfo) {
         logger.warn(`Pool info not found for ${position.poolAddress}`);
         continue;
       }
 
-      logger.info(`\nAnalyzing position: ${positionAddress}`);
+      logger.info(`\n🆕 New position detected: ${positionAddress}`);
       logger.info(`Pool: ${poolInfo.mintA?.symbol || '?'}/${poolInfo.mintB?.symbol || '?'}`);
 
       const analysis = await this.analyzePosition(position, poolInfo);
@@ -219,6 +262,9 @@ export class SniperEngine {
     logger.info(`⏱️ Poll Interval: ${CONFIG.POLL_INTERVAL_MS / 1000}s`);
     logger.info('═══════════════════════════════════════════\n');
 
+    // Initialize: record existing positions but don't copy them
+    await this.initialize();
+
     while (this.isRunning) {
       try {
         await this.scanForNewPositions();