Skip to content

Commit fd1f05d

Browse files
invetigating
1 parent e840647 commit fd1f05d

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

AI_research/check_sparkdex_pool.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import logging
2+
from web3 import Web3
3+
from web3.exceptions import ContractLogicError
4+
5+
from web3.middleware import ExtraDataToPOAMiddleware
6+
7+
# Configure logging
8+
logging.basicConfig(
9+
level=logging.DEBUG,
10+
format='%(asctime)s - %(levelname)s - %(message)s',
11+
handlers=[logging.StreamHandler()]
12+
)
13+
logger = logging.getLogger(__name__)
14+
15+
# Constants
16+
FACTORY_ADDRESSES = [
17+
"0x8A2578d23d4C532cC9A98FaD91C0523f5efDE652",
18+
]
19+
UNIVERSAL_ROUTER_ADDRESS = "0x8a1E35F5c98C4E85B36B7B253222eE17773b2781"
20+
WFLR_ADDRESS = "0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d"
21+
USDC_ADDRESS = "0xFbDa5F676cB37624f28265A144A48B0d6e87d3b6" # USDC.e
22+
FEE_TIER = 500
23+
USER_ADDRESS = "0x1812C40b5785AeD831EC4a0d675f30c5461Fd42E" # Replace with your address
24+
RPC_URL = "https://flare-api.flare.network/ext/C/rpc"
25+
FALLBACK_POOL_ADDRESS = None # Replace with "0x..." if known, else None
26+
27+
# ABIs
28+
FACTORY_ABI = [{"inputs": [{"internalType": "address", "name": "tokenA", "type": "address"}, {"internalType": "address", "name": "tokenB", "type": "address"}, {"internalType": "uint24", "name": "fee", "type": "uint24"}], "name": "getPool", "outputs": [{"internalType": "address", "name": "pool", "type": "address"}], "stateMutability": "view", "type": "function"}]
29+
POOL_ABI = [{"inputs": [], "name": "token0", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "token1", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "fee", "outputs": [{"internalType": "uint24", "name": "", "type": "uint24"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "liquidity", "outputs": [{"internalType": "uint128", "name": "", "type": "uint128"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "slot0", "outputs": [{"internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160"}, {"internalType": "int24", "name": "tick", "type": "int24"}, {"internalType": "uint16", "name": "observationIndex", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinality", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinalityNext", "type": "uint16"}, {"internalType": "uint8", "name": "feeProtocol", "type": "uint8"}, {"internalType": "bool", "name": "unlocked", "type": "bool"}], "stateMutability": "view", "type": "function"}]
30+
ERC20_ABI = [{"inputs": [], "name": "decimals", "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}], "stateMutability": "view", "type": "function"}, {"inputs": [{"internalType": "address", "name": "account", "type": "address"}], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}]
31+
UNIVERSAL_ROUTER_ABI = [{"inputs": [{"components": [{"internalType": "address", "name": "tokenIn", "type": "address"}, {"internalType": "address", "name": "tokenOut", "type": "address"}, {"internalType": "uint24", "name": "fee", "type": "uint24"}, {"internalType": "address", "name": "recipient", "type": "address"}, {"internalType": "uint256", "name": "deadline", "type": "uint256"}, {"internalType": "uint256", "name": "amountIn", "type": "uint256"}, {"internalType": "uint256", "name": "amountOutMinimum", "type": "uint256"}, {"internalType": "uint160", "name": "sqrtPriceLimitX96", "type": "uint160"}], "internalType": "struct ISwapRouter.ExactInputSingleParams", "name": "params", "type": "tuple"}], "name": "exactInputSingle", "outputs": [{"internalType": "uint256", "name": "amountOut", "type": "uint256"}], "stateMutability": "payable", "type": "function"}]
32+
33+
# Connect to Flare
34+
logger.info("=== STEP 1: CONNECTING TO FLARE NETWORK ===")
35+
w3 = Web3(Web3.HTTPProvider(RPC_URL))
36+
if not w3.is_connected():
37+
logger.error("Failed to connect to Flare RPC")
38+
exit(1)
39+
logger.info("Successfully connected to Flare network")
40+
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
41+
42+
# Check factory code
43+
logger.info("=== STEP 2: FINDING VALID FACTORY ADDRESS ===")
44+
for factory_addr in FACTORY_ADDRESSES:
45+
code = w3.eth.get_code(factory_addr)
46+
logger.debug(f"Factory {factory_addr} bytecode length: {len(code)}")
47+
if len(code) > 0:
48+
logger.info(f"Found factory with code at {factory_addr}")
49+
FACTORY_ADDRESS = factory_addr
50+
break
51+
else:
52+
logger.error("No factory with bytecode found. Please provide SparkDEX factory address.")
53+
if FALLBACK_POOL_ADDRESS:
54+
logger.info(f"Using fallback pool address: {FALLBACK_POOL_ADDRESS}")
55+
pool_address = FALLBACK_POOL_ADDRESS
56+
else:
57+
logger.error("No fallback pool address provided. Exiting.")
58+
exit(1)
59+
60+
# Contracts
61+
factory = w3.eth.contract(address=FACTORY_ADDRESS, abi=FACTORY_ABI)
62+
wflr_contract = w3.eth.contract(address=WFLR_ADDRESS, abi=ERC20_ABI)
63+
usdc_contract = w3.eth.contract(address=USDC_ADDRESS, abi=ERC20_ABI)
64+
universal_router = w3.eth.contract(address=UNIVERSAL_ROUTER_ADDRESS, abi=UNIVERSAL_ROUTER_ABI)
65+
66+
# Step 3: Get pool address
67+
logger.info("=== STEP 3: FETCHING POOL ADDRESS ===")
68+
if not FALLBACK_POOL_ADDRESS:
69+
try:
70+
pool_address = factory.functions.getPool(WFLR_ADDRESS, USDC_ADDRESS, FEE_TIER).call()
71+
logger.debug(f"WFLR/USDC.e pool address at fee {FEE_TIER}: {pool_address}")
72+
if pool_address == "0x0000000000000000000000000000000000000000":
73+
logger.error("No pool found for WFLR/USDC.e at fee tier 500")
74+
exit(1)
75+
except Exception as e:
76+
logger.error(f"Failed to get pool: {str(e)}")
77+
exit(1)
78+
else:
79+
pool_address = FALLBACK_POOL_ADDRESS
80+
logger.info(f"Using provided fallback pool address: {pool_address}")
81+
82+
# Step 4: Verify pool details
83+
logger.info("=== STEP 4: VERIFYING POOL DETAILS ===")
84+
pool = w3.eth.contract(address=pool_address, abi=POOL_ABI)
85+
token0 = pool.functions.token0().call()
86+
token1 = pool.functions.token1().call()
87+
fee = pool.functions.fee().call()
88+
logger.debug(f"Pool tokens: token0={token0}, token1={token1}, fee={fee}")
89+
if {token0, token1} != {WFLR_ADDRESS, USDC_ADDRESS} or fee != FEE_TIER:
90+
logger.error("Pool mismatch: tokens or fee incorrect")
91+
exit(1)
92+
logger.info("Pool verified successfully")
93+
94+
# Step 5: Check pool state
95+
logger.info("=== STEP 5: CHECKING POOL STATE ===")
96+
slot0 = pool.functions.slot0().call()
97+
liquidity = pool.functions.liquidity().call()
98+
logger.debug(f"Slot0: {slot0}")
99+
logger.debug(f"Liquidity: {liquidity}")
100+
101+
# Step 6: Get decimals and balance
102+
logger.info("=== STEP 6: FETCHING TOKEN DETAILS AND BALANCE ===")
103+
decimals_wflr = wflr_contract.functions.decimals().call()
104+
decimals_usdc = usdc_contract.functions.decimals().call()
105+
balance_wflr = wflr_contract.functions.balanceOf(USER_ADDRESS).call()
106+
logger.debug(f"WFLR decimals: {decimals_wflr}, USDC.e decimals: {decimals_usdc}")
107+
logger.debug(f"User WFLR balance: {balance_wflr} wei ({balance_wflr / 10**decimals_wflr} WFLR)")
108+
109+
# Step 7: Test swap (1 WFLR -> USDC.e)
110+
logger.info("=== STEP 7: TESTING SWAP (1 WFLR -> USDC.e) ===")
111+
amount_in = 1 * 10**decimals_wflr
112+
if balance_wflr < amount_in:
113+
logger.error(f"Insufficient balance: {balance_wflr} < {amount_in}")
114+
exit(1)
115+
116+
deadline = w3.eth.get_block("latest")["timestamp"] + 300
117+
params = (WFLR_ADDRESS, USDC_ADDRESS, FEE_TIER, USER_ADDRESS, deadline, amount_in, 1, 0)
118+
logger.debug(f"Swap params: {params}")
119+
120+
try:
121+
amount_out = universal_router.functions.exactInputSingle(params).call()
122+
logger.info(f"Swap successful! Expected USDC.e output: {amount_out} wei ({amount_out / 10**decimals_usdc} USDC.e)")
123+
except ContractLogicError as e:
124+
logger.error(f"Swap failed: {str(e)}")
125+
except Exception as e:
126+
logger.error(f"Unexpected error: {str(e)}")
127+
128+
logger.info("=== CHECK COMPLETE ===")
129+
130+
131+
132+
133+
swap_tx = universal_router.functions.exactInputSingle(params).build_transaction({
134+
'from': USER_ADDRESS,
135+
'nonce': 76,
136+
"maxFeePerGas": w3.eth.gas_price * w3.eth.max_priority_fee,
137+
"maxPriorityFeePerGas": w3.eth.max_priority_fee,
138+
'chainId': 14,
139+
"type": 2,
140+
})

src/flare_ai_defai/api/routes/chat.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ async def handle_command(self, command: str) -> dict[str, str]:
273273
response = self.flareExplorer.get_contract_abi("0x12e605bc104e93B45e1aD99F9e555f659051c2BB")
274274
return {"response": json.dumps(response)}
275275

276+
if command == "/testSwap":
277+
self.sparkdex.handle_swap_token("wflr", "usdc", 1)
278+
276279
return {"response": "Unknown command"}
277280

278281
async def get_semantic_route(self, message: str) -> SemanticRouterResponse:

0 commit comments

Comments
 (0)