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

Voting: use BN.js everywhere #1113

Closed
wants to merge 1,226 commits into from

Conversation

rperez89
Copy link
Contributor

@rperez89 rperez89 commented Apr 8, 2020

This pr closes aragon/client#1347

sohkai and others added 30 commits April 16, 2019 09:47
* Payroll: Fix accrued salary calculation

* Payroll: Improve casting when calculating last payroll date
* Copy improvements

* More specific copy

* Reverting controversial change
* Change confusing token manager copy
* voting: fetch active account votes in script

* Move connectedAccount out of the store and cache

* Add comment about using strings over symbols

* Move functions to helpers

* Update comments

Co-Authored-By: 2color <[email protected]>

* Add newline
Improve the filters layout:

- Move TransfersFilters to its own component.
- Make the layout work at all sizes.
- Update the download button so it looks like the other icon buttons.
- Update some labels:
  - “Date range” => “Period”
  - “Transfer type” => “Type” (since it is already below the “Transfers” title).
- Select the last 90 days (rolling) by default.
* Voting: fix bug with votes not loading initially

* Add comment
Fixes aragon/client#734.

With aragon/aragon.js#277 we now get the actual errors back from the RPC when a call goes wrong (e.g. naive `token.symbol()` on DAI) and we need to handle these explicitly.

This PR converts a lot of the token fallback-related bits into simpler Promise-based code and adds explicit handlers for their error cases.
@bpierre bpierre force-pushed the voting-token-amount-fix branch from 9a6d907 to 7c2fdc1 Compare June 11, 2020 19:58
@bpierre
Copy link
Contributor

bpierre commented Jun 11, 2020

I added some changes to remove the Number-based calculations from the app, and rely on formatTokenAmount() to format amounts.

Changes:

  • Add a new TokenAmount class.
  • Add a new Percentage class.
  • Add bnPercentageToNumber().
  • Add formatBnPercentage().
  • Format amounts / percentages from the TokenAmount / Percentage classes.
  • Convert the calculations to BN.js.
  • Remove numData from the vote data structure.

@bpierre bpierre requested review from sohkai and removed request for bpierre June 11, 2020 20:01
@bpierre bpierre changed the title Voting: Wrong token amount used to vote Voting: use BN.js everywhere Jun 12, 2020
@sohkai sohkai requested review from delfipolito and removed request for Evalir June 16, 2020 09:40
Copy link
Contributor

@Evalir Evalir left a comment

Choose a reason for hiding this comment

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

Very very minor nitpicks! This is looking awesome!

@@ -1,17 +1,16 @@
import React from 'react'
import styled from 'styled-components'
import { GU, textStyle, useTheme } from '@aragon/ui'
import { GU, textStyle, formatTokenAmount, useTheme } from '@aragon/ui'
Copy link
Contributor

Choose a reason for hiding this comment

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

We can move this behind textStyle so it's alphabetized 🙏

@@ -1,5 +1,6 @@
import BN from 'bn.js'
import { hasLoadedVoteSettings } from './vote-settings'
import { Percentage, TokenAmount } from './math-utils'
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, we don't have to do it now, but I think we could use our newly released TokenAmount lib!

Comment on lines 3 to 4
import { formatTokenAmount } from '@aragon/ui'
import { useAragonApi } from '@aragon/api-react'
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that I'm seeing the order, shouldn't we move @aragon/ui below @aragon/api-react?


const totalVotes = yea.add(nay)
const totalVotes = yea.value().add(nay.value())
Copy link
Contributor

Choose a reason for hiding this comment

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

Just realized this probably could equal -2 if both yea and nay get passed in as -1, but, AFAIK, this can't really happen as they're not being set at -1 at any moment.

) {
if (!tokenContract || !connectedAccount) {
return -1
export async function getUserBalanceAt(account, snapshotBlock, tokenContract) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should also make these return BN objects (or null), so all the number-related APIs use BN.js?

}

// Converts a percentage expressed as a value + base into a number between 0 and 1.
export function bnPercentageToNumber(value, base, precision = 10 ** 9) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a bit worried with the precision being too big—wonder if we should use something like maxDecimalPrecision instead (just the number of decimals)?

@@ -16,6 +17,7 @@ function appStateReducer(state) {
connectedAccountVotes,
} = state

const pctBaseBn = new BN(pctBase)
const pctBaseNum = parseInt(pctBase, 10)
Copy link
Contributor

Choose a reason for hiding this comment

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

We can probably remove this now?

supportRequired: new Percentage(data.supportRequired, pctBaseBn),
votingPower: new TokenAmount(data.votingPower, tokenDecimals),
yea: new TokenAmount(data.yea, tokenDecimals),
nay: new TokenAmount(data.nay, tokenDecimals),
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about also including the token symbol in the TokenAmount?

import You from './You'
import { formatNumber } from '../math-utils'
import { VOTE_NAY, VOTE_YEA } from '../vote-types'

function SummaryRows({ yea, nay, symbol, connectedAccountVote }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wanted to double check—what type is yea and nay? We're accessing yea.pct but I'm not sure this exists on the object anymore.


return (
parseInt(
divideRoundBigInt(
Copy link
Contributor

Choose a reason for hiding this comment

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

It's starting to look like we may want another utility :).

Maybe divideBN() and we can give it a decimalsPrecision option?


// Tolerate having too many digits by correcting the value.
if (basePrecision > Number.MAX_SAFE_INTEGER) {
digits = Math.floor(Math.log(Number.MAX_SAFE_INTEGER) / Math.log(10))
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure about this:

  1. I think we should make this max precision value be a constant
  2. This value is actually only 15, and and I think we should at least support 18 decimals (since that's what tokens use, as well as our contract's pctBase exponent).

It's unlikely someone will want something this large, but I'm also wondering if we shouldn't just cap the precision at the pctBase's exponent (since it'll just be 0s after that anyway).

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should make this max precision value be a constant

Why? This is already on the Javascript Number object, and so having this as a constant seems a bit redundant to me.

This value is actually only 15, and and I think we should at least support 18 decimals (since that's what tokens use, as well as our contract's pctBase exponent).

This is true, and relates to #1177 in terms of having an utility to safely scale up normal numbers to Bigints.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why? This is already on the Javascript Number object, and so having this as a constant seems a bit redundant to me.

Because Math.floor(Math.log(Number.MAX_SAFE_INTEGER) / Math.log(10)) is pure and doesn't need to be calculated every time

@eliobricenov
Copy link

hey, I continued the last changes you requested here https://github.com/eliobricenov/aragon-apps/commits/voting-token-amount-fix-v2

Should I create a new PR with these changes?

C.C @nivida

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Voting: amount of tokens shown that I voted with does not match real holdings