Compare commits

..

4 Commits
master ... main

Author SHA1 Message Date
lzx ddd5b13945 delete config file 2025-08-08 10:49:19 +08:00
lzx 982d14a469 update 2025-08-08 10:32:40 +08:00
lzx 927bfa198c update 2025-08-08 10:31:21 +08:00
lzx 4675b2e3d7 confirm readme.md 2025-08-08 10:22:15 +08:00
4 changed files with 137 additions and 55 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
node_modules
src/config.json
config.json

View File

@ -1,4 +1,41 @@
# start
```
npm run start --${port} // default: 12345
npm install
npm run start ${port} // default: 12345
```
# api
```
1, /checkPayment/eth
[request]
method:post
params:coin string, address string, amount float64, ts uint64 (request-body)
[response]
success: {code:0, result:true, data:array[]{
"blockNumber": "23088543",
"timeStamp": "1754561951",
"hash": "0x887ba171af3ed43cec6dfaef5f0379e2718cdc91a538eea7173947461dbcfd90",
"nonce": "0",
"blockHash": "0x5752c8fc343db877853c76aa14ecdfa6aa19bc9f273e1df715cd03020395152f",
"from": "0xfdd78d01030956dc417a3057b205159490b3919e",
"contractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"to": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43",
"value": "1100000000",
"tokenName": "USDC",
"tokenSymbol": "USDC",
"tokenDecimal": "6",
"transactionIndex": "110",
"gas": "45746",
"gasPrice": "2240053599",
"gasUsed": "40348",
"cumulativeGasUsed": "16503510",
"input": "deprecated",
"methodId": "0xa9059cbb",
"functionName": "transfer(address _to, uint256 _value)",
"confirmations": "4768"
}, ... }
error: {code:-1, result:false, data: array[]} // 未转账
{code:-2, result:false, data: array[]} // coin参数不支持
```

4
app.js
View File

@ -4,6 +4,8 @@ const ETH = require("./src/chain/eth")
const eth = new ETH()
const app = express()
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const port = process.argv[2] || 12345
app.get("/", (req, res) =>{
@ -15,7 +17,7 @@ app.post("/checkPayment/eth", async(req, res) =>{
let result
switch (coin) {
case "eth":
// 校验eth
result = await eth.checkETHPaymentStatus(address, amount, ts)
break
case "usdt":
result = await eth.checkUSDTPaymentStatus(address, amount, ts)

View File

@ -1,6 +1,6 @@
const app = require("../app");
const abiDecoder = require("abi-decoder");
const Web3 = require("web3");
// const Web3 = require("web3");
const axios = require("axios");
class ETH {
@ -9,7 +9,7 @@ class ETH {
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));
// this.web3 = new Web3(new Web3.providers.HttpProvider(apiUrl));
abiDecoder.addABI(usdt_abi);
abiDecoder.addABI(usdc_abi);
this.decoder = abiDecoder;
@ -25,58 +25,101 @@ class ETH {
}
}
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;
}
}
// 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;
}
// 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);
}
// 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 checkETHPaymentStatus(address, amount, ts) {
const url = `${app.ethNodeUrl}
?chainid=1
&module=account
&action=txlist
&address=${address}
&startblock=0
&endblock=99999999
&page=1
&offset=100
&sort=desc
&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: [] };
}
// 筛选出金额等于指定值的交易ETH 最小单位是 18 位)
const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 10 ** 18 === amount && address === tx.to);
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:[]};
}
return result;
}
async checkUSDTPaymentStatus(address, amount, ts){
@ -108,7 +151,7 @@ class ETH {
}
// 筛选出金额等于指定值的交易USDT 最小单位是 6 位)
const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)");
const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)" && address === tx.to);
if (matchedTxs.length === 0) {
return { code: -1, result: false, data: [] };
@ -154,7 +197,7 @@ class ETH {
}
// 筛选出金额等于指定值的交易USDT 最小单位是 6 位)
const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)");
const matchedTxs = afterTimestampTxs.filter(tx => parseFloat(tx.value) / 1_000_000 === amount && tx.functionName === "transfer(address _to, uint256 _value)" && address === tx.to);
if (matchedTxs.length === 0) {
return { code: -1, result: false, data: [] };