Ver Fonte

开始测试

龚成明 há 2 anos atrás
pai
commit
ebded6ad12

+ 450 - 631
abi/UNIV2_TOOLS_ABI.json

@@ -1,633 +1,452 @@
 [
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "tokenIn",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "tokenOut",
-				"type": "address"
-			},
-			{
-				"internalType": "uint24",
-				"name": "fee",
-				"type": "uint24"
-			},
-			{
-				"internalType": "uint256",
-				"name": "amountOut",
-				"type": "uint256"
-			},
-			{
-				"internalType": "uint160",
-				"name": "sqrtPriceLimitX96",
-				"type": "uint160"
-			}
-		],
-		"name": "getAmountInV3",
-		"outputs": [
-			{
-				"internalType": "uint256",
-				"name": "amountIn",
-				"type": "uint256"
-			}
-		],
-		"stateMutability": "nonpayable",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "tokenIn",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "tokenOut",
-				"type": "address"
-			},
-			{
-				"internalType": "uint24",
-				"name": "fee",
-				"type": "uint24"
-			},
-			{
-				"internalType": "uint256",
-				"name": "amountIn",
-				"type": "uint256"
-			},
-			{
-				"internalType": "uint160",
-				"name": "sqrtPriceLimitX96",
-				"type": "uint160"
-			}
-		],
-		"name": "getAmountOutV3",
-		"outputs": [
-			{
-				"internalType": "uint256",
-				"name": "amountOut",
-				"type": "uint256"
-			}
-		],
-		"stateMutability": "nonpayable",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "token",
-				"type": "address"
-			}
-		],
-		"name": "get_decimals",
-		"outputs": [
-			{
-				"internalType": "uint8",
-				"name": "",
-				"type": "uint8"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "token",
-				"type": "address"
-			}
-		],
-		"name": "get_symbol",
-		"outputs": [
-			{
-				"internalType": "string",
-				"name": "",
-				"type": "string"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "token",
-				"type": "address"
-			}
-		],
-		"name": "getDecimals",
-		"outputs": [
-			{
-				"internalType": "uint8",
-				"name": "",
-				"type": "uint8"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "rounteAddr",
-				"type": "address"
-			}
-		],
-		"name": "getFactory",
-		"outputs": [
-			{
-				"internalType": "address",
-				"name": "factoryAdd",
-				"type": "address"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address[]",
-				"name": "factoryAddr",
-				"type": "address[]"
-			},
-			{
-				"internalType": "address",
-				"name": "token0",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "token1",
-				"type": "address"
-			}
-		],
-		"name": "getPairAddS",
-		"outputs": [
-			{
-				"internalType": "address[]",
-				"name": "pairAdds",
-				"type": "address[]"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "rounteAddr",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "token0",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "token1",
-				"type": "address"
-			},
-			{
-				"internalType": "bool",
-				"name": "stable",
-				"type": "bool"
-			}
-		],
-		"name": "getPairAddV1",
-		"outputs": [
-			{
-				"internalType": "address",
-				"name": "",
-				"type": "address"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "factoryAddr",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "token0",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "token1",
-				"type": "address"
-			}
-		],
-		"name": "getPairAddV2",
-		"outputs": [
-			{
-				"internalType": "address",
-				"name": "",
-				"type": "address"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "dex",
-				"type": "address"
-			}
-		],
-		"name": "getPairBalance",
-		"outputs": [
-			{
-				"internalType": "uint112",
-				"name": "amount0",
-				"type": "uint112"
-			},
-			{
-				"internalType": "uint112",
-				"name": "amount1",
-				"type": "uint112"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "factoryAddr",
-				"type": "address"
-			},
-			{
-				"internalType": "uint256",
-				"name": "id",
-				"type": "uint256"
-			}
-		],
-		"name": "getPairIdInfo",
-		"outputs": [
-			{
-				"internalType": "address",
-				"name": "",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "",
-				"type": "address"
-			},
-			{
-				"internalType": "string",
-				"name": "",
-				"type": "string"
-			},
-			{
-				"internalType": "uint8",
-				"name": "",
-				"type": "uint8"
-			},
-			{
-				"internalType": "uint256",
-				"name": "",
-				"type": "uint256"
-			},
-			{
-				"internalType": "address",
-				"name": "",
-				"type": "address"
-			},
-			{
-				"internalType": "string",
-				"name": "",
-				"type": "string"
-			},
-			{
-				"internalType": "uint8",
-				"name": "",
-				"type": "uint8"
-			},
-			{
-				"internalType": "uint256",
-				"name": "",
-				"type": "uint256"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "factoryAddr",
-				"type": "address"
-			},
-			{
-				"internalType": "uint256[]",
-				"name": "id",
-				"type": "uint256[]"
-			}
-		],
-		"name": "getPairIdSInfo",
-		"outputs": [
-			{
-				"internalType": "address[]",
-				"name": "lp",
-				"type": "address[]"
-			},
-			{
-				"internalType": "address[]",
-				"name": "token0",
-				"type": "address[]"
-			},
-			{
-				"internalType": "string[]",
-				"name": "symbol0",
-				"type": "string[]"
-			},
-			{
-				"internalType": "uint8[]",
-				"name": "decimals0",
-				"type": "uint8[]"
-			},
-			{
-				"internalType": "uint256[]",
-				"name": "r0",
-				"type": "uint256[]"
-			},
-			{
-				"internalType": "address[]",
-				"name": "token1",
-				"type": "address[]"
-			},
-			{
-				"internalType": "string[]",
-				"name": "symbol1",
-				"type": "string[]"
-			},
-			{
-				"internalType": "uint8[]",
-				"name": "decimals1",
-				"type": "uint8[]"
-			},
-			{
-				"internalType": "uint256[]",
-				"name": "r1",
-				"type": "uint256[]"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "pairAdd",
-				"type": "address"
-			}
-		],
-		"name": "getPairInfo",
-		"outputs": [
-			{
-				"components": [
-					{
-						"internalType": "address",
-						"name": "lp",
-						"type": "address"
-					},
-					{
-						"internalType": "address",
-						"name": "token0",
-						"type": "address"
-					},
-					{
-						"internalType": "string",
-						"name": "symbol0",
-						"type": "string"
-					},
-					{
-						"internalType": "uint8",
-						"name": "decimals0",
-						"type": "uint8"
-					},
-					{
-						"internalType": "uint256",
-						"name": "r0",
-						"type": "uint256"
-					},
-					{
-						"internalType": "address",
-						"name": "token1",
-						"type": "address"
-					},
-					{
-						"internalType": "string",
-						"name": "symbol1",
-						"type": "string"
-					},
-					{
-						"internalType": "uint8",
-						"name": "decimals1",
-						"type": "uint8"
-					},
-					{
-						"internalType": "uint256",
-						"name": "r1",
-						"type": "uint256"
-					},
-					{
-						"internalType": "uint24",
-						"name": "fee",
-						"type": "uint24"
-					}
-				],
-				"internalType": "struct dexInfoTools.PairInfo",
-				"name": "pairInfo",
-				"type": "tuple"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "uint256",
-				"name": "id",
-				"type": "uint256"
-			}
-		],
-		"name": "getPairInfoV3",
-		"outputs": [
-			{
-				"components": [
-					{
-						"internalType": "address",
-						"name": "lp",
-						"type": "address"
-					},
-					{
-						"internalType": "address",
-						"name": "token0",
-						"type": "address"
-					},
-					{
-						"internalType": "string",
-						"name": "symbol0",
-						"type": "string"
-					},
-					{
-						"internalType": "uint8",
-						"name": "decimals0",
-						"type": "uint8"
-					},
-					{
-						"internalType": "uint256",
-						"name": "r0",
-						"type": "uint256"
-					},
-					{
-						"internalType": "address",
-						"name": "token1",
-						"type": "address"
-					},
-					{
-						"internalType": "string",
-						"name": "symbol1",
-						"type": "string"
-					},
-					{
-						"internalType": "uint8",
-						"name": "decimals1",
-						"type": "uint8"
-					},
-					{
-						"internalType": "uint256",
-						"name": "r1",
-						"type": "uint256"
-					},
-					{
-						"internalType": "uint24",
-						"name": "fee",
-						"type": "uint24"
-					}
-				],
-				"internalType": "struct dexInfoTools.PairInfo",
-				"name": "pairInfo",
-				"type": "tuple"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address[]",
-				"name": "path",
-				"type": "address[]"
-			}
-		],
-		"name": "getPairSBalance",
-		"outputs": [
-			{
-				"internalType": "uint112[]",
-				"name": "amounts0",
-				"type": "uint112[]"
-			},
-			{
-				"internalType": "uint112[]",
-				"name": "amounts1",
-				"type": "uint112[]"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "tokenA",
-				"type": "address"
-			},
-			{
-				"internalType": "address",
-				"name": "tokenB",
-				"type": "address"
-			},
-			{
-				"internalType": "uint24",
-				"name": "fee",
-				"type": "uint24"
-			}
-		],
-		"name": "getPoolV3",
-		"outputs": [
-			{
-				"internalType": "address",
-				"name": "pool",
-				"type": "address"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "token",
-				"type": "address"
-			}
-		],
-		"name": "getSymbol",
-		"outputs": [
-			{
-				"internalType": "string",
-				"name": "",
-				"type": "string"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	},
-	{
-		"inputs": [
-			{
-				"internalType": "address",
-				"name": "rounteAddr",
-				"type": "address"
-			}
-		],
-		"name": "getTotalPair",
-		"outputs": [
-			{
-				"internalType": "uint256",
-				"name": "counts",
-				"type": "uint256"
-			}
-		],
-		"stateMutability": "view",
-		"type": "function"
-	}
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      }
+    ],
+    "name": "fee_Cal",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      }
+    ],
+    "name": "feeCal1",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      },
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "token",
+        "type": "address"
+      }
+    ],
+    "name": "get_decimals",
+    "outputs": [
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "token",
+        "type": "address"
+      }
+    ],
+    "name": "get_symbol",
+    "outputs": [
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "token",
+        "type": "address"
+      }
+    ],
+    "name": "getDecimals",
+    "outputs": [
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      }
+    ],
+    "name": "getFactory",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "factoryAdd",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "token0",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "token1",
+        "type": "address"
+      }
+    ],
+    "name": "getPairAdd",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address[]",
+        "name": "factoryAddr",
+        "type": "address[]"
+      },
+      {
+        "internalType": "address",
+        "name": "token0",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "token1",
+        "type": "address"
+      }
+    ],
+    "name": "getPairAddS",
+    "outputs": [
+      {
+        "internalType": "address[]",
+        "name": "pairAdds",
+        "type": "address[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "dex",
+        "type": "address"
+      }
+    ],
+    "name": "getPairBalance",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "amount0",
+        "type": "uint256"
+      },
+      {
+        "internalType": "uint256",
+        "name": "amount1",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256",
+        "name": "id",
+        "type": "uint256"
+      }
+    ],
+    "name": "getPairIdInfo",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      },
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      },
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      },
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      },
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      },
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256[]",
+        "name": "id",
+        "type": "uint256[]"
+      }
+    ],
+    "name": "getPairIdSInfo",
+    "outputs": [
+      {
+        "internalType": "address[]",
+        "name": "lp",
+        "type": "address[]"
+      },
+      {
+        "internalType": "address[]",
+        "name": "token0",
+        "type": "address[]"
+      },
+      {
+        "internalType": "string[]",
+        "name": "symbol0",
+        "type": "string[]"
+      },
+      {
+        "internalType": "uint8[]",
+        "name": "decimals0",
+        "type": "uint8[]"
+      },
+      {
+        "internalType": "uint256[]",
+        "name": "r0",
+        "type": "uint256[]"
+      },
+      {
+        "internalType": "address[]",
+        "name": "token1",
+        "type": "address[]"
+      },
+      {
+        "internalType": "string[]",
+        "name": "symbol1",
+        "type": "string[]"
+      },
+      {
+        "internalType": "uint8[]",
+        "name": "decimals1",
+        "type": "uint8[]"
+      },
+      {
+        "internalType": "uint256[]",
+        "name": "r1",
+        "type": "uint256[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "pairAdd",
+        "type": "address"
+      }
+    ],
+    "name": "getPairInfo",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      },
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      },
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      },
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      },
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      },
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      },
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address[]",
+        "name": "path",
+        "type": "address[]"
+      }
+    ],
+    "name": "getPairSBalance",
+    "outputs": [
+      {
+        "internalType": "uint256[]",
+        "name": "amounts0",
+        "type": "uint256[]"
+      },
+      {
+        "internalType": "uint256[]",
+        "name": "amounts1",
+        "type": "uint256[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "token",
+        "type": "address"
+      }
+    ],
+    "name": "getSymbol",
+    "outputs": [
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "rounteAddr",
+        "type": "address"
+      }
+    ],
+    "name": "getTotalPair",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "counts",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  }
 ]

