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

Handle 429 error #102

Merged
merged 2 commits into from
Apr 25, 2024
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
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import './types/global'

export * from './utils/enums'
export { createContract } from './contracts'
export { BigDecimal, configs, getGas } from './utils'
export { default as StakeWiseSDK } from './StakeWiseSDK'
export { BigDecimal, configs, getGas, createProvider } from './utils'
2 changes: 2 additions & 0 deletions src/utils/apiUrls.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import configs from './configs'


const getWeb3Url = (options: StakeWise.Options) => options.endpoints?.web3 || configs[options.network].network.url
const getBackendUrl = (options: StakeWise.Options) => options.endpoints?.api || configs[options.network].api.backend
const getSubgraphqlUrl = (options: StakeWise.Options) => options.endpoints?.subgraph || configs[options.network].api.subgraph


export default {
getWeb3Url,
getBackendUrl,
getSubgraphqlUrl,
}
56 changes: 45 additions & 11 deletions src/utils/createProvider.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,60 @@
import { JsonRpcProvider, FallbackProvider } from 'ethers'
import { JsonRpcProvider, FallbackProvider, FetchRequest, FetchResponse } from 'ethers'

import configs from './configs'
import apiUrls from './apiUrls'


const createProvider = (options: StakeWise.Options) => {
const urls = options.endpoints?.web3
const { network } = options

if (!urls) {
return new JsonRpcProvider(configs[options.network].network.url)
}
const urls = apiUrls.getWeb3Url(options)

if (Array.isArray(urls)) {
if (urls.length === 1) {
return new JsonRpcProvider(urls[0])
}
else {
const providers: ConstructorParameters<typeof FallbackProvider>[0] = urls.map((url, index) => ({
provider: new JsonRpcProvider(url),
priority: index + 1,
}))
const providers: ConstructorParameters<typeof FallbackProvider>[0] = urls.map((url, index) => {
// Why do we use FetchRequest and change the behavior of the 429 error?
// Because inside ethers error 429 is handled only by resending the request
// and in this case no additional node is started. This is a problem for public nodes,
// so we think it is better to use an additional node in case of 429 error
const fetchRequest = new FetchRequest(url)

fetchRequest.setThrottleParams({
slotInterval: 2 * 1000,
maxAttempts: 2,
})

fetchRequest.processFunc = async (_, resp) => {
if (resp.statusCode === 429) {
// mutate the response to 500 to start an additional node
// https://github.com/ethers-io/ethers.js/blob/main/src.ts/utils/fetch.ts#L519
const newResponse = new FetchResponse(500, '', resp.headers, null)

return newResponse
}

return resp
}

fetchRequest.retryFunc = async (_, response) => {
if (response.statusCode === 429) {
// stop retry attempts
// https://github.com/ethers-io/ethers.js/blob/main/src.ts/utils/fetch.ts#L556
return false
}

return true
}

return {
provider: new JsonRpcProvider(fetchRequest, network),
priority: index + 1,
weight: 1,
}
})

const provider = new FallbackProvider(providers) as StakeWise.CustomFallbackProvider
const provider = new FallbackProvider(providers, network) as StakeWise.CustomFallbackProvider

provider.getSigner = () => {
throw new Error('Pass your provider to the SDK class instance to get a signer')
Expand Down
Loading