const app = require("../app"); const abiDecoder = require("abi-decoder"); const Web3 = require("web3"); const axios = require("axios"); class ETH { #key = "2KKTKZ8MSG6DNUPQ4K9JVWPQ4H33DSUQA3" constructor(){ const apiUrl = app.ethNodeUrl const usdt_abi = app.abis.usdterc20_abi; const usdc_abi = app.abis.usdcerc20_abi; this.web3 = new Web3(new Web3.providers.HttpProvider(apiUrl)); abiDecoder.addABI(usdt_abi); abiDecoder.addABI(usdc_abi); this.decoder = abiDecoder; } decodeInput(input){ try{ return this.decoder.decodeMethod(input); } catch (error) { console.error("Error decoding input data:", error); return null; } } async decodeTxInput(txHash) { try{ const tx = await this.web3.eth.getTransaction(txHash); if (!tx || !tx.input) { console.error("Transaction not found or has no input data."); return null; } return this.decodeInput(tx.input); } catch (error) { console.error("Error decoding transaction input:", error); return null; } } decodeUSDT(input){ const decoded = this.decodeInput(input) const result = [] if (decoded && decoded.name === "transfer") { for (let item of decoded.params) { const obj = {} if (item.name === "_to") { obj.toAddress = item.value; } if (item.name === "_value") { obj.amount = this.web3.utils.fromWei(item.value, "ether"); } if (Object.keys(obj).length > 0) { result.push(obj); } } } return result; } decodeUSDC(input){ const decoded = this.decodeInput(input) const result = [] if (decoded && decoded.name === "transfer") { for (let item of decoded.params) { const obj = {} if (item.name === "to") { obj.toAddress = item.value; } if (item.name === "value") { obj.amount = this.web3.utils.fromWei(item.value, "mwei"); } if (Object.keys(obj).length > 0) { result.push(obj); } } } return result; } async checkUSDTPaymentStatus(address, amount, ts){ const url = `${app.ethNodeUrl} ?chainid=1 &module=account &action=tokentx &contractaddress=0xdAC17F958D2ee523a2206206994597C13D831ec7 &address=${address} &page=1 &offset=100 &startblock=0 &endblock=27025780 &sort=asc &apikey=${this.#key}` try { const response = await axios.get(url); const transactions = response.data.result; if (!Array.isArray(transactions) || transactions.length === 0) { return { code: -1, result: false, data: [] }; } // 筛选时间戳 >= ts 的交易 const afterTimestampTxs = transactions.filter(tx => parseInt(tx.timeStamp) >= ts); if (afterTimestampTxs.length === 0) { return { code: -1, result: false, data: [] }; } // 筛选出金额等于指定值的交易(USDT 最小单位是 6 位) const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)"); if (matchedTxs.length === 0) { return { code: -1, result: false, data: [] }; } return { code: 0, result: true, data: matchedTxs.length === 1 ? matchedTxs[0] : matchedTxs, }; } catch (error) { console.error("Error fetching transactions:", error); return {code:-1, result: false, data:[]}; } } async checkUSDCPaymentStatus(address, amount, ts) { const url = `${app.ethNodeUrl} ?chainid=1 &module=account &action=tokentx &contractaddress=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 &address=${address} &page=1 &offset=100 &startblock=0 &endblock=27025780 &sort=asc &apikey=${this.#key}` try{ const response = await axios.get(url); const transactions = response.data.result; if (!Array.isArray(transactions) || transactions.length === 0) { return { code: -1, result: false, data: [] }; } // 筛选时间戳 >= ts 的交易 const afterTimestampTxs = transactions.filter(tx => parseInt(tx.timeStamp) >= ts); if (afterTimestampTxs.length === 0) { return { code: -1, result: false, data: [] }; } // 筛选出金额等于指定值的交易(USDT 最小单位是 6 位) const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)"); if (matchedTxs.length === 0) { return { code: -1, result: false, data: [] }; } return { code: 0, result: true, data: matchedTxs.length === 1 ? matchedTxs[0] : matchedTxs, }; } catch (error) { console.error("Error fetching transactions:", error); return {code:-1, result: false, data:[]}; } } } module.exports = ETH