Skip to content

Commit

Permalink
new endpoint to check that a address is registered as a holder for a …
Browse files Browse the repository at this point in the history
…token, some comments and typos
  • Loading branch information
lucasmenendez committed Sep 27, 2023
1 parent fb0612c commit 4524f90
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 15 deletions.
4 changes: 2 additions & 2 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ Returns the information of the snapshots related to the provided ID.
| 500 | `error getting census information` | 5009 |
| 500 | `error encoding census` | 5017 |

### GET `/census/queue/{queueID}`
### GET `/censuses/queue/{queueID}`
Returns the information of the census that are in the creation queue.

- 📥 response:
Expand Down Expand Up @@ -549,7 +549,7 @@ Returns the information of the census that are in the creation queue.
| 500 | `error creating the census tree on the census database` | 5001 |
| 500 | `error evaluating strategy predicate` | 5026 |

### GET `/census/strategy/{strategyID}`
### GET `/censuses/strategy/{strategyID}`
Returns a list of censusID for the strategy provided.

- 📥 response:
Expand Down
5 changes: 5 additions & 0 deletions api/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ var (
HTTPstatus: apirest.HTTPstatusNoContent,
Err: fmt.Errorf("strategy has not registered holders"),
}
ErrMalformedChainID = apirest.APIerror{
Code: 4018,
HTTPstatus: apirest.HTTPstatusBadRequest,
Err: fmt.Errorf("malformed chain ID"),
}
ErrCantCreateToken = apirest.APIerror{
Code: 5000,
HTTPstatus: apirest.HTTPstatusInternalErr,
Expand Down
19 changes: 19 additions & 0 deletions api/strategyoperators/combinators.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package strategyoperators

import "math/big"

// normalize returns the two balances with the same number of decimals. It also
// returns the number of decimals used to normalize these numbers. To choose the
// correct number of decimals, the function chooses the highest number of
// decimals between the two provided values.
func normalize(a, b *big.Int, aDecimals, bDecimals uint64) (*big.Int, *big.Int, uint64) {
if aDecimals > bDecimals {
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(aDecimals-bDecimals)), nil)
Expand All @@ -11,11 +15,17 @@ func normalize(a, b *big.Int, aDecimals, bDecimals uint64) (*big.Int, *big.Int,
return new(big.Int).Mul(a, exp), b, bDecimals
}

// reduceNormalized returns the balance provided reducing the number of decimals
// of it by the number of decimals provided. It allows to fix the normalization
// of a balance after operations like multiplication or division.
func reduceNormalized(a *big.Int, aDecimals uint64) *big.Int {
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(aDecimals)), nil)
return new(big.Int).Div(a, exp)
}

