init
This commit is contained in:
commit
44f31f8b9f
402 changed files with 47865 additions and 0 deletions
423
services/graph.js
Normal file
423
services/graph.js
Normal file
|
@ -0,0 +1,423 @@
|
|||
import { ApolloClient, InMemoryCache, gql } from '@apollo/client/core'
|
||||
|
||||
import {
|
||||
_META,
|
||||
GET_DEPOSITS,
|
||||
GET_STATISTIC,
|
||||
GET_REGISTERED,
|
||||
GET_WITHDRAWALS,
|
||||
GET_NOTE_ACCOUNTS,
|
||||
GET_ENCRYPTED_NOTES
|
||||
} from './queries'
|
||||
|
||||
const isEmptyArray = (arr) => !Array.isArray(arr) || !arr.length
|
||||
|
||||
const first = 1000
|
||||
|
||||
const link = ({ getContext }) => {
|
||||
const { chainId } = getContext()
|
||||
return CHAIN_GRAPH_URLS[chainId]
|
||||
}
|
||||
|
||||
const CHAIN_GRAPH_URLS = {
|
||||
1: 'https://api.thegraph.com/subgraphs/name/tornadocash/mainnet-tornado-subgraph',
|
||||
5: 'https://api.thegraph.com/subgraphs/name/tornadocash/goerli-tornado-subgraph',
|
||||
10: 'https://api.thegraph.com/subgraphs/name/tornadocash/optimism-tornado-subgraph',
|
||||
56: 'https://api.thegraph.com/subgraphs/name/tornadocash/bsc-tornado-subgraph',
|
||||
100: 'https://api.thegraph.com/subgraphs/name/tornadocash/xdai-tornado-subgraph',
|
||||
137: 'https://api.thegraph.com/subgraphs/name/tornadocash/matic-tornado-subgraph',
|
||||
42161: 'https://api.thegraph.com/subgraphs/name/tornadocash/arbitrum-tornado-subgraph',
|
||||
43114: 'https://api.thegraph.com/subgraphs/name/tornadocash/avalanche-tornado-subgraph'
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
query: {
|
||||
fetchPolicy: 'no-cache',
|
||||
errorPolicy: 'all'
|
||||
}
|
||||
}
|
||||
|
||||
const client = new ApolloClient({
|
||||
uri: link,
|
||||
cache: new InMemoryCache(),
|
||||
defaultOptions
|
||||
})
|
||||
|
||||
const registryClient = new ApolloClient({
|
||||
uri: 'https://api.thegraph.com/subgraphs/name/tornadocash/tornado-relayer-registry',
|
||||
cache: new InMemoryCache(),
|
||||
defaultOptions
|
||||
})
|
||||
|
||||
async function getStatistic({ currency, amount, netId }) {
|
||||
try {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(GET_STATISTIC),
|
||||
variables: {
|
||||
currency,
|
||||
first: 10,
|
||||
orderBy: 'index',
|
||||
orderDirection: 'desc',
|
||||
amount: String(amount)
|
||||
}
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
|
||||
const { deposits } = data
|
||||
|
||||
const lastSyncBlock = await getMeta({ netId })
|
||||
|
||||
const events = deposits
|
||||
.map((e) => ({
|
||||
timestamp: e.timestamp,
|
||||
leafIndex: Number(e.index),
|
||||
blockNumber: Number(e.blockNumber)
|
||||
}))
|
||||
.reverse()
|
||||
|
||||
const [lastEvent] = events.slice(-1)
|
||||
|
||||
return {
|
||||
lastSyncBlock: lastEvent?.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock,
|
||||
events
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllRegisters(fromBlock) {
|
||||
try {
|
||||
const relayers = await getRegisters(fromBlock)
|
||||
|
||||
if (!relayers) {
|
||||
return { lastSyncBlock: '', events: [] }
|
||||
}
|
||||
|
||||
const lastSyncBlock = await getRegisteredMeta()
|
||||
|
||||
return { lastSyncBlock, events: relayers }
|
||||
} catch {
|
||||
return { lastSyncBlock: '', events: [] }
|
||||
}
|
||||
}
|
||||
async function getAllDeposits({ currency, amount, fromBlock, netId }) {
|
||||
try {
|
||||
let deposits = []
|
||||
|
||||
while (true) {
|
||||
let result = await getDeposits({ currency, amount, fromBlock, netId })
|
||||
|
||||
if (isEmptyArray(result)) {
|
||||
break
|
||||
}
|
||||
|
||||
if (result.length < 900) {
|
||||
deposits = deposits.concat(result)
|
||||
break
|
||||
}
|
||||
|
||||
const [lastEvent] = result.slice(-1)
|
||||
|
||||
result = result.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
||||
fromBlock = Number(lastEvent.blockNumber)
|
||||
|
||||
deposits = deposits.concat(result)
|
||||
}
|
||||
|
||||
if (!deposits) {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
|
||||
const lastSyncBlock = await getMeta({ netId })
|
||||
|
||||
const data = deposits.map((e) => ({
|
||||
...e,
|
||||
leafIndex: Number(e.index),
|
||||
blockNumber: Number(e.blockNumber)
|
||||
}))
|
||||
|
||||
const [lastEvent] = data.slice(-1)
|
||||
|
||||
return {
|
||||
events: data,
|
||||
lastSyncBlock: lastEvent?.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getMeta({ netId }) {
|
||||
try {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(_META)
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return data._meta.block.number
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function getRegisteredMeta() {
|
||||
try {
|
||||
const { data } = await registryClient.query({
|
||||
context: {
|
||||
chainId: 1
|
||||
},
|
||||
query: gql(_META)
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return data._meta.block.number
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function getRegisters(fromBlock) {
|
||||
const { data } = await registryClient.query({
|
||||
context: {
|
||||
chainId: 1
|
||||
},
|
||||
query: gql(GET_REGISTERED),
|
||||
variables: { first, fromBlock }
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.relayers
|
||||
}
|
||||
|
||||
async function getDeposits({ currency, amount, fromBlock, netId }) {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(GET_DEPOSITS),
|
||||
variables: { currency, amount: String(amount), first, fromBlock }
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.deposits
|
||||
}
|
||||
|
||||
async function getAllWithdrawals({ currency, amount, fromBlock, netId }) {
|
||||
try {
|
||||
let withdrawals = []
|
||||
|
||||
while (true) {
|
||||
let result = await getWithdrawals({ currency, amount, fromBlock, netId })
|
||||
|
||||
if (isEmptyArray(result)) {
|
||||
break
|
||||
}
|
||||
|
||||
if (result.length < 900) {
|
||||
withdrawals = withdrawals.concat(result)
|
||||
break
|
||||
}
|
||||
|
||||
const [lastEvent] = result.slice(-1)
|
||||
|
||||
result = result.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
||||
fromBlock = Number(lastEvent.blockNumber)
|
||||
|
||||
withdrawals = withdrawals.concat(result)
|
||||
}
|
||||
|
||||
if (!withdrawals) {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
|
||||
const lastSyncBlock = await getMeta({ netId })
|
||||
|
||||
const data = withdrawals.map((e) => ({
|
||||
...e,
|
||||
nullifierHash: e.nullifier,
|
||||
leafIndex: Number(e.index),
|
||||
blockNumber: Number(e.blockNumber)
|
||||
}))
|
||||
|
||||
const [lastEvent] = data.slice(-1)
|
||||
|
||||
return {
|
||||
events: data,
|
||||
lastSyncBlock: lastEvent?.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getWithdrawals({ currency, amount, fromBlock, netId }) {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(GET_WITHDRAWALS),
|
||||
variables: { currency, amount: String(amount), fromBlock, first }
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.withdrawals
|
||||
}
|
||||
|
||||
async function getNoteAccounts({ address, netId }) {
|
||||
try {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(GET_NOTE_ACCOUNTS),
|
||||
variables: { address }
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
|
||||
const lastSyncBlock = await getMeta({ netId })
|
||||
|
||||
return {
|
||||
lastSyncBlock,
|
||||
events: data.noteAccounts
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllEncryptedNotes({ fromBlock, netId }) {
|
||||
try {
|
||||
let encryptedNotes = []
|
||||
|
||||
while (true) {
|
||||
let result = await getEncryptedNotes({ fromBlock, netId })
|
||||
|
||||
if (isEmptyArray(result)) {
|
||||
break
|
||||
}
|
||||
|
||||
if (result.length < 900) {
|
||||
encryptedNotes = encryptedNotes.concat(result)
|
||||
break
|
||||
}
|
||||
|
||||
const [lastEvent] = result.slice(-1)
|
||||
|
||||
result = result.filter((e) => e.blockNumber !== lastEvent.blockNumber)
|
||||
fromBlock = Number(lastEvent.blockNumber)
|
||||
|
||||
encryptedNotes = encryptedNotes.concat(result)
|
||||
|
||||
if (isEmptyArray(result)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!encryptedNotes) {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
|
||||
const lastSyncBlock = await getMeta({ netId })
|
||||
|
||||
const data = encryptedNotes.map((e) => ({
|
||||
txHash: e.transactionHash,
|
||||
encryptedNote: e.encryptedNote,
|
||||
transactionHash: e.transactionHash,
|
||||
blockNumber: Number(e.blockNumber)
|
||||
}))
|
||||
|
||||
const [lastEvent] = data.slice(-1)
|
||||
|
||||
return {
|
||||
events: data,
|
||||
lastSyncBlock: lastEvent?.blockNumber >= lastSyncBlock ? lastEvent.blockNumber + 1 : lastSyncBlock
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
lastSyncBlock: '',
|
||||
events: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getEncryptedNotes({ fromBlock, netId }) {
|
||||
const { data } = await client.query({
|
||||
context: {
|
||||
chainId: netId
|
||||
},
|
||||
query: gql(GET_ENCRYPTED_NOTES),
|
||||
variables: { fromBlock, first }
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.encryptedNotes
|
||||
}
|
||||
|
||||
export default {
|
||||
getDeposits,
|
||||
getStatistic,
|
||||
getAllDeposits,
|
||||
getWithdrawals,
|
||||
getNoteAccounts,
|
||||
getAllRegisters,
|
||||
getAllWithdrawals,
|
||||
getAllEncryptedNotes
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue