174 lines
5.7 KiB
JavaScript
174 lines
5.7 KiB
JavaScript
|
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
|