// sumBalancesCombinator returns the sum of the balances provided for each
// address in the provided map. It returns a new map with the same keys and the
// result of the sum of the balances.
func sumBalancesCombinator(balances map[string][2]*big.Int) map[string]*big.Int {
res := make(map[string]*big.Int)
for address, balances := range balances {
Expand All @@ -24,6 +34,12 @@ func sumBalancesCombinator(balances map[string][2]*big.Int) map[string]*big.Int
return res
}

// mulBalancesCombinator returns the multiplication of the balances provided for
// each address in the provided map. If the forceNotZero flag is set to true,
// and any of the balances is zero, the address is not included in the result.
// Else if forceNotZero is set to false, and any of the balances is zero, the
// other one will be assigned to the address. The resulting balances are reduced
// by the number of decimals provided using the reduceNormalized function.
func mulBalancesCombinator(balances map[string][2]*big.Int, decimals uint64, forceNotZero bool) map[string]*big.Int {
res := make(map[string]*big.Int)
for address, balances := range balances {
Expand Down Expand Up @@ -51,6 +67,9 @@ func mulBalancesCombinator(balances map[string][2]*big.Int, decimals uint64, for
return res
}

// membershipCombinator returns a map with the same keys as the provided map,
// and the value of each key is 1, discarding the value of the balances of the
// provided map.
func membershipCombinator(balances map[string][2]*big.Int) map[string]*big.Int {
res := make(map[string]*big.Int)
for address := range balances {
Expand Down
30 changes: 18 additions & 12 deletions api/strategyoperators/strategyoperators.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,34 @@ var ValidOperatorsTags = []string{
// ValidOperators variable contains the information of the supported operators
var ValidOperators = []map[string]string{
{
"tag": ANDTag,
"description": "logical operator that returns the common token holders between symbols with fixed balance to 1",
"tag": ANDTag,
"description": "logical operator that returns the common token " +
"holders between symbols with fixed balance to 1",
},
{
"tag": ANDSUMTag,
"description": "logical operator that returns the common token holders between symbols with the sum of their balances on both tokens",
"tag": ANDSUMTag,
"description": "logical operator that returns the common token holders " +
"between symbols with the sum of their balances on both tokens",
},
{
"tag": ANDMULTag,
"description": "logical operator that returns the common token holders between symbols with the multiplication of their balances on both tokens",
"tag": ANDMULTag,
"description": "logical operator that returns the common token holders " +
"between symbols with the multiplication of their balances on both tokens",
},
{
"tag": ORTag,
"description": "logical operator that returns the token holders of both symbols with fixed balance to 1",
"tag": ORTag,
"description": "logical operator that returns the token holders of " +
"both symbols with fixed balance to 1",
},
{
"tag": ORSUMTag,
"description": "logical operator that returns the token holders of both symbols with the sum of their balances on both tokens",
"tag": ORSUMTag,
"description": "logical operator that returns the token holders of " +
"both symbols with the sum of their balances on both tokens",
},
{
"tag": ORMULTag,
"description": "logical operator that returns the token holders of both symbols with the multiplication of their balances on both tokens",
"tag": ORMULTag,
"description": "logical operator that returns the token holders of " +
"both symbols with the multiplication of their balances on both tokens",
},
}

Expand Down
26 changes: 26 additions & 0 deletions api/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"math/big"
"strconv"
"strings"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -31,6 +32,10 @@ func (capi *census3API) initTokenHandlers() error {
api.MethodAccessTypePublic, capi.getToken); err != nil {
return err
}
if err := capi.endpoint.RegisterMethod("/tokens/{tokenID}/{chainID}/holders/{holderID}", "GET",
api.MethodAccessTypePublic, capi.isTokenHolder); err != nil {
return err
}
return capi.endpoint.RegisterMethod("/tokens/types", "GET",
api.MethodAccessTypePublic, capi.getTokenTypes)
}
Expand Down Expand Up @@ -271,6 +276,27 @@ func (capi *census3API) getToken(msg *api.APIdata, ctx *httprouter.HTTPContext)
return ctx.Send(res, api.HTTPstatusOK)
}

func (capi *census3API) isTokenHolder(msg *api.APIdata, ctx *httprouter.HTTPContext) error {
address := common.HexToAddress(ctx.URLParam("tokenID"))
holderID := common.HexToAddress(ctx.URLParam("holderID"))
chainID, err := strconv.Atoi(ctx.URLParam("chainID"))
if err != nil {
return ErrMalformedChainID.WithErr(err)
}
internalCtx, cancel := context.WithTimeout(context.Background(), getTokenTimeout)
defer cancel()

exists, err := capi.db.QueriesRO.ExistTokenHolder(internalCtx, queries.ExistTokenHolderParams{
TokenID: address.Bytes(),
HolderID: holderID.Bytes(),
ChainID: uint64(chainID),
})
if err != nil {
return ErrCantGetTokenHolders.WithErr(err)
}
return ctx.Send([]byte(strconv.FormatBool(exists)), api.HTTPstatusOK)
}

// getTokenTypes handler returns the list of string names of the currently
// supported types of token contracts.
func (capi *census3API) getTokenTypes(msg *api.APIdata, ctx *httprouter.HTTPContext) error {
Expand Down
2 changes: 1 addition & 1 deletion census/census.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func censusDBKey(censusID uint64) string {
// represented as 1 for true and 0 for false. This concatenated string is then converted
// to a uint64 to create a unique identifier.
func InnerCensusID(blockNumber, strategyID uint64, anonymous bool) uint64 {
// Convert the boolean to a uint32: 1 for true, 0 for false
// Convert the boolean to a uint64: 1 for true, 0 for false
var anonymousUint uint64
if anonymous {
anonymousUint = 1
Expand Down
9 changes: 9 additions & 0 deletions db/queries/holders.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ WHERE token_holders.token_id = ?
AND token_holders.chain_id = ?
AND token_holders.holder_id = ?;

-- name: ExistTokenHolder :one
SELECT EXISTS (
SELECT holder_id
FROM token_holders
WHERE token_id = ?
AND holder_id = ?
AND chain_id = ?
);

-- name: LastBlockByTokenID :one
SELECT block_id
FROM token_holders
Expand Down
23 changes: 23 additions & 0 deletions db/sqlc/holders.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4524f90

Please sign in to comment.