+ 184 - 151
config/router-list.json

@@ -1,186 +1,219 @@
 [
   {
-    "name": "V1.Solidly",
-    "router": "0x0000000000000000000000000000000000000000",
-    "factory": "0x3faab499b519fdc5819e3d7ed0c26111904cbc28",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "Octo",
+    "router": "0x009541cfbdbb00e5cf9f3d7638b551f634e32b31",
+    "hash": "0x3a69e908fa1614e445720ab816a0cd51e5dc6fec",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "V1.SpiritSwap",
-    "router": "0x0000000000000000000000000000000000000000",
-    "factory": "0x9d3591719038752db0c8beee2040ffcc3b2c6b9c",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "Alien",
+    "router": "0x7a76e55aaa625e1e56d0dde79e391e5cbb59d097",
+    "hash": "0xC51C4Ba282509085013094be4E23144104Ab955F",
+    "fee": 10000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "UNIWD2",
+    "router": "0xd61d0b11041e3df0df912976ecbef37e51d69742",
+    "hash": "0xfa969454d450dfb86a2dceffec48529f799f4a69",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "v1Base",
+    "name": "ETHW",
+    "router": "0x667ea65560ad4b84c91b5cb164241197cf60ffee",
+    "hash": "0x78376072f4945b2a5450b1a6b41a85ff20034527",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "Miner",
+    "router": "0x8f048e25fEcd0AFdE2af78d9966C010D94e76aEc",
+    "hash": "0x91836D77AF0A5fdA36C5a1F3c11DbC7766dE4D03",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "Ethswap",
     "router": "0x0000000000000000000000000000000000000000",
-    "factory": "0x535646cf57e4155df723bb24625f356d98ae9d2f",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "hash": "0x8BF922dA8E2CC0c094AB4827f660e17542cC30A3",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Spirit",
-    "router": "0x16327e3fbdaca3bcf7e38f5af2599d2ddc33ae52",
-    "factory": "0xef45d134b73241eda7703fa787148d9c9f4950b0",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "UNIE96",
+    "router": "0x2eEBfF016c28e924F315F01A6ee4beF6C058ec55",
+    "hash": "0xE96276F040Bb3619BC2F104f9E8Caa51eE3C1812",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Spooky",
-    "router": "0xf491e7b69e4244ad4002bc14e878a34207e38c29",
-    "factory": "0x152ee697f2e276fa89e96742e9bb9ab1f2e61be3",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "AAA",
+    "router": "0x0000000000000000000000000000000000000000",
+    "hash": "0xfA969454d450dFB86a2dCeFfEc48529F799F4a69",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Dfyn",
-    "router": "0x2724b9497b2cf3325c6be3ea430b3cec34b5ef2d",
-    "factory": "0xd9820a17053d6314b20642e465a84bf01a3d64f5",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "POWER",
+    "router": "0x0000000000000000000000000000000000000000",
+    "hash": "0xD51CFEb0fa23101f67cF62EB02D0a82A4BaD52b7",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Jet",
-    "router": "0x845e76a8691423fbc4ecb8dd77556cb61c09ee25",
-    "factory": "0xf6488205957f0b4497053d6422f49e27944ee3dd",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "SEA",
+    "router": "0xc0Fb1f3100e8Fb477e9E42F748e94884CEc03810",
+    "hash": "0x1Ee0fe7f80BeA6353b137B2E7DCA9e26F3c6F442",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Tomb",
-    "router": "0x6d0176c5ea1e44b08d3dd001b0784ce42f47a3a7",
-    "factory": "0xe236f6890f1824fa0a7ffc39b1597a5a6077cfe9",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "CRO",
+    "router": "0xCeB90E4C17d626BE0fACd78b79c9c87d7ca181b3",
+    "hash": "0x9DEB29c9a4c7A88a3C0257393b7f3335338D9A9D",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Bomb",
-    "router": "0xb9799de71100e20ac1cdbcc63c69dda2d0d81710",
-    "factory": "0xd9473a05b2edf4f614593ba5d1dbd3021d8e0ebe",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "SUSHI",
+    "router": "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f",
+    "hash": "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Sushi",
-    "router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506",
-    "factory": "0xc35dadb65012ec5796536bd9864ed8773abc74c4",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "EQ",
+    "router": "0xf6A86EAA9Ea0F38F66B3718114AE79acaf35e02F",
+    "hash": "0xF14421F0BCf9401d8930872C2d44d8e67e40529a",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Red",
-    "router": "0x6726a3c9afd89ce0beac9a7f6d3cc6870dd26331",
-    "factory": "0xa2df50d1401aff182d19bb41d76cf35953942c51",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "SHIBA",
+    "router": "0x03f7724180aa6b939894b5ca4314783b0b36b329",
+    "hash": "0x115934131916C8b277DD010Ee02de363c09d037c",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Wigo",
-    "router": "0x5023882f4d1ec10544fcb2066abe9c1645e95aa0",
-    "factory": "0xc831a5cbfb4ac2da5ed5b194385dfd9bf5bfcba7",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "DOOAR",
+    "router": "0x53e0e51b5ed9202110d7ecd637a4581db8b9879f",
+    "hash": "0x1e895bFe59E3A5103e8B7dA3897d1F2391476f3c",
+    "fee": 10000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "PPK",
-    "router": "0xad362c30b2991a154651b05181fe6bed795a9792",
-    "factory": "0x7ceb5f3a6d1888eec74a41a5377afba5b97200ea",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "SAITA",
+    "router": "0x0c17e776cd218252adfca8d4e761d3fe757e9778",
+    "hash": "0x35113a300ca0D7621374890ABFEAC30E88f214b1",
+    "fee": "2000",
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Waka",
-    "router": "0x7b17021fcb7bc888641dc3bedfed3734fcaf2c87",
-    "factory": "0xb2435253c71fca27be41206eb2793e44e1df6b6d",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "RADIO",
+    "router": "0x3e445e3280c5747a188db8d0ab7762838a50e4ff",
+    "hash": "0x91fAe1bc94A9793708fbc66aDcb59087C46dEe10",
+    "fee": "1000",
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "Elk",
-    "router": "0x4d2cf285a519261f30b4d9c2c344baf260d65fa2",
-    "factory": "0x7ba73c99e6f01a37f3e33854c8f544bbbadd3420",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "UP",
+    "router": "0xe6e90bc9f3b95cdb69f48c7bfdd0ede1386b135a",
+    "hash": "0xbAcC776b231c571a7e6ab7Bc2C8a099e07153377",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
   },
   {
-    "name": "AAA",
-    "router": "0x67a937ea41cd05ec8c832a044afc0100f30aa4b5",
-    "factory": "0xbfd1ce8e6d85e911e80c169293d5c1f5c950fe03",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "Magik",
-    "router": "0xc1d27b206bdecdb31e238098241022f4319f3d1c",
-    "factory": "0x349d953ca03c9d63c040d463545e21fe4b713c2e",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "Wing",
-    "router": "0x2b660040b289b1b570e053b21dd9a6f1067ad7f5",
-    "factory": "0xc0719a9a35a2d9ebbfdf1c6d383a5e8e7b2ef7a8",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "DOA",
-    "router": "0x4e2a57a8ffe65f794e9a32637bc67b502ffc84c6",
-    "factory": "0x5ef0153590d4a762f129dcf3c59186d91365e4e1",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "Dark",
-    "router": "0x045312c737a6b7a115906be0ad0ef53a6aa38106",
-    "factory": "0x7d82f56ea0820a9d42b01c3c28f1997721732218",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "Frax",
-    "router": "0xa007a9716dba05289df85a90d0fd9d39bee808de",
-    "factory": "0xf55c563148ca0c0f1626834ec1b8651844d76792",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "ProTo",
-    "router": "0xf4c587a0972ac2039bff67bc44574bb403ef5235",
-    "factory": "0x39720e5fe53beeeb9de4759cb91d8e7d42c17b76",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
-  },
-  {
-    "name": "PTD",
-    "router": "0xe4a4642b19c4d0cba965673cd51422b1eda0a78d",
-    "factory": "0xc5bc174cb6382fbab17771d05e6a918441deceea",
-    "fee": "3000",
-    "type": "univ2",
-    "chain": "ftm"
+    "name": "EW",
+    "router": "0x0000000000000000000000000000000000000000",
+    "hash": "0x78376072F4945b2A5450B1A6B41a85ff20034527",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "UNIV2",
+    "router": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
+    "hash": "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "LFG",
+    "router": "0x4f381d5fF61ad1D0eC355fEd2Ac4000eA1e67854",
+    "hash": "0xf66cef53c518659bfa0a9a4aa07445af08bf9b3a",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "UNIW",
+    "router": "0x633e494C22D163F798b25b0264b92Ac612645731",
+    "hash": "0xaBC4325bAD182076EAa5877c68437833d596D3Ee",
+    "fee": "1700",
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "POW",
+    "router": "0x6851e767Aaa9C4674Fe8cAE95AFCc819b7Fb0403",
+    "hash": "0x62009bD6349A3A1d7f1bcC7C69492Cd26F1FBF75",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "HIP",
+    "router": "0x8F2a57bbC2B3870Ed321541F091f9A3EbE008Ad4",
+    "hash": "0x8cF9A887e53be909C221A2708E72898546dAB7Cc",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "UNIW2",
+    "router": "0xf19eb68da923d28c78f2c640fb5ddbc07868cdcf",
+    "hash": "0xfa969454d450dfb86a2dceffec48529f799f4a69",
+    "fee": 3000,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "CakeW",
+    "router": "0xb8dad6ef36940a7c881980860ea28822994e22bd",
+    "hash": "0xe97352E2d3a4F418044a91533a2379dbd11b425d",
+    "fee": 2500,
+    "version": "univ2",
+    "chainId": 10001
+  },
+  {
+    "name": "UNIV3",
+    "hash": "0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f",
+    "router": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
+    "positionManager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
+    "fee": 0,
+    "version": "univ3",
+    "chainId": 10001
   }
 ]

