Skip to content

Commit

Permalink
Merge pull request #828 from oasisprotocol/ptrus/feature/evm-tokens-s…
Browse files Browse the repository at this point in the history
…orting

server/runtimes: EVM tokens sorting param
  • Loading branch information
ptrus authored Dec 18, 2024
2 parents 00eae0f + c711d6a commit 708476e
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 29 deletions.
4 changes: 4 additions & 0 deletions .changelog/828.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add `sort_by` parameter to `/{runtime}/evm_tokens` endpoint.

The parameter can be used to configure if results should be sorted by number
of total holders, or by the calculated market cap.
8 changes: 8 additions & 0 deletions api/spec/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,14 @@ paths:
schema:
type: string
description: A filter on the name, the name or symbol must contain this value as a substring.
- in: query
name: sort_by
schema:
type: string
enum: [total_holders, market_cap]
description: |
The field to sort the tokens by.
If unset, the tokens will be sorted by number of holders.
responses:
'200':
description: The requested tokens.
Expand Down
1 change: 1 addition & 0 deletions storage/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,7 @@ func (c *StorageClient) RuntimeTokens(ctx context.Context, p apiTypes.GetRuntime
p.Name,
refSwapFactoryAddr,
refSwapTokenAddr,
p.SortBy,
p.Limit,
p.Offset,
)
Expand Down
61 changes: 32 additions & 29 deletions storage/client/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,37 +704,40 @@ const (
tokens.token_type IS NOT NULL AND -- exclude token _candidates_ that we haven't inspected yet
tokens.token_type != 0 -- exclude unknown-type tokens; they're often just contracts that emitted Transfer events but don't expose the token ticker, name, balance etc.
ORDER BY
(
CASE
-- For the reference token itself, it is 1:1 in value with, you know, itself.
WHEN
tokens.token_address = $5
THEN 1.0
-- The pool keeps a proportion of reserves so that reserve0 of token0 is worth about as much as reserve1 of token1.
-- When token0 is the reference token, more reserve0 means token1 is worth more than the reference token.
WHEN
ref_swap_pair_creations.token0_address = $5 AND
ref_swap_pairs.reserve0 IS NOT NULL AND
ref_swap_pairs.reserve0 > 0 AND
ref_swap_pairs.reserve1 IS NOT NULL AND
ref_swap_pairs.reserve1 > 0
THEN ref_swap_pairs.reserve0::REAL / ref_swap_pairs.reserve1::REAL
-- When token1 is the reference token, more reserve1 means token0 is worth more than the reference token.
WHEN
ref_swap_pair_creations.token1_address = $5 AND
ref_swap_pairs.reserve0 IS NOT NULL AND
ref_swap_pairs.reserve0 > 0 AND
ref_swap_pairs.reserve1 IS NOT NULL AND
ref_swap_pairs.reserve1 > 0
THEN ref_swap_pairs.reserve1::REAL / ref_swap_pairs.reserve0::REAL
ELSE 0.0
END *
COALESCE(tokens.total_supply, 0)
) DESC,
CASE
-- If sort_by is not "market_cap" then we sort by num_holders (below).
WHEN $6::text IS NULL OR $6::text != 'market_cap' THEN NULL
ELSE
-- Otherwise, sort by market cap.
(
CASE
-- For the reference token itself, it is 1:1 in value with, you know, itself.
WHEN tokens.token_address = $5 THEN 1.0
-- The pool keeps a proportion of reserves so that reserve0 of token0 is worth about as much as reserve1 of token1.
-- When token0 is the reference token, more reserve0 means token1 is worth more than the reference token.
WHEN
ref_swap_pair_creations.token0_address = $5 AND
ref_swap_pairs.reserve0 IS NOT NULL AND
ref_swap_pairs.reserve0 > 0 AND
ref_swap_pairs.reserve1 IS NOT NULL AND
ref_swap_pairs.reserve1 > 0
THEN ref_swap_pairs.reserve0::REAL / ref_swap_pairs.reserve1::REAL
-- When token1 is the reference token, more reserve1 means token0 is worth more than the reference token.
WHEN
ref_swap_pair_creations.token1_address = $5 AND
ref_swap_pairs.reserve0 IS NOT NULL AND
ref_swap_pairs.reserve0 > 0 AND
ref_swap_pairs.reserve1 IS NOT NULL AND
ref_swap_pairs.reserve1 > 0
THEN ref_swap_pairs.reserve1::REAL / ref_swap_pairs.reserve0::REAL
ELSE 0.0
END * COALESCE(tokens.total_supply, 0)
)
END DESC,
num_holders DESC,
contract_addr
LIMIT $6::bigint
OFFSET $7::bigint`
LIMIT $7::bigint
OFFSET $8::bigint`

//nolint:gosec // Linter suspects a hardcoded credentials token.
EvmTokenHolders = `
Expand Down
1 change: 1 addition & 0 deletions tests/e2e_regression/common_test_cases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ commonTestCases=(
'emerald_events /v1/emerald/events'
'emerald_events_by_type /v1/emerald/events?type=accounts.transfer'
'emerald_tokens /v1/emerald/evm_tokens'
'emerald_tokens_sort_market_cap /v1/emerald/evm_tokens?sort_by=market_cap'
'emerald_status /v1/emerald/status'
'emerald_tx_volume /v1/emerald/stats/tx_volume'
'emerald_contract_account /v1/emerald/accounts/oasis1qz2rynvcmrkwd57v00298uc2vtzgatde3cjpy72f'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"evm_tokens": [],
"is_total_count_clipped": false,
"total_count": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: UNINTERESTING
Content-Length: UNINTERESTING

167 changes: 167 additions & 0 deletions tests/e2e_regression/eden/expected/emerald_tokens_sort_market_cap.body
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
{
"evm_tokens": [
{
"contract_addr": "oasis1qqz8706pmf38wmptl6dkcaec8yykw0rvfv7ql6fc",
"decimals": 18,
"eth_contract_addr": "0xf02b3e437304892105992512539F769423a515Cb",
"is_verified": true,
"name": "YUZUToken",
"num_holders": 15,
"num_transfers": 108,
"symbol": "YUZU",
"total_supply": "324996573618707482993195360",
"type": "ERC20",
"verification_level": "partial"
},
{
"contract_addr": "oasis1qpgcp5jzlgk4hcenaj2x82rqk8rrve2keyuc8aaf",
"decimals": 18,
"eth_contract_addr": "0x21C718C22D52d0F3a789b752D4c2fD5908a8A733",
"is_verified": true,
"name": "Wrapped ROSE",
"num_holders": 14,
"num_transfers": 48,
"symbol": "wROSE",
"total_supply": "11110528749907675559457292",
"type": "ERC20",
"verification_level": "partial"
},
{
"contract_addr": "oasis1qp2hssandc7dekjdr6ygmtzt783k3gn38uupdeys",
"decimals": 6,
"eth_contract_addr": "0xdC19A122e268128B5eE20366299fc7b5b199C8e3",
"is_verified": false,
"name": "Tether USD",
"num_holders": 9,
"num_transfers": 33,
"symbol": "USDT",
"total_supply": "690015441212",
"type": "ERC20"
},
{
"contract_addr": "oasis1qzj2hwfs3yjm20jz5h70yk3etsst0k8s3cnl6l08",
"decimals": 18,
"eth_contract_addr": "0x941494A56164eA04d79f9867ddDB0Dd754A625cC",
"is_verified": true,
"name": "YuzuSwap LP Token",
"num_holders": 4,
"num_transfers": 2,
"symbol": "LPT",
"total_supply": "5515821744343857173275622",
"type": "ERC20",
"verification_level": "partial"
},
{
"contract_addr": "oasis1qpuqs65me58n6mt05ezd7cnttx7k57w28v36l4ca",
"decimals": 6,
"eth_contract_addr": "0x81ECac0D6Be0550A00FF064a4f9dd2400585FE9c",
"is_verified": false,
"name": "USD Coin (Celer)",
"num_holders": 3,
"num_transfers": 6,
"symbol": "ceUSDC",
"total_supply": "160671058631",
"type": "ERC20"
},
{
"contract_addr": "oasis1qqehgt8jfnczmku5hazxkkprw5nqqk4nvunx9zf4",
"decimals": 18,
"eth_contract_addr": "0x28c9D3e689B5d3629aFC2D69ef6a2799578574e0",
"is_verified": true,
"name": "YuzuSwap LP Token",
"num_holders": 2,
"num_transfers": 1,
"symbol": "LPT",
"total_supply": "8543198732792740426556",
"type": "ERC20",
"verification_level": "partial"
},
{
"contract_addr": "oasis1qzel2watfs6g3cm765dwlukymjs5k3rnhvua4z78",
"decimals": 18,
"eth_contract_addr": "0x3223f17957Ba502cbe71401D55A0DB26E5F7c68F",
"is_verified": false,
"name": "Wrapped Ether",
"num_holders": 2,
"num_transfers": 2,
"symbol": "WETH",
"total_supply": "153212215450000000000",
"type": "ERC20"
},
{
"contract_addr": "oasis1qpgvjkelzwd0yucjqyfpfzalrp3x74se7y922a7s",
"decimals": 18,
"eth_contract_addr": "0x485E6D145E958347EFDe7A43538879DCcD868f40",
"is_verified": false,
"name": "YuzuParkExtDummyToken",
"num_holders": 1,
"num_transfers": 2,
"symbol": "YPEDT",
"total_supply": "10000",
"type": "ERC20"
},
{
"contract_addr": "oasis1qqjv74rz8e6v9q6yn7y76zvf0yv5299ejsaxnjqu",
"decimals": 18,
"eth_contract_addr": "0xf5493ea940d12cE8594f81BaB2bB7d4ed81d49e8",
"is_verified": false,
"name": "xYUZU",
"num_holders": 1,
"num_transfers": 1,
"symbol": "xYUZU",
"total_supply": "72707317251766251839614070",
"type": "ERC20"
},
{
"contract_addr": "oasis1qrsl7tgujttvscfe2k268s7q2s7kdu9tyv9qv2tx",
"decimals": 8,
"eth_contract_addr": "0x5D9ab5522c64E1F6ef5e3627ECCc093f56167818",
"is_verified": false,
"name": "Wrapped BTC",
"num_holders": 1,
"num_transfers": 2,
"symbol": "WBTC",
"total_supply": "175579512",
"type": "ERC20"
},
{
"contract_addr": "oasis1qz29t7nxkwfqgfk36uqqs9pzuzdt8zmrjud5mehx",
"decimals": 0,
"eth_contract_addr": "0x1108A83b867c8b720fEa7261AE7A64DAB17B4159",
"is_verified": false,
"name": "MyNFT",
"num_holders": 1,
"num_transfers": 2,
"symbol": "MNFT",
"total_supply": "2",
"type": "ERC721"
},
{
"contract_addr": "oasis1qzpxtzc3xphccjq94wxffchfc5sua5t24vc6gvt6",
"decimals": 18,
"eth_contract_addr": "0x5C78A65AD6D0eC6618788b6E8e211F31729111Ca",
"is_verified": true,
"name": "Wrapped ROSE",
"num_holders": 1,
"num_transfers": 1,
"symbol": "WROSE",
"total_supply": "370854109276538025377920",
"type": "ERC20",
"verification_level": "partial"
},
{
"contract_addr": "oasis1qzxx6htc6cceayd492mqt6lqc8l3eda29cnscx67",
"decimals": 18,
"eth_contract_addr": "0x0487F746B01A663108E7c4E5739F282491a45799",
"is_verified": false,
"name": "YuzuSwap LP Token",
"num_holders": 1,
"num_transfers": 4,
"symbol": "LPT",
"total_supply": "3454145239972177",
"type": "ERC20"
}
],
"is_total_count_clipped": false,
"total_count": 13
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: UNINTERESTING
Transfer-Encoding: chunked

0 comments on commit 708476e

Please sign in to comment.