From 064c481c02f6c11038ba26aa393050764937da6f Mon Sep 17 00:00:00 2001 From: gozzy Date: Fri, 2 Dec 2022 21:02:43 +0000 Subject: [PATCH 01/11] event retry & err conditioning --- services/events.js | 70 +++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/services/events.js b/services/events.js index 7d951f2..7fee968 100644 --- a/services/events.js +++ b/services/events.js @@ -292,6 +292,8 @@ class EventService { i !== 5, i ) + } else { + throw new Error(`Failed to fetch block ${toBlock}`) } } @@ -310,23 +312,16 @@ class EventService { } } - createBatchRequest({ batchIndex, batchSize, batchBlocks, blockDenom, type }) { - return new Array(batchSize).fill('').map( - (_, i) => + createBatchRequest(batchArray) { + return batchArray.map( + (e, i) => new Promise(async (resolve) => { - const toBlock = batchBlocks[batchIndex * batchSize + i] - const fromBlock = toBlock - blockDenom - - const batchEvents = await this.getEventsPartFromRpc( - { - fromBlock, - toBlock, - type - }, - true - ) - - resolve(batchEvents.events) + try { + const { events } = await this.getEventsPartFromRpc({ ...e }, true) + resolve(events) + } catch (e) { + resolve({ isFailedBatch: true, ...e }) + } }) ) } @@ -335,30 +330,47 @@ class EventService { try { const batchSize = 10 const blockRange = 10000 - const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock }) + let [events, failed] = [[], []] + let lastBlock = fromBlock + + const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock }) const batchDigest = blockDifference === 0 ? 1 : Math.ceil(blockDifference / blockRange) + const blockDenom = Math.ceil(blockDifference / batchDigest) const batchCount = Math.ceil(batchDigest / batchSize) - const blocks = new Array(batchCount * batchSize).fill('') - const batchBlocks = blocks.map((_, i) => (i + 1) * blockDenom + fromBlock) - - let events = [] - if (fromBlock < currentBlockNumber) { - this.updateEventProgress(0, type) + await this.updateEventProgress(0, type) for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) { - const batch = await Promise.all( - this.createBatchRequest({ batchIndex, batchBlocks, blockDenom, batchSize, type }) - ) + const isLastBatch = batchIndex === batchCount - 1 + const params = new Array(batchSize).fill('').map((_, i) => { + const toBlock = (i + 1) * blockDenom + lastBlock + const fromBlock = toBlock - blockDenom + return { fromBlock, toBlock, type } + }) + const batch = await Promise.all(this.createBatchRequest(params)) - this.updateEventProgress(batchIndex / batchCount, type) - events = events.concat(batch) + lastBlock = params[batchSize - 1].toBlock + events = events.concat(batch.filter((e) => !e.isFailedBatch)) + failed = failed.concat(batch.filter((e) => e.isFailedBatch)) + + const progressIndex = batchIndex - failed.length / batchSize + + if (isLastBatch && failed.length !== 0) { + const fbatch = await Promise.all(this.createBatchRequest(failed)) + const isFailedBatch = fbatch.filter((e) => e.isFailedBatch).length !== 0 + + if (isFailedBatch) { + throw new Error('Failed to batch events') + } else { + events = events.concat(fbatch) + } + } + await this.updateEventProgress(progressIndex / batchCount, type) await sleep(200) } - events = flattenNArray(events) return { -- 2.45.2 From 11c87ff3193f4714e34c80e507ad1abf9765bbe6 Mon Sep 17 00:00:00 2001 From: gozzy Date: Sat, 3 Dec 2022 16:02:03 +0000 Subject: [PATCH 02/11] eth rpc custom configuration --- components/Settings.vue | 116 ++++++++++++++++++++++++++++++++++++++-- store/settings.js | 16 +++--- 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/components/Settings.vue b/components/Settings.vue index f39ecbd..476b5e9 100644 --- a/components/Settings.vue +++ b/components/Settings.vue @@ -47,6 +47,51 @@ {{ hasErrorRpc.msg }}

+
{{ $t('reset') }} @@ -75,9 +120,13 @@ export default { return { checkingRpc: false, hasErrorRpc: { type: '', msg: '' }, + hasErrorEthRpc: { type: '', msg: '' }, customRpcUrl: '', + customEthUrl: '', selectedRpc: 'custom', - rpc: { name: 'custom', url: '' } + selectedEthRpc: 'custom', + rpc: { name: 'custom', url: '' }, + ethRpc: { name: 'custom', url: '' } } }, computed: { @@ -85,9 +134,18 @@ export default { networkConfig() { return networkConfig[`netId${this.netId}`] }, + ethNetworkConfig() { + return networkConfig.netId1 + }, + isEthereumNetwork() { + return this.netId === 1 + }, isCustomRpc() { return this.selectedRpc === 'custom' }, + isCustomEthRpc() { + return this.selectedEthRpc === 'custom' + }, isDisabledSave() { return ( this.hasErrorRpc.type === 'is-warning' || this.checkingRpc || (this.isCustomRpc && !this.customRpcUrl) @@ -95,16 +153,24 @@ export default { } }, created() { + this.ethRpc = this.getRpc(1) this.rpc = this.getRpc(this.netId) this.selectedRpc = this.rpc.name + this.selectedEthRpc = this.ethRpc.name if (this.selectedRpc === 'custom') { this.$nextTick(() => { this.customRpcUrl = this.rpc.url }) } + if (this.selectedEthRpc === 'custom') { + this.$nextTick(() => { + this.customEthRpcUrl = this.ethRpc.url + }) + } this.checkRpc(this.rpc) + this.checkEthRpc(this.ethRpc) }, methods: { ...mapMutations('settings', ['SAVE_RPC']), @@ -113,25 +179,38 @@ export default { this.hasErrorRpc = { type: '', msg: '' } this.rpc = Object.entries(this.networkConfig.rpcUrls)[0][1] + this.ethRpc = Object.entries(this.ethNetworkConfig.rpcUrls)[0][1] this.selectedRpc = this.rpc.name + this.selectedEthRpc = this.ethRpc.name + this.checkEthRpc(this.ethRpc) this.checkRpc(this.rpc) }, onSave() { this.SAVE_RPC({ ...this.rpc, netId: this.netId }) + this.SAVE_RPC({ ...this.ethRpc, netId: 1 }) this.$emit('close') }, onCancel() { this.$emit('cancel') }, checkRpc({ name, url = '' }) { + this.checkingRpc = true + if (name === 'custom') { this.customRpcUrl = '' this.hasErrorRpc = { type: '', msg: '' } - this.checkingRpc = true + } + this._checkRpc({ name, url }) + }, + checkEthRpc({ name, url = '' }) { + this.checkingRpc = true + + if (name === 'custom') { + this.customEthRpcUrl = '' + this.hasErrorEthRpc = { type: '', msg: '' } return } - - this._checkRpc({ name, url }) + this._checkEthRpc({ name, url }) }, checkCustomRpc(url) { const trimmedUrl = url.trim() @@ -141,6 +220,14 @@ export default { } debounce(this._checkRpc, { name: 'custom', url: trimmedUrl }) }, + checkCustomEthRpc(url) { + const trimmedUrl = url.trim() + if (!trimmedUrl) { + this.hasErrorEthRpc = { type: '', msg: '' } + return + } + debounce(this._checkEthRpc, { name: 'custom', url: trimmedUrl }) + }, async _checkRpc({ name, url }) { this.checkingRpc = true this.hasErrorRpc = { type: '', msg: '' } @@ -159,6 +246,27 @@ export default { this.hasErrorRpc.msg = error } + this.checkingRpc = false + }, + async _checkEthRpc({ name, url }) { + this.checkingRpc = true + this.hasErrorEthRpc = { type: '', msg: '' } + + const { isValid, error } = await this.$store.dispatch('settings/checkRpc', { + url, + netId: 1, + isEthRpc: true + }) + + if (isValid) { + this.hasErrorEthRpc.type = 'is-primary' + this.hasErrorEthRpc.msg = this.$t('rpcStatusOk') + this.ethRpc = { name, url } + } else { + this.hasErrorEthRpc.type = 'is-warning' + this.hasErrorEthRpc.msg = error + } + this.checkingRpc = false } } diff --git a/store/settings.js b/store/settings.js index 94ebe80..4b6e7db 100644 --- a/store/settings.js +++ b/store/settings.js @@ -51,11 +51,14 @@ export const actions = { }, async checkCurrentRpc({ dispatch, getters, rootGetters }) { const netId = rootGetters['metamask/netId'] + if (netId !== 1) { + await dispatch('preselectRpc', { netId: 1, isEthRpc: true }) + } await dispatch('preselectRpc', { netId }) }, - async preselectRpc({ getters, commit, dispatch }, { netId }) { + async preselectRpc({ getters, commit, dispatch }, { netId, isEthRpc = false }) { const savedRpc = getters.getRpc(netId) - const { isValid } = await dispatch('checkRpc', { ...savedRpc, netId }) + const { isValid } = await dispatch('checkRpc', { ...savedRpc, netId, isEthRpc }) if (isValid) { return @@ -64,7 +67,7 @@ export const actions = { const { rpcUrls } = networkConfig[`netId${netId}`] for (const [, { name, url }] of Object.entries(rpcUrls)) { - const { isValid, error } = await dispatch('checkRpc', { url, netId }) + const { isValid, error } = await dispatch('checkRpc', { url, netId, isEthRpc }) if (isValid) { commit('SAVE_RPC', { netId, name, url }) return @@ -74,14 +77,13 @@ export const actions = { } throw new Error(this.app.i18n.t('rpcSelectError')) }, - async checkRpc(_, { url, netId }) { + async checkRpc(_, { url, netId, isEthRpc = false }) { try { const web3 = new Web3(url) - const chainId = await web3.eth.getChainId() - const isCurrent = Number(chainId) === Number(netId) - if (isCurrent) { + + if (isEthRpc || isCurrent) { return { isValid: true } } else { return { isValid: false, error: this.app.i18n.t('thisRpcIsForDifferentNetwork') } -- 2.45.2 From ea97a39aff1a79a5fbb497c7310ab23678d8668d Mon Sep 17 00:00:00 2001 From: gozzy Date: Sat, 3 Dec 2022 16:29:21 +0000 Subject: [PATCH 03/11] increase gas price timeout & update rpcs --- networkConfig.js | 48 ++++++++++++++++++++++++++++++++++++---------- store/gasPrices.js | 2 +- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/networkConfig.js b/networkConfig.js index 31973d8..e540bd2 100644 --- a/networkConfig.js +++ b/networkConfig.js @@ -19,7 +19,7 @@ export default { networkName: 'Ethereum Mainnet', deployedBlock: 9116966, rpcUrls: { - SecureRPC: { + secureRPC: { name: 'SecureRPC', url: 'https://api.securerpc.com/v1' } @@ -135,6 +135,10 @@ export default { multicall: '0x41263cba59eb80dc200f3e2544eda4ed6a90e76c', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { + oneRPC: { + name: '1RPC', + url: 'https://1rpc.io/bnb' + }, bscRpc: { name: 'BSC RPC', url: 'https://bscrpc.com/' @@ -182,9 +186,13 @@ export default { multicall: '0x11ce4B23bD875D7F5C6a31084f55fDe1e9A87507', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { - polygonRPC: { + polygonRpc: { name: 'Polygon RPC', - url: `https://polygon-rpc.com` + url: 'https://polygon-rpc.com/' + }, + oneRpc: { + name: '1RPC', + url: 'https://1rpc.io/matic/' } }, tokens: { @@ -230,9 +238,13 @@ export default { echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', ovmGasPriceOracleContract: '0x420000000000000000000000000000000000000F', rpcUrls: { + oneRpc: { + name: '1RPC', + url: 'https://1rpc.io/op/' + }, Optimism: { name: 'Optimism', - url: `https://mainnet.optimism.io` + url: 'https://mainnet.optimism.io/' } }, tokens: { @@ -278,8 +290,16 @@ export default { echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { Arbitrum: { + name: 'Arbitrum RPC', + url: 'https://arb1.arbitrum.io/rpc/' + }, + publicRpc: { + name: 'Arbitrum Public RPC', + url: 'https://arbitrum.public-rpc.com/' + }, + oneRpc: { name: '1RPC', - url: 'https://1rpc.io/arb' + url: 'https://1rpc.io/arb/' } }, tokens: { @@ -324,9 +344,9 @@ export default { multicall: '0xb5b692a88bdfc81ca69dcb1d924f59f0413a602a', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { - publicRpc: { - name: 'Community RPC', - url: 'https://development.tornadocash.community/rpc/v1' + communityResolver: { + name: 'Community RPC Resolver', + url: 'https://development.tornadocash.community/rpc/v1/' } }, tokens: { @@ -371,9 +391,17 @@ export default { multicall: '0xe86e3989c74293Acc962156cd3F525c07b6a1B6e', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { - publicRpc: { + publicRpc1: { name: 'Avalanche RPC', - url: 'https://api.avax.network/ext/bc/C/rpc' + url: 'https://api.avax.network/ext/bc/C/rpc/' + }, + publicRpc2: { + name: 'Avalanche Public PRC', + url: 'https://avalanche-evm.publicnode.com/' + }, + oneRpc: { + name: '1RPC', + ulr: 'https://1rpc.io/avax/' } }, tokens: { diff --git a/store/gasPrices.js b/store/gasPrices.js index 8145814..763cd23 100644 --- a/store/gasPrices.js +++ b/store/gasPrices.js @@ -76,7 +76,7 @@ export const actions = { } catch (e) { console.error('fetchGasPrice', e) } finally { - setTimeout(() => dispatch('fetchGasPrice'), 1000 * pollInterval) + setTimeout(() => dispatch('fetchGasPrice'), 2000 * pollInterval) } }, setDefault({ commit, rootGetters }) { -- 2.45.2 From 5aef9e6d069ee7a3a326cca6400504a9334d4f06 Mon Sep 17 00:00:00 2001 From: gozzy Date: Tue, 31 Jan 2023 19:35:39 +0000 Subject: [PATCH 04/11] fix: #11 --- components/Settings.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/Settings.vue b/components/Settings.vue index 476b5e9..a4a8889 100644 --- a/components/Settings.vue +++ b/components/Settings.vue @@ -187,7 +187,9 @@ export default { }, onSave() { this.SAVE_RPC({ ...this.rpc, netId: this.netId }) - this.SAVE_RPC({ ...this.ethRpc, netId: 1 }) + if (this.netId !== 1) { + this.SAVE_RPC({ ...this.ethRpc, netId: 1 }) + } this.$emit('close') }, onCancel() { -- 2.45.2 From aef16eda5fe44ecd43597db1a4ccb9c0621c4757 Mon Sep 17 00:00:00 2001 From: gozzy Date: Wed, 22 Mar 2023 10:03:27 +0000 Subject: [PATCH 05/11] factor for invalid proposal json --- store/governance/gov.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/store/governance/gov.js b/store/governance/gov.js index 933d6df..9d21618 100644 --- a/store/governance/gov.js +++ b/store/governance/gov.js @@ -688,6 +688,13 @@ const actions = { } } + if (text.includes(`'`)) { + text = text.replaceAll(`'`, `"`) + } + if (text.includes(`" "`)) { + text = text.replace(`" "`, `", "`) + } + let title, description, rest try { ;({ title, description } = JSON.parse(text)) -- 2.45.2 From 2b61afbafe9fc17af11a920428bb2da968e18f38 Mon Sep 17 00:00:00 2001 From: gozzy Date: Wed, 22 Mar 2023 20:50:13 +0000 Subject: [PATCH 06/11] improve rpc rate-limit conditions --- services/events.js | 6 +++--- services/registry/index.js | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/services/events.js b/services/events.js index 7fee968..b76880e 100644 --- a/services/events.js +++ b/services/events.js @@ -280,8 +280,8 @@ class EventService { } catch (e) { if (shouldRetry) { i = i + 1 - // maximum 10 second buffer for rate-limiting - await sleep(2000 * i) + // maximum 5 second buffer for rate-limiting + await sleep(1000 * i) events = await this.getEventsPartFromRpc( { @@ -317,6 +317,7 @@ class EventService { (e, i) => new Promise(async (resolve) => { try { + sleep(20 * i) const { events } = await this.getEventsPartFromRpc({ ...e }, true) resolve(events) } catch (e) { @@ -369,7 +370,6 @@ class EventService { } } await this.updateEventProgress(progressIndex / batchCount, type) - await sleep(200) } events = flattenNArray(events) diff --git a/services/registry/index.js b/services/registry/index.js index c20a744..9a372be 100644 --- a/services/registry/index.js +++ b/services/registry/index.js @@ -37,7 +37,7 @@ class RelayerRegister { resolve(registeredEventsPart) } catch (error) { if (shouldRetry) { - sleep(1000) + sleep(500) const events = this.fetchEvents({ fromBlock, toBlock }) @@ -61,8 +61,7 @@ class RelayerRegister { const promises = new Array(chunkCount).fill('').map( (_, i) => new Promise((resolve) => { - sleep(300) - + sleep(20 * i) const batch = this.fetchEvents( { fromBlock: i * blockDenom + fromBlock, -- 2.45.2 From 4ecde79c867ac5b549d705b14e7d9554fe4448b9 Mon Sep 17 00:00:00 2001 From: gozzy Date: Thu, 23 Mar 2023 03:03:21 +0000 Subject: [PATCH 07/11] proposeByDelegate support --- components/governance/ProposalsList.vue | 11 ++++++++--- store/governance/gov.js | 14 ++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/components/governance/ProposalsList.vue b/components/governance/ProposalsList.vue index 1cadbbb..5c02180 100644 --- a/components/governance/ProposalsList.vue +++ b/components/governance/ProposalsList.vue @@ -59,8 +59,13 @@ export default { } }, computed: { - ...mapState('governance/gov', ['lockedBalance', 'proposals']), - ...mapGetters('governance/gov', ['isFetchingProposals', 'constants', 'isFetchingBalances']), + ...mapState('governance/gov', ['proposals']), + ...mapGetters('governance/gov', [ + 'isFetchingProposals', + 'constants', + 'isFetchingBalances', + 'votingPower' + ]), ...mapGetters('token', ['toDecimals']), filteredProposals() { return this.proposals @@ -74,7 +79,7 @@ export default { }, hasProposalThreshold() { const PROPOSAL_THRESHOLD = toBN(this.constants.PROPOSAL_THRESHOLD) - return toBN(this.lockedBalance).gte(PROPOSAL_THRESHOLD) + return toBN(this.votingPower).gte(PROPOSAL_THRESHOLD) }, proposalThreshold() { return this.toDecimals(this.constants.PROPOSAL_THRESHOLD, 18) diff --git a/store/governance/gov.js b/store/governance/gov.js index 9d21618..8a06ce8 100644 --- a/store/governance/gov.js +++ b/store/governance/gov.js @@ -179,15 +179,21 @@ const actions = { ) { try { const { ethAccount } = rootState.metamask + const { lockedBalance, constants } = state const netId = rootGetters['metamask/netId'] + const proposalThreshold = toBN(constants.PROPOSAL_THRESHOLD) + const proposeIndependently = lockedBalance.gte(proposalThreshold) + const govInstance = getters.govContract({ netId }) const json = JSON.stringify({ title, description }) - const data = await govInstance.methods.propose(proposalAddress, json).encodeABI() + const fSelector = !proposeIndependently ? 'proposeByDelegate' : 'propose' + const data = await govInstance.methods[fSelector](proposalAddress, json).encodeABI() - const gas = await govInstance.methods - .propose(proposalAddress, json) - .estimateGas({ from: ethAccount, value: 0 }) + const gas = await govInstance.methods[fSelector](proposalAddress, json).estimateGas({ + from: ethAccount, + value: 0 + }) const callParams = { method: 'eth_sendTransaction', -- 2.45.2 From b492ef6e2056daf6e09be996cbed47774aaf6321 Mon Sep 17 00:00:00 2001 From: gozzy Date: Tue, 11 Apr 2023 19:47:02 +0000 Subject: [PATCH 08/11] increase relayer minimum stake balance --- services/registry/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registry/index.js b/services/registry/index.js index 9a372be..81cd84d 100644 --- a/services/registry/index.js +++ b/services/registry/index.js @@ -10,7 +10,7 @@ import { sleep, flattenNArray } from '@/utils' import AggregatorABI from '@/abis/Aggregator.abi.json' import RelayerRegistryABI from '@/abis/RelayerRegistry.abi.json' -const MIN_STAKE_BALANCE = '0x22B1C8C1227A00000' // 40 TORN +const MIN_STAKE_BALANCE = '0X1B1AE4D6E2EF500000' // 500 TORN const subdomains = Object.values(networkConfig).map(({ ensSubdomainKey }) => ensSubdomainKey) -- 2.45.2 From 322184baf800ced63c51b37159a9d8c6b07c1ac5 Mon Sep 17 00:00:00 2001 From: gozzy Date: Thu, 13 Apr 2023 00:35:17 +0000 Subject: [PATCH 09/11] update rpcs --- networkConfig.js | 50 ++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/networkConfig.js b/networkConfig.js index e540bd2..bdae9c5 100644 --- a/networkConfig.js +++ b/networkConfig.js @@ -139,9 +139,13 @@ export default { name: '1RPC', url: 'https://1rpc.io/bnb' }, - bscRpc: { - name: 'BSC RPC', - url: 'https://bscrpc.com/' + blockPi: { + name: 'BlockPi', + url: 'https://bsc.blockpi.network/v1/rpc/public' + }, + nodeReal: { + name: 'NodeReal', + url: 'https://bsc-mainnet.nodereal.io/v1/64a9df0874fb4a93b9d0a3849de012d3' } }, tokens: { @@ -188,11 +192,11 @@ export default { rpcUrls: { polygonRpc: { name: 'Polygon RPC', - url: 'https://polygon-rpc.com/' + url: 'https://polygon-rpc.com' }, oneRpc: { name: '1RPC', - url: 'https://1rpc.io/matic/' + url: 'https://1rpc.io/matic' } }, tokens: { @@ -238,13 +242,17 @@ export default { echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', ovmGasPriceOracleContract: '0x420000000000000000000000000000000000000F', rpcUrls: { + blockPi: { + name: 'BlockPi', + url: 'https://optimism.blockpi.network/v1/rpc/public' + }, oneRpc: { name: '1RPC', - url: 'https://1rpc.io/op/' + url: 'https://1rpc.io/op' }, Optimism: { name: 'Optimism', - url: 'https://mainnet.optimism.io/' + url: 'https://mainnet.optimism.io' } }, tokens: { @@ -289,17 +297,13 @@ export default { multicall: '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', rpcUrls: { + blockPi: { + name: 'BlockPi', + url: 'https://arbitrum.blockpi.network/v1/rpc/public' + }, Arbitrum: { name: 'Arbitrum RPC', - url: 'https://arb1.arbitrum.io/rpc/' - }, - publicRpc: { - name: 'Arbitrum Public RPC', - url: 'https://arbitrum.public-rpc.com/' - }, - oneRpc: { - name: '1RPC', - url: 'https://1rpc.io/arb/' + url: 'https://arb1.arbitrum.io/rpc' } }, tokens: { @@ -346,7 +350,11 @@ export default { rpcUrls: { communityResolver: { name: 'Community RPC Resolver', - url: 'https://development.tornadocash.community/rpc/v1/' + url: 'https://development.tornadocash.community/rpc/v1' + }, + blockPi: { + name: 'BlockPi', + url: 'https://gnosis.blockpi.network/v1/rpc/public' } }, tokens: { @@ -393,11 +401,15 @@ export default { rpcUrls: { publicRpc1: { name: 'Avalanche RPC', - url: 'https://api.avax.network/ext/bc/C/rpc/' + url: 'https://api.avax.network/ext/bc/C/rpc' + }, + blockPi: { + name: 'BlockPi', + url: 'https://avalanche.blockpi.network/v1/rpc/public' }, publicRpc2: { name: 'Avalanche Public PRC', - url: 'https://avalanche-evm.publicnode.com/' + url: 'https://avalanche-evm.publicnode.com' }, oneRpc: { name: '1RPC', -- 2.45.2 From eb59acd31961f5ef2c766919b99383500eb928aa Mon Sep 17 00:00:00 2001 From: gozzy Date: Sun, 16 Apr 2023 02:30:43 +0000 Subject: [PATCH 10/11] event promise chaining --- services/events.js | 124 ++++++++++++++++++------------------- services/registry/index.js | 95 ++++++++++++++++++---------- 2 files changed, 124 insertions(+), 95 deletions(-) diff --git a/services/events.js b/services/events.js index b76880e..2c0f9bf 100644 --- a/services/events.js +++ b/services/events.js @@ -80,7 +80,6 @@ class EventService { } return a.blockNumber - b.blockNumber }) - const lastBlock = allEvents[allEvents.length - 1].blockNumber this.saveEvents({ events: allEvents, lastBlock, type }) @@ -247,66 +246,61 @@ class EventService { } } - getPastEvents({ fromBlock, toBlock, type }) { + getPastEvents({ fromBlock, toBlock, type }, shouldRetry = false, i = 0) { return new Promise((resolve, reject) => { - const repsonse = this.contract.getPastEvents(capitalizeFirstLetter(type), { - fromBlock, - toBlock - }) + this.contract + .getPastEvents(capitalizeFirstLetter(type), { + fromBlock, + toBlock + }) + .then((events) => resolve(events)) + .catch((err) => { + i = i + 1 + // maximum 5 second buffer for rate-limiting + if (shouldRetry) { + const isRetry = i !== 5 - if (repsonse) { - resolve(repsonse) - } else { - reject(new Error()) - } + sleep(1000 * i).then(() => + this.getPastEvents({ fromBlock, toBlock, type }, isRetry, i) + .then((events) => resolve(events)) + .catch((_) => resolve(undefined)) + ) + } else { + reject(new Error(err)) + } + }) }) } - async getEventsPartFromRpc({ fromBlock, toBlock, type }, shouldRetry = false, i = 0) { + async getEventsPartFromRpc(parameters, shouldRetry = false) { try { + const { fromBlock, type } = parameters const { currentBlockNumber } = await this.getBlocksDiff({ fromBlock }) - if (fromBlock > currentBlockNumber) { - return { - events: [], - lastBlock: fromBlock - } - } + if (fromBlock < currentBlockNumber) { + const eventsPart = await this.getPastEvents(parameters, shouldRetry) - let events = [] - - try { - events = await this.getPastEvents({ fromBlock, toBlock, type }) - } catch (e) { - if (shouldRetry) { - i = i + 1 - // maximum 5 second buffer for rate-limiting - await sleep(1000 * i) - - events = await this.getEventsPartFromRpc( - { - fromBlock, - toBlock, - type - }, - i !== 5, - i - ) + if (eventsPart) { + if (eventsPart.length > 0) { + return { + events: formatEvents(eventsPart, type), + lastBlock: eventsPart[eventsPart.length - 1].blockNumber + } + } else { + return { + events: [], + lastBlock: fromBlock + } + } } else { - throw new Error(`Failed to fetch block ${toBlock}`) + return undefined } - } - - if (!events?.length) { + } else { return { events: [], lastBlock: fromBlock } } - return { - events: formatEvents(events, type), - lastBlock: events[events.length - 1].blockNumber - } } catch (err) { return undefined } @@ -315,15 +309,17 @@ class EventService { createBatchRequest(batchArray) { return batchArray.map( (e, i) => - new Promise(async (resolve) => { - try { - sleep(20 * i) - const { events } = await this.getEventsPartFromRpc({ ...e }, true) - resolve(events) - } catch (e) { - resolve({ isFailedBatch: true, ...e }) - } - }) + new Promise((resolve) => + sleep(20 * i).then(() => + this.getEventsPartFromRpc({ ...e }, true).then((batch) => { + if (!batch) { + resolve([{ isFailedBatch: true, ...e }]) + } else { + resolve(batch.events) + } + }) + ) + ) ) } @@ -352,33 +348,35 @@ class EventService { return { fromBlock, toBlock, type } }) const batch = await Promise.all(this.createBatchRequest(params)) + const requests = flattenNArray(batch) + events = events.concat(requests.filter((e) => !e.isFailedBatch)) + failed = failed.concat(requests.filter((e) => e.isFailedBatch)) lastBlock = params[batchSize - 1].toBlock - events = events.concat(batch.filter((e) => !e.isFailedBatch)) - failed = failed.concat(batch.filter((e) => e.isFailedBatch)) const progressIndex = batchIndex - failed.length / batchSize if (isLastBatch && failed.length !== 0) { - const fbatch = await Promise.all(this.createBatchRequest(failed)) - const isFailedBatch = fbatch.filter((e) => e.isFailedBatch).length !== 0 + const failedBatch = await Promise.all(this.createBatchRequest(failed)) + const failedReqs = flattenNArray(failedBatch) + const failedRept = failedReqs.filter((e) => e.isFailedBatch) - if (isFailedBatch) { - throw new Error('Failed to batch events') + if (failedRept.length === 0) { + events = events.concat(failedReqs) } else { - events = events.concat(fbatch) + throw new Error('Failed to batch events') } } await this.updateEventProgress(progressIndex / batchCount, type) } - events = flattenNArray(events) return { lastBlock: events[events.length - 1].blockNumber, events } + } else { + return undefined } - return undefined } catch (err) { return undefined } diff --git a/services/registry/index.js b/services/registry/index.js index 81cd84d..056224a 100644 --- a/services/registry/index.js +++ b/services/registry/index.js @@ -28,53 +28,83 @@ class RelayerRegister { fetchEvents = ({ fromBlock, toBlock }, shouldRetry = false) => { return new Promise((resolve, reject) => { if (fromBlock <= toBlock) { - try { - const registeredEventsPart = this.relayerRegistry.getPastEvents('RelayerRegistered', { - fromBlock, - toBlock + this.relayerRegistry + .getPastEvents('RelayerRegistered', { fromBlock, toBlock }) + .then((events) => resolve(events)) + .catch((_) => { + if (shouldRetry) { + sleep(500).then(() => + this.fetchEvents({ fromBlock, toBlock }) + .then((events) => resolve(events)) + .catch((_) => resolve(undefined)) + ) + } else { + resolve(undefined) + } }) - - resolve(registeredEventsPart) - } catch (error) { - if (shouldRetry) { - sleep(500) - - const events = this.fetchEvents({ fromBlock, toBlock }) - - resolve(events) - } else { - reject(new Error(error)) - } - } } else { - resolve([]) + resolve(undefined) } }) } batchFetchEvents = async ({ fromBlock, toBlock }) => { + const batchSize = 10 const blockRange = 10000 const blockDifference = toBlock - fromBlock const chunkCount = Math.ceil(blockDifference / blockRange) const blockDenom = Math.ceil(blockDifference / chunkCount) + const chunkSize = Math.ceil(chunkCount / batchSize) - const promises = new Array(chunkCount).fill('').map( - (_, i) => - new Promise((resolve) => { - sleep(20 * i) - const batch = this.fetchEvents( - { - fromBlock: i * blockDenom + fromBlock, - toBlock: (i + 1) * blockDenom + fromBlock - }, - true + let failed = [] + let events = [] + let lastBlock = fromBlock + + for (let batchIndex = 0; batchIndex < chunkSize; batchIndex++) { + const params = new Array(batchSize).fill('').map((_, i) => { + const toBlock = (i + 1) * blockDenom + lastBlock + const fromBlock = toBlock - blockDenom + return { fromBlock, toBlock } + }) + const promises = new Array(batchSize).fill('').map( + (_, i) => + new Promise((resolve) => + sleep(i * 20).then(() => { + this.fetchEvents(params[i], true).then((batch) => { + if (!batch) { + resolve([{ isFailedBatch: true, fromBlock, toBlock }]) + } else { + resolve(batch) + } + }) + }) ) - resolve(batch) + ) + const requests = flattenNArray(await Promise.all(promises)) + const failedIndexes = requests + .filter((e) => e.isFailedBatch) + .map((e) => { + const reqIndex = requests.indexOf(e) + return params[reqIndex] }) - ) - const batchEvents = flattenNArray(await Promise.all(promises)) - const events = batchEvents.map((e) => ({ ...e.returnValues })) + failed = failed.concat(failedIndexes || []) + events = events.concat(requests.filter((e) => !e.isFailedBatch)) + lastBlock = params[batchSize - 1].toBlock + } + + if (failed.length !== 0) { + const failedReqs = failed.map((e) => this.fetchEvents(e)) + const failedBatch = flattenNArray(await Promise.all(failedReqs)) + + events = events.concat(failedBatch || []) + } + + events = events.map((e) => ({ ...e.returnValues })) + + if (events.length === 0) { + throw new Error('Failed to fetch registry events') + } return events } @@ -169,6 +199,7 @@ class RelayerRegister { for (let x = 0; x < relayerEvents.length; x++) { const { ensName, relayerAddress } = relayerEvents[x] let ensAddress + if (!isAddress(relayerAddress)) { ensAddress = await this.getENSAddress(ensName) ensAddress = toChecksumAddress(ensAddress) -- 2.45.2 From a8c238c2afd3cf01f00ca72bb9f1d7e9806d62b5 Mon Sep 17 00:00:00 2001 From: gozzy Date: Sun, 16 Apr 2023 02:36:20 +0000 Subject: [PATCH 11/11] correct proposeByDelegate support --- store/governance/gov.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/store/governance/gov.js b/store/governance/gov.js index 8a06ce8..3d946de 100644 --- a/store/governance/gov.js +++ b/store/governance/gov.js @@ -179,21 +179,35 @@ const actions = { ) { try { const { ethAccount } = rootState.metamask - const { lockedBalance, constants } = state + const { lockedBalance, constants, delegators } = state const netId = rootGetters['metamask/netId'] const proposalThreshold = toBN(constants.PROPOSAL_THRESHOLD) - const proposeIndependently = lockedBalance.gte(proposalThreshold) + const proposeIndependently = toBN(lockedBalance).gte(proposalThreshold) const govInstance = getters.govContract({ netId }) const json = JSON.stringify({ title, description }) - const fSelector = !proposeIndependently ? 'proposeByDelegate' : 'propose' - const data = await govInstance.methods[fSelector](proposalAddress, json).encodeABI() + const delegatorAddress = delegators[delegators.length - 1] - const gas = await govInstance.methods[fSelector](proposalAddress, json).estimateGas({ - from: ethAccount, - value: 0 - }) + let data, gas + + if (proposeIndependently) { + data = await govInstance.methods.propose(proposalAddress, json).encodeABI() + gas = await govInstance.methods.propose(proposalAddress, json).estimateGas({ + from: ethAccount, + value: 0 + }) + } else { + data = await govInstance.methods + .proposeByDelegate(delegatorAddress, proposalAddress, json) + .encodeABI() + gas = await govInstance.methods + .proposeByDelegate(delegatorAddress, proposalAddress, json) + .estimateGas({ + from: ethAccount, + value: 0 + }) + } const callParams = { method: 'eth_sendTransaction', -- 2.45.2