+ 11 - 1
model/base-model.js

@@ -3,7 +3,10 @@ module.exports = class BaseModel {
   static MODULES = {
     HISTORY: 'history',
     PENDING: 'pending',
-    FACTORY: 'factory'
+    FACTORY: 'factory',
+    TOKEN: 'token',
+    V2_LP: 'v2-lp',
+    V3_LP: 'v3-lp'
   }
 
   constructor(chainId, module) {
@@ -21,4 +24,11 @@ module.exports = class BaseModel {
 
     return rst.data
   }
+
+  async appendOrUpdate(data) {
+    const url = `/${this.module}/appendOrUpdate`
+    const rst = await http.post(url, data)
+
+    return rst.data
+  }
 }

+ 21 - 0
scripts/aux/insertFactory.js

@@ -0,0 +1,21 @@
+const BaseModel = require("../../model/base-model");
+const routerList = require("../../config/router-list.json")
+const logger = require("../../utils/logger")
+
+async function main() {
+  const factoryModel = new BaseModel(-1, BaseModel.MODULES.FACTORY)
+
+  for (const router of routerList) {
+    if (router.hash) router.hash = router.hash.toLowerCase()
+    if (router.router) router.router = router.router.toLowerCase()
+    if (router.positionManager) router.positionManager = router.positionManager.toLowerCase()
+
+    // logger.info(router)
+    logger.info(await factoryModel.appendOrUpdate(router))
+  }
+}
+
+main().catch((error) => {
+  console.error(error);
+  process.exitCode = 1;
+})

+ 35 - 75
scripts/generate/index.js

@@ -1,41 +1,53 @@
 const Web3Utils = require('../../utils/web3-utils')
 const logger = require("../../utils/logger")
-const BigNumber = require('ethers').BigNumber
-const ierc20abi = require('../../abi/IERC20_ABI.json')
-const contracts = require('../../config/contracts')
 const Time = require("../../utils/time")
 const ChainLib = require("../lib/chain-lib")
 const FactoryLib = require("../lib/factory-lib")
-const BaseModel = require("../../model/base-model")
+const LpLib = require("../lib/lp-lib")
+const StateLib = require("../lib/state-lib")
+const TokenLib = require("../lib/token-lib")
 
 class LpGenerate {
-  tokenInstance = {}
-  lpInstance = {}
-
   constructor(web3, chain) {
     this.web3 = web3
     this.chain = chain
 
-    // 初始化V2工具箱
-    this.v2ToolAbi = require('../../abi/UNIV2_TOOLS_ABI.json')
-    this.v2Tool = new this.web3.eth.Contract(this.v2ToolAbi, this.chain.v2ToolAddress)
-    this.v2FactoryAbi = require('../../abi/UNIV2_FACTORY_ABI.json')
-    // 初始化V3工具箱
-    this.positionManagerAbi = require('../../abi/UNIV3_POSITION_MANAGER_ABI.json')
-    this.v3ToolAbi = require('../../abi/UNIV3_TOOLS_ABI.json')
-    this.v3Tool = new this.web3.eth.Contract(this.v3ToolAbi, this.chain.v3ToolAddress)
-    // 初始化factory接口
-    this.factoryModel = new BaseModel(this.chain.id, BaseModel.MODULES.FACTORY)
+    // 初始化依赖库
+    this.factoryLib = new FactoryLib(this.web3, this.chain)
+    this.tokenLib = new TokenLib(this.web3, this.chain)
+    this.lpLib = new LpLib(this.web3, this.chain, this.factoryLib, this.tokenLib)
   }
 
   async tick() {
     // 3.1. 拉取指定链所有factory
-    const factoryList = await FactoryLib.getFactoryList(this.factoryModel)
-    logger.info(factoryList)
-    // 3.2. 拉取指定factory的拉取情况
-    // 3.3. 从指定位置开始拉取lp
-    // 3.3.1 更新或新增lp
-    // 3.3.2 更新或新增token
+    const factoryList = await this.factoryLib.getFactoryList()
+
+    // 3.2 循环处理所有factory
+    for (let factory of factoryList) {
+      // 3.2.1 拉取指定factory的拉取情况
+      let nextPosition = 0 // TODO 先都从0开始
+      let pairsLength = await this.factoryLib.getPairsLength(factory)
+
+      // 3.2.2 从指定位置开始拉取lp
+      for (let position = nextPosition; position < pairsLength; position++) {
+        // 3.2.2.1 拉取lp
+        const lp = await this.lpLib.getLpByPosition(factory, position)
+        if (lp) {
+          // 3.2.2.2 构造token0, token1
+          const token0 = await this.tokenLib.parseToken(lp, true)
+          const token1 = await this.tokenLib.parseToken(lp, false)
+          // 3.2.2.3 更新或新增lp
+          logger.info(await this.lpLib.saveLp(factory, lp))
+          // 3.3.2.4 更新或新增token
+          logger.info(await this.tokenLib.saveToken(token0))
+          logger.info(await this.tokenLib.saveToken(token1))
+
+          logger.debug(`${position + 1} / ${pairsLength}, ${lp.name}-${lp.hash}-${this.chain.networkName}`)
+        } else {
+          logger.debug(`lp get filed. ${position + 1} / ${pairsLength}, ${factory.name}-${factory.router}-${this.chain.networkName}`)
+        }
+      }
+    }
   }
 
   async run() {
@@ -52,58 +64,6 @@ class LpGenerate {
 
       await Time.delay(12000)
     }
-
-
-    // while (true) {
-    //   for (const routerObj of routerList) {
-    //     try {
-    //       let pairsLength = 0
-    //
-    //       const factoryAddress = routerObj.factory
-    //       // 获取当前pull状态
-    //       let position = await this.handlePosition(routerObj)
-    //       let v2Factory = undefined
-    //       // v2,v3分开处理
-    //       if (routerObj.type === 'univ2') {
-    //         // 获取工厂实例
-    //         v2Factory = this.parseFactory(routerObj, v2FactoryAbi, factoryAddress)
-    //         // 获取当前pairsLength
-    //         pairsLength = await v2Factory.methods.allPairsLength().call()
-    //       }
-    //       // 如果有未获取的池子
-    //       const haveNewLp = position < pairsLength
-    //
-    //       // 打印信息
-    //       if (haveNewLp) {
-    //         logger.debug(`Router address: ${routerObj.router}`)
-    //         if (routerObj.type === 'univ2') {
-    //           logger.debug(`factory: ${factoryAddress}, ${position} / ${pairsLength}.`)
-    //         } else {
-    //           logger.debug(`position: ${routerObj.position}, ${position} / ${pairsLength}.`)
-    //         }
-    //       }
-    //
-    //       // 挨个处理lp信息
-    //       for (; position < pairsLength; position++) {
-    //         await this.handleLp(position, pairsLength, routerObj, v2ToolBy410)
-    //       }
-    //
-    //       if (haveNewLp) {
-    //         if (routerObj.type === 'univ2') {
-    //           await History.appendOrUpdate('UNIV2DEX', routerObj.factory, {"next": position})
-    //         }
-    //
-    //         logger.debug('')
-    //         logger.debug('')
-    //         logger.debug('')
-    //       }
-    //     } catch (e) {
-    //       logger.debug(e)
-    //     }
-    //   }
-    //
-    //   await Time.delay(12000)
-    // }
   }
 }
 

+ 129 - 6
scripts/lib/factory-lib.js

@@ -1,8 +1,23 @@
 const logger = require("../../utils/logger")
+const BaseModel = require("../../model/base-model");
 
 module.exports = class FactoryLib {
-  static async getFactoryList(baseModel) {
-    const requestRst = await baseModel.find()
+  constructor(web3, chain) {
+    this.web3 = web3
+    this.chain = chain
+    
+    this.factoryModel = new BaseModel(this.chain.id, BaseModel.MODULES.FACTORY)
+
+    this.factoryContractMap = {}
+    this.positionManagerContractMap = {}
+
+    // abi加载
+    this.v2FactoryAbi = require('../../abi/UNIV2_FACTORY_ABI.json')
+    this.positionManagerAbi = require('../../abi/UNIV3_POSITION_MANAGER_ABI.json')
+  }
+
+  async getFactoryList() {
+    const requestRst = await this.factoryModel.find()
 
     if (requestRst.state) {
       return requestRst.data
@@ -13,11 +28,119 @@ module.exports = class FactoryLib {
     }
   }
 
-  static parseFactory(router, factoryAbi, factoryAddress) {
-    if (router.factoryObj === null) {
-      router.factoryObj = new web3.eth.Contract(factoryAbi, factoryAddress)
+  getFactoryContract(factoryAddress) {
+    if (!this.factoryContractMap[factoryAddress]) {
+      this.factoryContractMap[factoryAddress] = new this.web3.eth.Contract(this.v2FactoryAbi, factoryAddress)
+    }
+
+    return this.factoryContractMap[factoryAddress]
+  }
+
+  getPositionManager(positionManagerAddress) {
+    if (!this.positionManagerContractMap[positionManagerAddress]) {
+      this.positionManagerContractMap[positionManagerAddress] = new this.web3.eth.Contract(this.positionManagerAbi, positionManagerAddress)
+    }
+
+    return this.positionManagerContractMap[positionManagerAddress]
+  }
+
+  async getPositionLength(positionManagerContract, low) {
+    let high = 1_000_000
+
+    let checkNumber = low
+    let prevLow = low
+    let prevHigh = high
+
+    async function check(checkNumber) {
+      async function final_check(checkNumber) {
+        try {
+          await positionManagerContract.methods.positions(checkNumber).call()
+
+          return true
+        } catch (e) {
+          return false
+        }
+      }
+
+      // [,,,,,c(,,,,,,,)]
+      let too_low = false
+      for (let i = 1; i <= 5; i++) {
+        too_low = too_low || (await final_check(checkNumber + i))
+      }
+      if (too_low) return 'too_low'
+
+      // [,,,,,(c,,,,,,,)]
+      let too_high = true
+      for (let i = 0; i < 5; i++) {
+        too_high = too_high && (!await final_check(checkNumber + i))
+      }
+      if (too_high) return 'too_high'
+
+      return 'ok'
     }
 
-    return router.factoryObj
+    let count = 60
+    while (--count > 0) {
+      let checkRst = await check(checkNumber)
+      // logger.debug(`[${low}, ${high}], c: ${checkNumber}, ${checkRst}. [${++count}]`)
+
+      if (checkRst === 'ok') {
+        break
+      } else {
+        let tempHigh = high
+        let tempLow = low
+
+        if (checkNumber === low) {
+          if (checkRst === 'too_high') {
+            high = tempLow
+            low = prevLow
+
+            prevHigh = tempHigh
+            prevLow = tempLow
+
+            checkNumber = high
+          } else if (checkRst === 'too_low') {
+            low = low + Math.floor((high - low) / 2)
+
+            prevLow = tempLow
+
+            checkNumber = low
+          }
+        } else if (checkNumber === high) {
+          if (checkRst === 'too_high') {
+            high = low + Math.floor((high - low) / 2)
+
+            prevHigh = tempHigh
+
+            checkNumber = high
+          } else if (checkRst === 'too_low') {
+            low = tempHigh
+            high = prevHigh
+
+            prevHigh = tempHigh
+            prevLow = tempLow
+
+            checkNumber = low
+          }
+        }
+      }
+    }
+
+    return checkNumber
+  }
+
+  async getPairsLength(factory) {
+    if (factory.version === 'univ2') {
+      // 获取工厂实例
+      const v2Factory = this.getFactoryContract(factory.hash)
+      // 获取当前pairsLength
+      return await v2Factory.methods.allPairsLength().call()
+    } else if (factory.version === 'univ3') {
+      // 获取positionManager
+      const v3PositionManager = this.getPositionManager(factory.positionManager)
+      return await this.getPositionLength(v3PositionManager, 0)
+    } else {
+      throw Error(`Unknown factory version: ${factory.version}, hash is: ${factory.hash}.`)
+    }
   }
 }

+ 100 - 37
scripts/lib/lp-lib.js

@@ -1,65 +1,128 @@
 const logger = require("../../utils/logger");
-const {BigNumber} = require("ethers");
+const BaseModel = require("../../model/base-model");
+const V2ToolAbi = require('../../abi/UNIV2_TOOLS_ABI.json')
+const V3ToolAbi = require('../../abi/UNIV3_TOOLS_ABI.json')
 
 module.exports = class LpLib {
-  async handleLp(position, pairsLength, routerObj, v2ToolBy410) {
-    // 1. 获取lp
-    let lp = undefined
-    if (routerObj.type === 'univ2') {
-      lp = await this.getV2PoolByPosition(routerObj, position, v2ToolBy410)
-    }
+  static LEVEL = {
+    NOT: 'not',
+    DISCARD: 'discard',
+    INIT: 'init',
+    NORMAL: 'normal',
+    TOP: 'top'
+  }
 
-    if (lp) {
-      // 2. 保存Lp信息
-      await this.saveLp(lp, 'lp')
-      // 3. 保存Lp的Token到Token表
-      await this.saveToken(lp, 'token')
-    }
+  constructor(web3, chain, factoryLib, tokenLib) {
+    this.web3 = web3
+    this.chain = chain
+    this.factoryLib = factoryLib
+    this.tokenLib = tokenLib
+    
+    this.v2LpModel = new BaseModel(this.chain.id, BaseModel.MODULES.V2_LP)
+    this.v3LpModel = new BaseModel(this.chain.id, BaseModel.MODULES.V3_LP)
+
+    // 初始化V2工具箱
+    this.v2Tool = new this.web3.eth.Contract(V2ToolAbi, this.chain.v2ToolAddress)
+    // 初始化V3工具箱
+    this.v3Tool = new this.web3.eth.Contract(V3ToolAbi, this.chain.v3ToolAddress)
+  }
 
-    if (lp) {
-      logger.debug(`${position + 1} / ${pairsLength}, ${lp.name}-${lp.LP}-${routerObj.chain}`)
+  async saveLp(factory, lp) {
+    if (factory.version === 'univ2') {
+      return await this.v2LpModel.appendOrUpdate(lp)
+    } else if (factory.version === 'univ3') {
+      return await this.v3LpModel.appendOrUpdate(lp)
     } else {
-      logger.debug(`lp get filed. ${position + 1} / ${pairsLength}, ${routerObj.name}-${routerObj.router}-${routerObj.chain}`)
+      throw Error(`Unknown factory version: ${factory.version}, hash is: ${factory.hash}.`)
     }
   }
 
-  async saveLp(lp, type = '0') {
-    // 本地lp实例存档
-    this.lpInstance[lp.LP.toLowerCase()] = lp
+  getEffectiveLp(factory, position, lp) {
+    // lp对象标准化
+    lp.symbol0 = this.tokenLib.getEffectiveSymbol(lp.symbol0)
+    lp.symbol1 = this.tokenLib.getEffectiveSymbol(lp.symbol1)
+    lp.name = `${factory.name}_${lp.symbol0}_${lp.symbol1}`
+    lp.router = factory.router
+    lp.factory = factory.hash
+    lp.fee = factory.fee
+    lp.positionId = position
+    lp.r0Str = String(lp.r0)
+    lp.r1Str = String(lp.r1)
+    lp.level = LpLib.LEVEL.INIT
+
+    // lp各种地址最小化
+    lp.hash = lp.hash.toLowerCase()
+    lp.token0 = lp.token0.toLowerCase()
+    lp.token1 = lp.token1.toLowerCase()
 
-    await History.appendOrUpdate(type, lp.LP, lp)
+    // 字符化数字
+    lp.decimals0 = parseInt(lp.decimals0)
+    lp.decimals1 = parseInt(lp.decimals1)
+
+    return lp
   }
 
-  async getV2PoolByPosition(routerObj, position, v2ToolBy410) {
+  async getV2Pool(factory, position) {
     try {
-      const info = await v2ToolBy410.methods.getPairIdInfo(routerObj.factory, position).call()
-
-      const symbol0 = info['2'].replace(/[^A-Za-z0-9]+/g, '').substring(0, 10)
-      const symbol1 = info['6'].replace(/[^A-Za-z0-9]+/g, '').substring(0, 10)
-      const name = `${routerObj.name}_${symbol0}_${symbol1}`
-      const sum2 = BigNumber.from(info['1']).add(BigNumber.from(info['5']))._hex.replace('0x0', '0x')
+      const info = await this.v2Tool.methods.getPairIdInfo(factory.hash, position).call()
 
-      return {
-        LP: info['0'],
+      const lp = {
+        hash: info['0'],
         decimals0: info['3'],
         decimals1: info['7'],
-        factory: routerObj.factory,
-        feei: routerObj.fee,
-        id: position,
-        name: name,
         r0: info['4'],
         r1: info['8'],
-        router: routerObj.router,
-        sum2: sum2,
-        symbol0: symbol0,
-        symbol1: symbol1,
+        symbol0: info['2'],
+        symbol1: info['6'],
         token0: info['1'],
         token1: info['5']
       }
+
+      return this.getEffectiveLp(factory, position, lp)
     } catch (e) {
       logger.info(e)
     }
 
     return undefined
   }
+
+  async getV3Pool(factory, position) {
+    try {
+      const positionManager = this.factoryLib.getPositionManager(factory.positionManager)
+      const positionInfo = await positionManager.methods.positions(position).call()
+      const info = await this.v3Tool.methods.getMoreInfo(positionInfo.token0, positionInfo.token1, positionInfo.fee).call()
+
+      const lp = {
+        hash: info.lp,
+        decimals0: info.decimals0,
+        decimals1: info.decimals1,
+        factory: factory.hash,
+        feei: positionInfo.fee,
+        id: position,
+        r0: info.r0,
+        r1: info.r1,
+        router: factory.router,
+        symbol0: symbol0,
+        symbol1: symbol1,
+        token0: positionInfo.token0,
+        token1: positionInfo.token1
+      }
+
+      return this.getEffectiveLp(factory, position, lp)
+    } catch (e) {}
+
+    return undefined
+  }
+
+  async getLpByPosition(factory, position) {
+    // 1. 获取lp
+    let lp = undefined
+    if (factory.version === 'univ2') {
+      return await this.getV2Pool(factory, position)
+    } else if (factory.version === 'univ3') {
+      return await this.getV3Pool(factory, position)
+    } else {
+      throw Error(`Unknown factory version: ${factory.version}, hash is: ${factory.hash}.`)
+    }
+  }
 }

+ 42 - 30
scripts/lib/token-lib.js

@@ -1,46 +1,58 @@
 const {web3} = require("hardhat");
 const ierc20abi = require("../../abi/IERC20_ABI.json");
+const BaseModel = require("../../model/base-model");
 
 module.exports = class TokenLib {
-  async handleToken(pool, zero) {
-    const token = {
-      'address': zero ? pool.token0 : pool.token1,
-      'symbol': zero ? pool.symbol0 : pool.symbol1,
-      'decimals': zero ? pool.decimals0 : pool.decimals1,
-      'name': 'xxxxxxxx'
+  static LEVEL = {
+    NOT: 'not',
+    DISCARD: 'discard',
+    INIT: 'init',
+    NORMAL: 'normal',
+    TOP: 'top'
+  }
+
+  constructor(web3, chain) {
+    this.web3 = web3
+    this.chain = chain
+
+    this.tokenContractMap = {}
+
+    this.tokenModel = new BaseModel(this.chain.id, BaseModel.MODULES.TOKEN)
+  }
+
+  getTokenContract(tokenAddress) {
+    if (!this.tokenContractMap[tokenAddress]) {
+      this.tokenContractMap[tokenAddress] = new this.web3.eth.Contract(ierc20abi, tokenAddress)
     }
 
-    let tokenObj = this.tokenInstance[token.address]
-    if (!tokenObj) {
-      tokenObj = new web3.eth.Contract(ierc20abi, token.address)
-      this.tokenInstance[token.address] = tokenObj
+    return this.tokenContractMap[tokenAddress]
+  }
+
+  async parseToken(lp, isZero) {
+    const token = {
+      'hash': isZero ? lp.token0 : lp.token1,
+      'symbol': isZero ? lp.symbol0 : lp.symbol1,
+      'decimals': isZero ? lp.decimals0 : lp.decimals1
     }
 
-    token.name = await tokenObj.methods.name().call()
-    token.name = token.name.replace(/[^A-Za-z0-9 ]+/g, '').substring(0, 37)
+    let tokenContract = this.getTokenContract(token.hash)
+
+    token.name = await tokenContract.methods.name().call()
+    token.name = this.getEffectiveName(token.name)
+    token.level = TokenLib.LEVEL.INIT
 
     return token
   }
 
-  async saveToken(lp, type = 'token') {
-    try {
-      const token = await this.handleToken(lp, true)
-
-      // token的hash不同时为lp的情况才更新
-      if (!this.lpInstance[token.address.toLowerCase()]) {
-        await history.appendOrUpdate(type, token.address, token)
-      }
-    } catch (e) {
-    }
+  getEffectiveSymbol(originSymbol) {
+    return originSymbol.replace(/[^A-Za-z0-9]+/g, '').substring(0, 10)
+  }
 
-    try {
-      const token = await this.handleToken(lp, false)
+  getEffectiveName(originName) {
+    return originName.replace(/[^A-Za-z0-9]+/g, '').substring(0, 37)
+  }
 
-      // token的hash不同时为lp的情况才更新
-      if (!this.lpInstance[token.address.toLowerCase()]) {
-        await history.appendOrUpdate(type, token.address, token)
-      }
-    } catch (e) {
-    }
+  async saveToken(token) {
+    return await this.tokenModel.appendOrUpdate(token)
   }
 }