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

Executive supporters batch requests + mobile delegate names #807

Merged
merged 4 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
12 changes: 9 additions & 3 deletions modules/address/components/AddressIconBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,15 @@ export default function AddressIconBox({
<Flex sx={{ flexDirection: ['column', 'row'] }}>
<Flex sx={{ alignItems: 'center' }}>
{delegate ? (
<Text>
{limitTextLength ? limitString(delegate.name, limitTextLength, '...') : delegate.name}
</Text>
limitTextLength ? (
<Flex sx={{ flexDirection: 'column' }}>
{delegate.name.split(' - ').map((name, i) => (
<Text key={delegate.name + '-' + i}>{limitString(name, limitTextLength, '...')}</Text>
))}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is fine as is, but a small suggestion is that this display logic of splitting the delegate name could be refactored into a little helper function that would A) add a little context to what it's doing (based on the function name, or a comment) for future maintainers and B) make it reusable if it was necessary somewhere else

</Flex>
) : (
<Text>{delegate.name}</Text>
)
) : (
<Text>
<Address address={address} maxLength={limitTextLength} />
Expand Down
68 changes: 44 additions & 24 deletions modules/executive/api/fetchExecutiveVoteTally.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import { getChiefDeposits } from 'modules/web3/api/getChiefDeposits';
import { getSlateAddresses } from '../helpers/getSlateAddresses';
import { formatValue } from 'lib/string';
import { paddedBytes32ToAddress } from 'lib/utils';
import { BigNumber } from 'ethers';

type AddressWithVotes = {
votes: string[];
slate: string;
address: string;
deposits: BigNumber;
};

export async function fetchExecutiveVoteTally(chief: Chief): Promise<any | null> {
const filter = {
Expand All @@ -32,36 +40,48 @@ export async function fetchExecutiveVoteTally(chief: Chief): Promise<any | null>
}
});

const withDeposits = await Promise.all(
voters.map(voter =>
getChiefDeposits(voter, chief).then(deposits => ({
address: voter,
deposits
}))
)
// Split voters array into chunks of 1000 addresses
const chunkSize = 1000;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also be helpful for future maintainers to leave a short comment about it being set to 1000 due the batch request limits

const voterChunks = Array.from({ length: Math.ceil(voters.length / chunkSize) }, (_, i) =>
voters.slice(i * chunkSize, i * chunkSize + chunkSize)
);
Comment on lines +45 to 48

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, one thing I'm curious about though is how the JsonRpcBatchProvider handles batching on it's end. From what I understand, the provider just continuously adds batched requests to it's internal cache and executes them with a 10ms delay.

If that's the case I wonder how the chunking here is actually working. But maybe it's because each loop of our chunk creates a new pendingBatch in the provider as seen here.

In any case it does seem to be working, so that's great


const withSlates = await Promise.all(
withDeposits.map(addressDeposit =>
chief.votes(addressDeposit.address).then(slate => ({
...addressDeposit,
slate
}))
)
);
const addressesWithVotes: AddressWithVotes[] = [];

const withVotes = await Promise.all(
withSlates.map(withSlate =>
getSlateAddresses(chief, withSlate.slate).then(addresses => ({
...withSlate,
votes: addresses
}))
)
);
for (const chunk of voterChunks) {
const withDeposits = await Promise.all(
chunk.map(voter =>
getChiefDeposits(voter, chief).then(deposits => ({
address: voter,
deposits
}))
)
);

const withSlates = await Promise.all(
withDeposits.map(addressDeposit =>
chief.votes(addressDeposit.address).then(slate => ({
...addressDeposit,
slate
}))
)
);

const withVotes = await Promise.all(
withSlates.map(withSlate =>
getSlateAddresses(chief, withSlate.slate).then(addresses => ({
...withSlate,
votes: addresses
}))
)
);

addressesWithVotes.push(...withVotes);
}

const voteTally = {};

for (const voteObj of withVotes) {
for (const voteObj of addressesWithVotes) {
for (let vote of voteObj.votes) {
vote = vote.toLowerCase();
if (voteTally[vote] === undefined) {
Expand Down