1. Modify the subgraph of config.js, delete unused chains, and add ensSubdomainKey to each chain #3

Merged
Theo merged 1 commits from nanli777torn/tornado-cli:master into master 2025-03-20 20:16:50 +03:00
5 changed files with 356 additions and 116 deletions

208
abis/Aggregator.abi.json Normal file

@ -0,0 +1,208 @@
[
{
"inputs": [],
"name": "ensRegistry",
"outputs": [
{
"internalType": "contract ENSRegistry",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract Governance",
"name": "governance",
"type": "address"
}
],
"name": "getAllProposals",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"internalType": "address",
"name": "target",
"type": "address"
},
{
"internalType": "uint256",
"name": "startTime",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "endTime",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "forVotes",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "againstVotes",
"type": "uint256"
},
{
"internalType": "bool",
"name": "executed",
"type": "bool"
},
{
"internalType": "bool",
"name": "extended",
"type": "bool"
},
{
"internalType": "enum Governance.ProposalState",
"name": "state",
"type": "uint8"
}
],
"internalType": "struct GovernanceAggregator.Proposal[]",
"name": "proposals",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract Governance",
"name": "governance",
"type": "address"
},
{
"internalType": "address[]",
"name": "accs",
"type": "address[]"
}
],
"name": "getGovernanceBalances",
"outputs": [
{
"internalType": "uint256[]",
"name": "amounts",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract Governance",
"name": "governance",
"type": "address"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "getUserData",
"outputs": [
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "latestProposalId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "latestProposalIdState",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "timelock",
"type": "uint256"
},
{
"internalType": "address",
"name": "delegatee",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "relayerRegistry",
"outputs": [
{
"internalType": "contract RelayerRegistry",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32[]",
"name": "_relayers",
"type": "bytes32[]"
},
{
"internalType": "string[]",
"name": "_subdomains",
"type": "string[]"
}
],
"name": "relayersData",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
},
{
"internalType": "bool",
"name": "isRegistered",
"type": "bool"
},
{
"internalType": "string[20]",
"name": "records",
"type": "string[20]"
}
],
"internalType": "struct Relayer[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
}
]

2
cli.js

