Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

indexer-common: Support connecting to any protocol network #513

Merged
merged 1 commit into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 16 additions & 92 deletions packages/indexer-agent/src/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from '@graphprotocol/indexer-common'
import { startAgent } from '../agent'
import { Indexer } from '../indexer'
import { providers, Wallet } from 'ethers'
import { Wallet } from 'ethers'
import { startCostModelAutomation } from '../cost'
import { createSyncingServer } from '../syncing-server'
import { monitorEthBalance } from '../utils'
Expand All @@ -53,7 +53,7 @@ export default {
description: 'Ethereum network',
type: 'string',
required: false,
default: 'mainnet',
default: 'any',
group: 'Ethereum',
})
.option('ethereum-polling-interval', {
Expand Down Expand Up @@ -581,107 +581,31 @@ export default {
await sequelize.sync()
logger.info(`Successfully synced database models`)

logger.info(`Connect to Ethereum`, {
provider: argv.ethereum,
network: argv.ethereumNetwork,
})

let providerUrl
try {
providerUrl = new URL(argv.ethereum)
} catch (err) {
logger.fatal(`Invalid Ethereum URL`, {
err: indexerError(IndexerErrorCode.IE002, err),
url: argv.ethereum,
})
process.exit(1)
return
}

const ethProviderMetrics = {
requests: new metrics.client.Counter({
name: 'eth_provider_requests',
help: 'Ethereum provider requests',
registers: [metrics.registry],
labelNames: ['method'],
}),
}

if (providerUrl.password && providerUrl.protocol == 'http:') {
logger.warn(
'Ethereum endpoint does not use HTTPS, your authentication credentials may not be secure',
)
}

// Prevent passing empty basicAuth info
let username
let password
if (providerUrl.username == '' && providerUrl.password == '') {
username = undefined
password = undefined
} else {
username = providerUrl.username
password = providerUrl.password
}

const ethereumProvider = new providers.StaticJsonRpcProvider(
{
url: providerUrl.toString(),
user: username,
password: password,
allowInsecureAuthentication: true,
},
const networkProvider = await Network.provider(
logger,
metrics,
argv.ethereumNetwork,
argv.ethereum,
argv.ethereumPollingInterval,
)
ethereumProvider.pollingInterval = argv.ethereumPollingInterval

ethereumProvider.on('debug', info => {
if (info.action === 'response') {
ethProviderMetrics.requests.inc({
method: info.request.method,
})

logger.trace('Ethereum request', {
method: info.request.method,
params: info.request.params,
response: info.response,
})
}
})

ethereumProvider.on('network', (newNetwork, oldNetwork) => {
logger.trace('Ethereum network change', {
oldNetwork: oldNetwork,
newNetwork: newNetwork,
})
})

const networkMeta = await ethereumProvider.getNetwork()
logger.info(`Connected to Ethereum`, {
provider: ethereumProvider.connection.url,
pollingInterval: ethereumProvider.pollingInterval,
network: await ethereumProvider.detectNetwork(),
})
const networkMeta = await networkProvider.getNetwork()

logger.info(`Connect wallet`, {
network: ethereumProvider.network.name,
chainId: ethereumProvider.network.chainId,
network: networkMeta.name,
chainId: networkMeta.chainId,
})
let wallet = Wallet.fromMnemonic(argv.mnemonic)
wallet = wallet.connect(ethereumProvider)
wallet = wallet.connect(networkProvider)
logger.info(`Connected wallet`)

logger.info(`Connect to contracts`, {
network: networkMeta.name,
chainId: networkMeta.chainId,
providerNetworkChainID: ethereumProvider.network.chainId,
providerNetworkChainID: networkProvider.network.chainId,
})
let contracts = undefined
try {
contracts = await connectContracts(
wallet,
ethereumProvider.network.chainId,
)
contracts = await connectContracts(wallet, networkMeta.chainId)
} catch (err) {
logger.error(
`Failed to connect to contracts, please ensure you are using the intended Ethereum network`,
Expand Down Expand Up @@ -731,7 +655,7 @@ export default {
const maxGasFee = argv.baseFeeGasMax || argv.gasPriceMax
const network = await Network.create(
logger,
ethereumProvider,
networkProvider,
contracts,
wallet,
indexerAddress,
Expand Down Expand Up @@ -772,7 +696,7 @@ export default {
logger.child({ component: 'NetworkMonitor' }),
indexingStatusResolver,
networkSubgraph,
ethereumProvider,
networkProvider,
epochSubgraph,
)

Expand Down Expand Up @@ -847,7 +771,7 @@ export default {

startCostModelAutomation({
logger,
ethereum: ethereumProvider,
ethereum: networkProvider,
contracts: network.contracts,
indexerManagement: indexerManagementClient,
injectDai: argv.injectDai,
Expand Down
89 changes: 89 additions & 0 deletions packages/indexer-common/src/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Eventual,
formatGRT,
Logger,
Metrics,
mutable,
NetworkContracts,
SubgraphDeploymentID,
Expand Down Expand Up @@ -154,6 +155,94 @@ export class Network {
)
}

static async provider(
logger: Logger,
metrics: Metrics,
networkName: string,
networkURL: string,
pollingInterval: number,
): Promise<providers.StaticJsonRpcProvider> {
logger.info(`Connect to Network chain`, {
provider: networkURL,
})

let providerUrl
try {
providerUrl = new URL(networkURL)
} catch (err) {
logger.fatal(`Invalid Network provider URL`, {
err: indexerError(IndexerErrorCode.IE002, err),
url: networkURL,
})
process.exit(1)
}

const ethProviderMetrics = {
requests: new metrics.client.Counter({
name: 'eth_provider_requests',
help: 'Ethereum provider requests',
registers: [metrics.registry],
labelNames: ['method'],
}),
}

if (providerUrl.password && providerUrl.protocol == 'http:') {
logger.warn(
'Network endpoint does not use HTTPS, your authentication credentials may not be secure',
)
}

let username
let password
if (providerUrl.username == '' && providerUrl.password == '') {
username = undefined
password = undefined
} else {
username = providerUrl.username
password = providerUrl.password
}

const networkProvider = new providers.StaticJsonRpcProvider(
{
url: providerUrl.toString(),
user: username,
password: password,
allowInsecureAuthentication: true,
},
networkName,
)
networkProvider.pollingInterval = pollingInterval

networkProvider.on('debug', (info) => {
if (info.action === 'response') {
ethProviderMetrics.requests.inc({
method: info.request.method,
})

logger.trace('Network request', {
method: info.request.method,
params: info.request.params,
response: info.response,
})
}
})

networkProvider.on('network', (newNetwork, oldNetwork) => {
logger.trace('Network change', {
oldNetwork: oldNetwork,
newNetwork: newNetwork,
})
})

logger.info(`Connected to network`, {
provider: networkProvider.connection.url,
pollingInterval: networkProvider.pollingInterval,
network: await networkProvider.detectNetwork(),
})

return networkProvider
}

// TODO: Move to NetworkMonitor
async claimableAllocations(disputableEpoch: number): Promise<Allocation[]> {
try {
Expand Down
Loading