2024-05-08 19:55:36 +03:00
|
|
|
import { isEmpty } from 'lodash'
|
|
|
|
import { ApolloClient, InMemoryCache, gql } from '@apollo/client/core'
|
|
|
|
import { utils } from 'ethers'
|
2024-05-07 15:34:40 +03:00
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
import { GET_ACCOUNTS, GET_COMMITMENT, GET_NULLIFIER } from './queries'
|
|
|
|
import { ChainId, numbers } from '../constants'
|
|
|
|
|
|
|
|
const { getAddress } = utils
|
2024-05-07 15:34:40 +03:00
|
|
|
|
|
|
|
const first = 1000
|
|
|
|
const breakLength = 900
|
|
|
|
|
|
|
|
const CHAIN_GRAPH_URLS = {
|
|
|
|
[ChainId.BSC]: 'https://api.thegraph.com/subgraphs/name/dan1kov/bsc-tornado-pool-subgraph',
|
|
|
|
[ChainId.MAINNET]: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/mainnet-tornado-pool-subgraph',
|
|
|
|
[ChainId.XDAI]: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/gnosis-tornado-nova-subgraph',
|
|
|
|
}
|
|
|
|
|
|
|
|
const link = (operation) => {
|
|
|
|
const { chainId } = operation.getContext()
|
|
|
|
return CHAIN_GRAPH_URLS[chainId]
|
|
|
|
}
|
|
|
|
|
|
|
|
const client = new ApolloClient({
|
|
|
|
uri: link,
|
|
|
|
cache: new InMemoryCache(),
|
|
|
|
})
|
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
export async function getAccounts({ fromBlock, chainId }) {
|
|
|
|
const { data } = await client.query({
|
|
|
|
context: {
|
|
|
|
chainId,
|
|
|
|
},
|
|
|
|
query: gql(GET_ACCOUNTS),
|
|
|
|
variables: { first, fromBlock },
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
return {
|
|
|
|
results: [],
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
results: data.accounts,
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function getAllAccounts({ fromBlock, toBlock, chainId }) {
|
|
|
|
try {
|
|
|
|
let accounts = []
|
|
|
|
let lastSyncBlock
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
let { results, lastSyncBlock: lastBlock } = await getAccounts({ fromBlock, chainId })
|
|
|
|
|
|
|
|
lastSyncBlock = lastBlock
|
|
|
|
|
|
|
|
if (isEmpty(results)) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (results.length < breakLength) {
|
|
|
|
accounts = accounts.concat(results)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
const [lastEvent] = results.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
results = results.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
|
|
|
fromBlock = Number(lastEvent.blockNumber)
|
|
|
|
|
|
|
|
accounts = accounts.concat(results)
|
|
|
|
|
|
|
|
if (toBlock && fromBlock >= Number(toBlock)) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!accounts) {
|
|
|
|
return {
|
|
|
|
lastSyncBlock,
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = accounts.map((e) => ({
|
|
|
|
key: e.key,
|
|
|
|
owner: getAddress(e.owner),
|
|
|
|
blockNumber: Number(e.blockNumber),
|
|
|
|
}))
|
|
|
|
|
|
|
|
const [lastEvent] = data.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
return {
|
|
|
|
events: data,
|
|
|
|
lastSyncBlock: (lastEvent && lastEvent.blockNumber >= lastSyncBlock)
|
|
|
|
? lastEvent.blockNumber + numbers.ONE
|
|
|
|
: lastSyncBlock,
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.log('Error from getAllAccounts')
|
|
|
|
console.log(err)
|
|
|
|
return {
|
|
|
|
lastSyncBlock: '',
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function getCommitments({ fromBlock, chainId }) {
|
2024-05-07 15:34:40 +03:00
|
|
|
const { data } = await client.query({
|
|
|
|
context: {
|
|
|
|
chainId,
|
|
|
|
},
|
|
|
|
query: gql(GET_COMMITMENT),
|
|
|
|
variables: { first, fromBlock },
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
return {
|
|
|
|
results: [],
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
results: data.commitments,
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
export async function getAllCommitments({ fromBlock, toBlock, chainId }) {
|
2024-05-07 15:34:40 +03:00
|
|
|
try {
|
|
|
|
let commitments = []
|
|
|
|
let lastSyncBlock
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
let { results, lastSyncBlock: lastBlock } = await getCommitments({ fromBlock, chainId })
|
|
|
|
|
|
|
|
lastSyncBlock = lastBlock
|
|
|
|
|
|
|
|
if (isEmpty(results)) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (results.length < breakLength) {
|
|
|
|
commitments = commitments.concat(results)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
const [lastEvent] = results.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
results = results.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
|
|
|
fromBlock = Number(lastEvent.blockNumber)
|
|
|
|
|
|
|
|
commitments = commitments.concat(results)
|
|
|
|
|
|
|
|
if (toBlock && fromBlock >= Number(toBlock)) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!commitments) {
|
|
|
|
return {
|
|
|
|
lastSyncBlock,
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
const data = commitments
|
|
|
|
.map((e) => ({
|
|
|
|
blockNumber: Number(e.blockNumber),
|
|
|
|
transactionHash: e.transactionHash,
|
|
|
|
index: Number(e.index),
|
|
|
|
commitment: e.commitment,
|
|
|
|
encryptedOutput: e.encryptedOutput
|
|
|
|
}))
|
|
|
|
.sort((a, b) => a.index - b.index)
|
2024-05-07 15:34:40 +03:00
|
|
|
|
|
|
|
const [lastEvent] = data.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
return {
|
|
|
|
events: data,
|
2024-05-08 19:55:36 +03:00
|
|
|
lastSyncBlock: (lastEvent && lastEvent.blockNumber >= lastSyncBlock)
|
2024-05-07 15:34:40 +03:00
|
|
|
? lastEvent.blockNumber + numbers.ONE
|
|
|
|
: lastSyncBlock,
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.log('Error from getAllCommitments')
|
|
|
|
console.log(err)
|
|
|
|
return {
|
|
|
|
lastSyncBlock: '',
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
export async function getNullifiers({ fromBlock, chainId }) {
|
2024-05-07 15:34:40 +03:00
|
|
|
const { data } = await client.query({
|
|
|
|
context: {
|
|
|
|
chainId,
|
|
|
|
},
|
|
|
|
query: gql(GET_NULLIFIER),
|
|
|
|
variables: { first, fromBlock },
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
return {
|
|
|
|
results: [],
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
results: data.nullifiers,
|
|
|
|
lastSyncBlock: data._meta.block.number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-08 19:55:36 +03:00
|
|
|
export async function getAllNullifiers({ fromBlock, chainId }) {
|
2024-05-07 15:34:40 +03:00
|
|
|
try {
|
|
|
|
let nullifiers = []
|
|
|
|
let lastSyncBlock
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
let { results, lastSyncBlock: lastBlock } = await getNullifiers({ fromBlock, chainId })
|
|
|
|
|
|
|
|
lastSyncBlock = lastBlock
|
|
|
|
|
|
|
|
if (isEmpty(results)) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (results.length < breakLength) {
|
|
|
|
nullifiers = nullifiers.concat(results)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
const [lastEvent] = results.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
results = results.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
|
|
|
fromBlock = Number(lastEvent.blockNumber)
|
|
|
|
|
|
|
|
nullifiers = nullifiers.concat(results)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nullifiers) {
|
|
|
|
return {
|
|
|
|
lastSyncBlock,
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = nullifiers.map((e) => ({
|
|
|
|
nullifier: e.nullifier,
|
|
|
|
blockNumber: Number(e.blockNumber),
|
|
|
|
transactionHash: e.transactionHash
|
|
|
|
}))
|
|
|
|
|
|
|
|
const [lastEvent] = data.slice(-numbers.ONE)
|
|
|
|
|
|
|
|
return {
|
|
|
|
events: data,
|
2024-05-08 19:55:36 +03:00
|
|
|
lastSyncBlock: (lastEvent && lastEvent.blockNumber >= lastSyncBlock)
|
2024-05-07 15:34:40 +03:00
|
|
|
? lastEvent.blockNumber + numbers.ONE
|
|
|
|
: lastSyncBlock,
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.log('Error from getAllNullifiers')
|
|
|
|
console.log(err)
|
|
|
|
return {
|
|
|
|
lastSyncBlock: '',
|
|
|
|
events: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|