@ -1201,7 +1201,7 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
}
await fetchGraphEvents();
}
if (!privateRpc && !subgraph && !isTestRPC) {
if (!privateRpc && subgraph && !isTestRPC) {
await syncGraphEvents();
} else {
await syncEvents();

127
config.js Normal file → Executable file

@ -106,121 +106,12 @@ module.exports = {
gasLimit: '85000'
}
},
ensSubdomainKey: 'mainnet-tornado',
proxy: '0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b',
multicall: '0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/mainnet-tornado-subgraph',
subgraph: 'https://gateway.thegraph.com/api/6a217817dd87d33db10beed79b044a91/subgraphs/id/Ec6fVMDVqXTDQZ3c4jxcyV3zBXqkdgMWfhdtCgtqn7Sh',
defaultRpc: 'https://mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
netId5: {
tokens: {
eth: {
instanceAddress: {
0.1: '0x6Bf694a291DF3FeC1f7e69701E3ab6c592435Ae7',
1: '0x3aac1cC67c2ec5Db4eA850957b967Ba153aD6279',
10: '0x723B78e67497E85279CB204544566F4dC5d2acA0',
100: '0x0E3A09dDA6B20aFbB34aC7cD4A6881493f3E7bf7'
},
deployedBlockNumber: {
0.1: 3782581,
1: 3782590,
10: 3782593,
100: 3782596
},
miningEnabled: true,
symbol: 'ETH',
decimals: 18
},
dai: {
instanceAddress: {
100: '0x76D85B4C0Fc497EeCc38902397aC608000A06607',
1000: '0xCC84179FFD19A1627E79F8648d09e095252Bc418',
10000: '0xD5d6f8D9e784d0e26222ad3834500801a68D027D',
100000: '0x407CcEeaA7c95d2FE2250Bf9F2c105aA7AAFB512'
},
deployedBlockNumber: {
100: 4339088,
1000: 4367659,
10000: 4441492,
100000: 4441488
},
miningEnabled: true,
tokenAddress: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60',
symbol: 'DAI',
decimals: 18,
gasLimit: '55000'
},
cdai: {
instanceAddress: {
5000: '0x833481186f16Cece3f1Eeea1a694c42034c3a0dB',
50000: '0xd8D7DE3349ccaA0Fde6298fe6D7b7d0d34586193',
500000: '0x8281Aa6795aDE17C8973e1aedcA380258Bc124F9',
5000000: '0x57b2B8c82F065de8Ef5573f9730fC1449B403C9f'
},
deployedBlockNumber: {
5000: 4441443,
50000: 4441489,
500000: 4441493,
5000000: 4441489
},
miningEnabled: true,
tokenAddress: '0x822397d9a55d0fefd20F5c4bCaB33C5F65bd28Eb',
symbol: 'cDAI',
decimals: 8,
gasLimit: '425000'
},
usdc: {
instanceAddress: {
100: '0x05E0b5B40B7b66098C2161A5EE11C5740A3A7C45',
1000: '0x23173fE8b96A4Ad8d2E17fB83EA5dcccdCa1Ae52'
},
deployedBlockNumber: {
100: 4441426,
1000: 4441492
},
miningEnabled: false,
tokenAddress: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C',
symbol: 'USDC',
decimals: 6,
gasLimit: '80000'
},
usdt: {
instanceAddress: {
100: '0x538Ab61E8A9fc1b2f93b3dd9011d662d89bE6FE6',
1000: '0x94Be88213a387E992Dd87DE56950a9aef34b9448'
},
deployedBlockNumber: {
100: 4441490,
1000: 4441492
},
miningEnabled: false,
tokenAddress: '0xb7FC2023D96AEa94Ba0254AA5Aeb93141e4aad66',
symbol: 'USDT',
decimals: 6,
gasLimit: '100000'
},
wbtc: {
instanceAddress: {
0.1: '0x242654336ca2205714071898f67E254EB49ACdCe',
1: '0x776198CCF446DFa168347089d7338879273172cF',
10: '0xeDC5d01286f99A066559F60a585406f3878a033e'
},
deployedBlockNumber: {
0.1: 4441488,
1: 4441490,
10: 4441490
},
miningEnabled: true,
tokenAddress: '0xC04B0d3107736C32e19F1c62b2aF67BE61d63a05',
symbol: 'WBTC',
decimals: 8,
gasLimit: '85000'
}
},
proxy: '0x454d870a72e29d5e5697f635128d18077bd04c60',
multicall: '0x77dCa2C955b15e9dE4dbBCf1246B4B85b651e50e',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/goerli-tornado-subgraph',
defaultRpc: 'https://goerli.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
netId56: {
tokens: {
bnb: {
@ -241,9 +132,10 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'bsc-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0x41263cBA59EB80dC200F3E2544eda4ed6A90E76C',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/bsc-tornado-subgraph',
subgraph: 'https://gateway.thegraph.com/api/6a217817dd87d33db10beed79b044a91/subgraphs/id/CiwGzefDBZCavXRPnwarnnF8xDDoLw4boBuySomJWYnV',
defaultRpc: 'https://bsc-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
netId100: {
@ -266,6 +158,7 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'gnosis-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0xb5b692a88BDFc81ca69dcB1d924f59f0413A602a',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/xdai-tornado-subgraph',
@ -291,9 +184,10 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'polygon-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0x11ce4B23bD875D7F5C6a31084f55fDe1e9A87507',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/matic-tornado-subgraph',
subgraph: 'https://gateway.thegraph.com/api/d2db349f28c895aa2272421996404c8d/subgraphs/id/HUMgwMYNrPQpnBJgesFXyy5u6jSiJ6u5nNWQng9ayCmD',
defaultRpc: 'https://polygon-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
netId42161: {
@ -316,9 +210,10 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'arbitrum-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0xB064Fe785d8131653eE12f3581F9A55F6D6E1ca3',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/arbitrum-tornado-subgraph',
subgraph: 'https://gateway.thegraph.com/api/d2db349f28c895aa2272421996404c8d/subgraphs/id/8x8o6XFAqYZmiPwrJ51UxGTaZLYyW1fFtghvsEy7a1KJ',
defaultRpc: 'https://arbitrum-one.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
netId43114: {
@ -339,9 +234,10 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'avalanche-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0x98e2060F672FD1656a07bc12D7253b5e41bF3876',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/avalanche-tornado-subgraph',
subgraph: 'https://gateway.thegraph.com/api/d2db349f28c895aa2272421996404c8d/subgraphs/id/CqUYVKJT9Jsyt7qnGNrf4FJNHw75ZbFGuzaJgqdaFASo',
defaultRpc: 'https://avalanche-rpc.tornado.ws/ext/bc/C/rpc'
},
netId10: {
@ -364,6 +260,7 @@ module.exports = {
decimals: 18
}
},
ensSubdomainKey: 'optimism-tornado',
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
multicall: '0x142E2FEaC30d7fc3b61f9EE85FCCad8e560154cc',
subgraph: 'https://api.thegraph.com/subgraphs/name/tornadocash/optimism-tornado-subgraph',

@ -22,6 +22,7 @@
"commander": "^5.1.0",
"dotenv": "^8.6.0",
"es5-ext": "0.10.53",
"eth-ens-namehash": "^2.0.8",
"private-ip": "^2.3.3",
"socks-proxy-agent": "^6.1.1",
"web3": "^1.10.2"

134
relayerslist.js Normal file

@ -0,0 +1,134 @@
const axios = require('axios');
const namehash = require('eth-ens-namehash');
const BigNumber = require('bignumber.js');
const apikey = '6a217817dd87d33db10beed79b044a91';
const api = 'https://gateway.thegraph.com/api/' + apikey + '/subgraphs/id/DgKwfAbLfynpiq7fDJy59LDnVnia4Y5nYeRDBYi9qezc';
const Web3 = require('web3');
const web3 = new Web3('https://rpc.mevblocker.io');
const aggregatorContract = '0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49';
const AggregatorABI = require('./abis/Aggregator.abi');
const aggregator = new web3.eth.Contract(AggregatorABI, aggregatorContract);
const MIN_STAKE_BALANCE = '0X1B1AE4D6E2EF500000'; // 500 TORN
const networkConfig = require('./config.js');
const subdomains = Object.values(networkConfig.deployments).map(({ ensSubdomainKey }) => ensSubdomainKey);
async function fetchRelayers() {
return new Promise(async (resolve, reject) => {
axios.post(api, { 'query': '{ relayers(first: 1000) {\n id\n address\n ensName\n ensHash\n }\n}' }
).then(res => {
if (res.data.errors) {
console.log(res.data);
return;
}
if (res.data.data.relayers.length > 0) {
resolve(res.data.data.relayers);
}
});
});
}
function filterRelayer(acc, curr, ensSubdomainKey, relayer) {
const subdomainIndex = subdomains.indexOf(ensSubdomainKey);
const mainnetSubdomain = curr.records[0];
const hostname = curr.records[subdomainIndex];
const isHostWithProtocol = hostname.includes('http');
const isOwner = relayer.address.toLowerCase() === curr.owner.toLowerCase();
const hasMinBalance = new BigNumber(curr.balance).gte(MIN_STAKE_BALANCE);
if (
hostname &&
isOwner &&
mainnetSubdomain &&
curr.isRegistered &&
hasMinBalance &&
!isHostWithProtocol
) {
acc.push({
hostname,
ensName: relayer.ensName,
stakeBalance: curr.balance,
relayerAddress: relayer.address.toLowerCase()
});
}
return acc;
}
async function getValidRelayers(relayers, ensSubdomainKey) {
const relayerNameHashes = relayers.map((r) => namehash.hash(r.ensName));
const relayersData = await aggregator.methods.relayersData(relayerNameHashes, subdomains).call();
const validRelayers = relayersData.reduce(
(acc, curr, index) => filterRelayer(acc, curr, ensSubdomainKey, relayers[index]),
[]
);
return validRelayers;
}
async function getRelayers(ensSubdomainKey) {
let relayers = await fetchRelayers();
const validRelayers = await getValidRelayers(relayers, ensSubdomainKey);
return validRelayers;
}
async function load() {
console.log('Please enter the relay number of the chain you want to obtain:');
console.log('1. Eth, 2. Bsc, 3. Gnosis, 4. Polygon, 5. Arb, 6. Avax, 7. Op');
process.stdin.on('data', async (data) => {
const input = data.toString().trim(); // 将输入转换为字符串并去除多余空格
if (/^[1-7]$/.test(input)) {
let ensSubdomainKey = Object.values(networkConfig.deployments)[input - 1].ensSubdomainKey;
console.log('Start requesting data');
const registeredRelayers = await getRelayers(ensSubdomainKey);
const axiosInstance = axios.create({
timeout: 3000
});
let statuses = [];
for (const registeredRelayer of registeredRelayers) {
try {
console.log(`https://${registeredRelayer.hostname}/status`);
const res = await axiosInstance.get(`https://${registeredRelayer.hostname}/status`);
const statusData = res.data;
if (statusData.rewardAccount && statusData.health.status == 'true') {
statuses.push({
...registeredRelayer,
statusData
});
}
} catch (e) {
console.error(`Failed to fetch status for ${registeredRelayer.hostname}:`);
}
}
statuses.forEach(item => {
console.log({
'hostname': 'https://' + item.hostname + '/',
'ensName': item.ensName,
'stakeBalance': Number(web3.utils.fromWei(item.stakeBalance, 'ether')).toFixed(2)+" TORN",
'tornadoServiceFee': item.statusData.tornadoServiceFee
});
});
} else {
console.log('Invalid input! Please enter a single number between 1-7');
}
});
}
load();