2023-05-03 22:56:02 +03:00
|
|
|
import axios from 'axios'
|
|
|
|
|
2023-08-01 15:15:32 +03:00
|
|
|
import { ChainId, Relayer, RelayerParsedVersion } from '@/types'
|
2023-05-03 22:56:02 +03:00
|
|
|
|
|
|
|
import { errors } from '@/constants'
|
|
|
|
import { getProvider, getRelayerValidateFunction } from '@/services'
|
|
|
|
|
2023-08-01 15:15:32 +03:00
|
|
|
import { GetTornadoStatusParams, RelayerParsedData } from '../@types'
|
2023-05-03 22:56:02 +03:00
|
|
|
|
2023-08-01 15:15:32 +03:00
|
|
|
async function getRelayerData({
|
|
|
|
url,
|
|
|
|
ensName,
|
|
|
|
hasEnabledLightProxy,
|
|
|
|
chainId = ChainId.MAINNET,
|
|
|
|
}: GetTornadoStatusParams): Promise<RelayerParsedData> {
|
2023-05-03 22:56:02 +03:00
|
|
|
let response = null
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (!url) {
|
|
|
|
throw new Error(errors.validation.INVALID_RELAYER)
|
|
|
|
}
|
|
|
|
|
|
|
|
response = await axios.get<Relayer>(`${url}/status`)
|
|
|
|
} catch {
|
|
|
|
if (ensName) {
|
|
|
|
const relayerData = await getRelayerDataFromENS(ensName, chainId)
|
|
|
|
|
|
|
|
if (relayerData) {
|
|
|
|
await checkProtocol(relayerData.txt)
|
|
|
|
response = await axios.get<Relayer>(`${relayerData.url}/status`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!response) {
|
|
|
|
throw new Error(errors.validation.NO_RESPONSE)
|
|
|
|
}
|
|
|
|
|
|
|
|
const validate = getRelayerValidateFunction(chainId)
|
|
|
|
|
|
|
|
const isValid = await validate(response.data)
|
|
|
|
|
|
|
|
if (!isValid) {
|
|
|
|
return { isValid: false }
|
|
|
|
}
|
|
|
|
|
2023-08-01 15:15:32 +03:00
|
|
|
const semVerRegex =
|
|
|
|
/^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
|
|
|
const regexpResult = semVerRegex.exec(response.data.version)
|
|
|
|
const invalidVersionData = { isValid: false, address: response.data.rewardAccount, chainId: response.data.netId }
|
2023-05-03 22:56:02 +03:00
|
|
|
|
2023-08-01 15:15:32 +03:00
|
|
|
if (!regexpResult?.groups) {
|
|
|
|
console.error('askRelayerStatus', url || ensName, 'Version specified incorrectly.')
|
|
|
|
return invalidVersionData
|
|
|
|
}
|
|
|
|
|
|
|
|
const { major } = regexpResult.groups as RelayerParsedVersion
|
2023-08-06 10:52:17 +03:00
|
|
|
const minimalMajorVersion = 4
|
2023-08-01 15:15:32 +03:00
|
|
|
const isMajorVersionUpdated = Number(major) >= minimalMajorVersion
|
|
|
|
|
|
|
|
if (!isMajorVersionUpdated) {
|
2023-05-03 22:56:02 +03:00
|
|
|
console.error('askRelayerStatus', url || ensName, 'Outdated version.')
|
2023-08-01 15:15:32 +03:00
|
|
|
return invalidVersionData
|
2023-05-03 22:56:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return { isValid, address: response.data.rewardAccount, chainId: response.data.netId }
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkProtocol(txt: string) {
|
|
|
|
if (txt.includes('http')) {
|
|
|
|
throw new Error(errors.validation.TXT_WITH_PROTOCOL)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getRelayerDataFromENS(ensName: string, chainId: ChainId = ChainId.MAINNET) {
|
|
|
|
try {
|
|
|
|
if (!ensName.includes('.eth')) {
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
const { provider } = getProvider(chainId)
|
|
|
|
|
|
|
|
const resolver = await provider.getResolver(ensName)
|
|
|
|
|
|
|
|
if (!resolver) {
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
const url = await resolver.getText('url')
|
|
|
|
|
|
|
|
if (!url) {
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
txt: url,
|
|
|
|
url: `${window.location.protocol}//${url}`,
|
|
|
|
address: resolver.address,
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const tornadoRelayerService = {
|
|
|
|
checkProtocol,
|
|
|
|
getRelayerData,
|
|
|
|
getRelayerDataFromENS,
|
|
|
|
}
|