Skip to content

Commit

Permalink
feat(unirpc): send 10% bnb traffic to unirpc
Browse files Browse the repository at this point in the history
  • Loading branch information
xrsv committed Sep 23, 2024
1 parent dc27299 commit dcf2555
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 29 deletions.
4 changes: 4 additions & 0 deletions bin/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ export class RoutingAPIPipeline extends Stack {
// ZkSync
'QUICKNODE_324',
'ALCHEMY_324',
// unirpc - serves all chains
'UNIRPC_0',
]
for (const provider of RPC_GATEWAY_PROVIDERS) {
jsonRpcProviders[provider] = jsonRpcProvidersSecret.secretValueFromJson(provider).toString()
Expand Down Expand Up @@ -408,6 +410,8 @@ const jsonRpcProviders = {
// ZkSync
QUICKNODE_324: process.env.QUICKNODE_324!,
ALCHEMY_324: process.env.ALCHEMY_324!,
// unirpc - serves all chains
UNIRPC_0: process.env.UNIRPC_0!,
}

// Local dev stack
Expand Down
38 changes: 25 additions & 13 deletions lib/config/rpcProviderProdConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,35 @@
"latencyEvaluationSampleProb": 0.1,
"healthCheckSampleProb": 0.1,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_42220"]
"providerUrls": ["QUICKNODE_42220"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 43114,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.1,
"healthCheckSampleProb": 0.1,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_43114"]
"providerUrls": ["QUICKNODE_43114"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 56,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.01,
"healthCheckSampleProb": 0.01,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_56"]
"providerInitialWeights": [0.9, 0.1],
"providerUrls": ["QUICKNODE_56", "UNIRPC_0"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 10,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.1,
"healthCheckSampleProb": 0.01,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_10"]
"providerUrls": ["QUICKNODE_10"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 11155111,
Expand All @@ -38,6 +42,7 @@
"healthCheckSampleProb": 0.01,
"providerInitialWeights": [1],
"providerUrls": ["ALCHEMY_11155111"],
"providerNames": ["ALCHEMY"],
"enableDbSync": true
},
{
Expand All @@ -46,54 +51,61 @@
"latencyEvaluationSampleProb": 0.25,
"healthCheckSampleProb": 0.005,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_137"]
"providerUrls": ["QUICKNODE_137"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 42161,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.1,
"healthCheckSampleProb": 0.002,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_42161"]
"providerUrls": ["QUICKNODE_42161"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 8453,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.05,
"healthCheckSampleProb": 0.0005,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_8453"]
"providerUrls": ["QUICKNODE_8453"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 1,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.05,
"healthCheckSampleProb": 0.001,
"providerInitialWeights": [1, 0],
"providerUrls": ["QUICKNODE_1", "QUICKNODERETH_1"]
"providerInitialWeights": [0.01, 0.99],
"providerUrls": ["QUICKNODE_1"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 81457,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.001,
"healthCheckSampleProb": 0.001,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_81457"]
"providerUrls": ["QUICKNODE_81457"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 7777777,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.001,
"healthCheckSampleProb": 0.001,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_7777777"]
"providerUrls": ["QUICKNODE_7777777"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 324,
"useMultiProviderProb": 1,
"latencyEvaluationSampleProb": 0.01,
"healthCheckSampleProb": 0.01,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_324"]
"providerUrls": ["QUICKNODE_324"],
"providerNames": ["QUICKNODE"]
}
]
15 changes: 13 additions & 2 deletions lib/rpc/GlobalRpcProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class GlobalRpcProviders {
if (process.env[urlEnvVar] === undefined) {
throw new Error(`Environmental variable ${urlEnvVar} isn't defined!`)
}
chainConfig.providerUrls[i] = generateProviderUrl(urlEnvVar, process.env[urlEnvVar]!)
chainConfig.providerUrls[i] = generateProviderUrl(urlEnvVar, process.env[urlEnvVar]!, chainConfig.chainId)
}
}
return prodConfig
Expand All @@ -51,11 +51,22 @@ export class GlobalRpcProviders {
const chainId = chainConfig.chainId as ChainId
if (Math.random() < chainConfig.useMultiProviderProb) {
let providers: SingleJsonRpcProvider[] = []
for (const providerUrl of chainConfig.providerUrls!) {

for (let i = 0; i < chainConfig.providerUrls!.length; i++) {
// For unirpc provider, pass the service id in the header.
const providerUrl = chainConfig.providerUrls![i]
const headers =
chainConfig.providerNames![i] === 'UNIRPC'
? {
'x-uni-service-id': 'routing_api',
}
: undefined

providers.push(
new SingleJsonRpcProvider(
{ name: chainIdToNetworkName(chainId), chainId },
providerUrl,
headers,
log,
singleConfig,
chainConfig.enableDbSync!,
Expand Down
2 changes: 2 additions & 0 deletions lib/rpc/ProdConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ChainConfig {
sessionAllowProviderFallbackWhenUnhealthy?: boolean
providerInitialWeights?: number[]
providerUrls?: string[]
providerNames?: string[]
dbSyncSampleProb?: number
latencyEvaluationSampleProb?: number
healthCheckSampleProb?: number
Expand All @@ -23,6 +24,7 @@ export const ProdConfigJoi = Joi.array().items(
sessionAllowProviderFallbackWhenUnhealthy: Joi.boolean().optional(),
providerInitialWeights: Joi.array().items(Joi.number()).optional(),
providerUrls: Joi.array().items(Joi.string()).optional(),
providerNames: Joi.array().items(Joi.string()).optional(),
dbSyncSampleProb: Joi.number().min(0.0).max(1.0).optional().default(1.0),
latencyEvaluationSampleProb: Joi.number().min(0.0).max(1.0).optional().default(1.0),
healthCheckSampleProb: Joi.number().min(0.0).max(1.0).optional().default(1.0),
Expand Down
9 changes: 8 additions & 1 deletion lib/rpc/SingleJsonRpcProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,19 @@ export class SingleJsonRpcProvider extends StaticJsonRpcProvider {
constructor(
network: Network,
url: string,
headers: Record<string, string | number> | undefined,
log: Logger,
config: SingleJsonRpcProviderConfig,
enableDbSync: boolean,
dbSyncSampleProb: number
) {
super(url, network)
super(
{
url: url,
headers: headers,
},
network
)
this.url = url
this.log = log
this.providerName = deriveProviderName(url)
Expand Down
8 changes: 7 additions & 1 deletion lib/rpc/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ export function chainIdToNetworkName(networkId: ChainId): string {
}
}

export function generateProviderUrl(key: string, value: string): string {
export function generateProviderUrl(key: string, value: string, chainId: number): string {
if (key === 'UNIRPC_0') {
// UNIRPC_0 is a special case for the Uniswap RPC
// - env value will contain the generic unirpc endpoint - no trailing '/'
return `${value}/rpc/${chainId}`
}

const tokens = value.split(',')
switch (key) {
// Infura
Expand Down
4 changes: 4 additions & 0 deletions test/mocha/unit/rpc/GlobalRpcProviders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ describe('GlobalRpcProviders', () => {
sessionAllowProviderFallbackWhenUnhealthy: true,
providerInitialWeights: [2, 1],
providerUrls: ['INFURA_43114', 'QUICKNODE_43114'],
providerNames: ['INFURA', 'QUICKNODE'],
},
]

Expand Down Expand Up @@ -116,13 +117,15 @@ describe('GlobalRpcProviders', () => {
chainId: 10,
useMultiProviderProb: 0.3,
providerUrls: ['INFURA_10', 'QUICKNODE_10'],
providerNames: ['INFURA', 'QUICKNODE'],
},
{
chainId: 43114,
useMultiProviderProb: 0.7,
sessionAllowProviderFallbackWhenUnhealthy: true,
providerInitialWeights: [2, 1],
providerUrls: ['INFURA_43114', 'QUICKNODE_43114'],
providerNames: ['INFURA', 'QUICKNODE'],
},
]

Expand Down Expand Up @@ -273,6 +276,7 @@ describe('GlobalRpcProviders', () => {
ALCHEMY_1: 'key25',
QUICKNODE_81457: 'host26,key26',
INFURA_81457: 'key27',
UNIRPC_0: 'key28',
}

const randStub = sandbox.stub(Math, 'random')
Expand Down
10 changes: 9 additions & 1 deletion test/mocha/unit/rpc/ProdConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect } from 'chai'
import { getRpcGatewayEnabledChains, ProdConfig, ProdConfigJoi } from '../../../../lib/rpc/ProdConfig'
import TEST_PROD_CONFIG from './rpcProviderTestProdConfig.json'
import PROD_CONFIG from '../../../../lib/config/rpcProviderProdConfig.json'
import { ChainId } from '@uniswap/sdk-core'

describe('ProdConfig', () => {
Expand Down Expand Up @@ -85,7 +86,14 @@ describe('ProdConfig', () => {
expect(enabledChains.get(ChainId.POLYGON)).to.have.members(['QUICKNODE', 'INFURA', 'ALCHEMY'])
expect(enabledChains.get(ChainId.ARBITRUM_ONE)).to.have.members(['QUICKNODE', 'INFURA', 'ALCHEMY', 'NIRVANA'])
expect(enabledChains.get(ChainId.BASE)).to.have.members(['QUICKNODE', 'INFURA', 'ALCHEMY', 'NIRVANA'])
expect(enabledChains.get(ChainId.MAINNET)).to.have.members(['QUICKNODE', 'INFURA', 'ALCHEMY', 'NIRVANA'])
expect(enabledChains.get(ChainId.MAINNET)).to.have.members(['QUICKNODE', 'INFURA', 'ALCHEMY', 'NIRVANA', 'UNIRPC'])
expect(enabledChains.get(ChainId.BLAST)).to.have.members(['QUICKNODE', 'INFURA'])
})

it('validates prod config', () => {
for (const entry of PROD_CONFIG) {
expect(entry.providerUrls.length == entry.providerInitialWeights.length)
expect(entry.providerUrls.length == entry.providerNames.length)
}
})
})
2 changes: 2 additions & 0 deletions test/mocha/unit/rpc/SingleJsonRpcProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe('SingleJsonRpcProvider', () => {
name: 'mainnet',
},
'provider_0_url',
undefined,
log,
config,
false,
Expand Down Expand Up @@ -200,6 +201,7 @@ describe('SingleJsonRpcProvider', () => {
name: 'mainnet',
},
'provider_0_url',
undefined,
log,
config,
false,
Expand Down
3 changes: 3 additions & 0 deletions test/mocha/unit/rpc/UniJsonRpcProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const createNewSingleJsonRpcProviders = () => [
new SingleJsonRpcProvider(
{ name: 'mainnet', chainId: ChainId.MAINNET },
`url_0`,
undefined,
log,
SINGLE_PROVIDER_TEST_CONFIG,
false,
Expand All @@ -53,6 +54,7 @@ const createNewSingleJsonRpcProviders = () => [
new SingleJsonRpcProvider(
{ name: 'mainnet', chainId: ChainId.MAINNET },
`url_1`,
undefined,
log,
SINGLE_PROVIDER_TEST_CONFIG,
false,
Expand All @@ -61,6 +63,7 @@ const createNewSingleJsonRpcProviders = () => [
new SingleJsonRpcProvider(
{ name: 'mainnet', chainId: ChainId.MAINNET },
`url_2`,
undefined,
log,
SINGLE_PROVIDER_TEST_CONFIG,
false,
Expand Down
32 changes: 21 additions & 11 deletions test/mocha/unit/rpc/rpcProviderTestProdConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,70 @@
"chainId": 42220,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0],
"providerUrls": ["QUICKNODE_42220", "INFURA_42220"]
"providerUrls": ["QUICKNODE_42220", "INFURA_42220"],
"providerNames": ["QUICKNODE", "INFURA"]
},
{
"chainId": 43114,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0, 0],
"providerUrls": ["INFURA_43114", "QUICKNODE_43114", "NIRVANA_43114"]
"providerUrls": ["INFURA_43114", "QUICKNODE_43114", "NIRVANA_43114"],
"providerNames": ["INFURA", "QUICKNODE", "NIRVANA"]
},
{
"chainId": 56,
"useMultiProviderProb": 1,
"providerInitialWeights": [1],
"providerUrls": ["QUICKNODE_56"]
"providerUrls": ["QUICKNODE_56"],
"providerNames": ["QUICKNODE"]
},
{
"chainId": 10,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0, 0],
"providerUrls": ["INFURA_10", "QUICKNODE_10", "ALCHEMY_10"]
"providerUrls": ["INFURA_10", "QUICKNODE_10", "ALCHEMY_10"],
"providerNames": ["INFURA", "QUICKNODE", "ALCHEMY"]
},
{
"chainId": 11155111,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0],
"providerUrls": ["INFURA_11155111", "ALCHEMY_11155111"]
"providerUrls": ["INFURA_11155111", "ALCHEMY_11155111"],
"providerNames": ["INFURA", "ALCHEMY"]
},
{
"chainId": 137,
"useMultiProviderProb": 0.01,
"providerInitialWeights": [1, 0, 0],
"providerUrls": ["QUICKNODE_137", "INFURA_137", "ALCHEMY_137"]
"providerUrls": ["QUICKNODE_137", "INFURA_137", "ALCHEMY_137"],
"providerNames": ["QUICKNODE", "INFURA", "ALCHEMY"]
},
{
"chainId": 42161,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 1, 1, 1],
"providerUrls": ["INFURA_42161", "QUICKNODE_42161", "NIRVANA_42161", "ALCHEMY_42161"]
"providerUrls": ["INFURA_42161", "QUICKNODE_42161", "NIRVANA_42161", "ALCHEMY_42161"],
"providerNames": ["INFURA", "QUICKNODE", "NIRVANA", "ALCHEMY"]
},
{
"chainId": 8453,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0, 0, 0],
"providerUrls": ["QUICKNODE_8453", "INFURA_8453", "ALCHEMY_8453", "NIRVANA_8453"]
"providerUrls": ["QUICKNODE_8453", "INFURA_8453", "ALCHEMY_8453", "NIRVANA_8453"],
"providerNames": ["QUICKNODE", "INFURA", "ALCHEMY", "NIRVANA"]
},
{
"chainId": 1,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0, 0, 0],
"providerUrls": ["INFURA_1", "QUICKNODE_1", "NIRVANA_1", "ALCHEMY_1"]
"providerInitialWeights": [1, 0, 0, 0, 0],
"providerUrls": ["INFURA_1", "QUICKNODE_1", "NIRVANA_1", "ALCHEMY_1", "UNIRPC_0"],
"providerNames": ["INFURA", "QUICKNODE", "NIRVANA", "ALCHEMY", "UNIRPC"]
},
{
"chainId": 81457,
"useMultiProviderProb": 1,
"providerInitialWeights": [1, 0],
"providerUrls": ["QUICKNODE_81457", "INFURA_81457"]
"providerUrls": ["QUICKNODE_81457", "INFURA_81457"],
"providerNames": ["QUICKNODE", "INFURA"]
}
]

0 comments on commit dcf2555

Please sign in to comment.