Skip to content

Commit

Permalink
calculate the total volume and USD prices
Browse files Browse the repository at this point in the history
  • Loading branch information
notJoon committed May 10, 2024
1 parent 50e7d49 commit 328b3dd
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
49 changes: 49 additions & 0 deletions price.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package vwap

import (
"encoding/json"
"fmt"
"math"
"math/big"
"net/http"
"strconv"
)

const priceEndpoint = "http://dev.api.gnoswap.io/v1/tokens/prices"
Expand Down Expand Up @@ -55,3 +59,48 @@ func fetchTokenPrices(endpoint string) ([]TokenPrice, error) {

return apiResponse.Data, nil
}

// calculateVolume calculates the total volume in the USD for each token.
func calculateVolume(prices []TokenPrice) map[string]float64 {
volumeByToken := make(map[string]float64)

for _, price := range prices {
volume, err := strconv.ParseFloat(price.VolumeUSD24h, 64)
if err != nil {
fmt.Printf("failed to parse volume for token %s: %v\n", price.Path, err)
}

volumeByToken[price.Path] = volume
}

return volumeByToken
}

// calculateTokenUSDPrices calculates the USD price based on a base token (wugnot) price and token ratios.
func calculateTokenUSDPrices(tokenData *TokenData, baseTokenPrice float64) map[string]float64 {
tokenPrices := make(map[string]float64)
baseRatio := new(big.Float)

// fund the base token ratio
for _, token := range tokenData.TokenRatio {
if token.TokenName == string(wugnot) {
ratio, _ := new(big.Float).SetString(token.Ratio)
baseRatio.Quo(ratio, big.NewFloat(math.Pow(2, 96)))
break
}
}

// calculate token prices based on the base token price and ratios.
for _, token := range tokenData.TokenRatio {
if token.TokenName != string(wugnot) {
ratio, _ := new(big.Float).SetString(token.Ratio)
tokenRatio := new(big.Float).Quo(ratio, big.NewFloat(math.Pow(2, 96)))
tokenPrice := new(big.Float).Quo(baseRatio, tokenRatio)

price, _ := tokenPrice.Float64()
tokenPrices[token.TokenName] = price * baseTokenPrice
}
}

return tokenPrices
}
66 changes: 66 additions & 0 deletions price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,69 @@ func TestFetchTokenPricesLive(t *testing.T) {
}
}
}

func TestCalculateVolume(t *testing.T) {
t.Parallel()
mockTokenPrices := []TokenPrice{
{
Path: "token1",
VolumeUSD24h: "1000.50",
},
{
Path: "token2",
VolumeUSD24h: "2500.75",
},
{
Path: "token3",
VolumeUSD24h: "500.25",
},
}

volumes := calculateVolume(mockTokenPrices)

assert.Equal(t, 3, len(volumes))
assert.InDelta(t, 1000.50, volumes["token1"], 0.001)
assert.InDelta(t, 2500.75, volumes["token2"], 0.001)
assert.InDelta(t, 500.25, volumes["token3"], 0.001)
}

func TestCalculateTokenPrices(t *testing.T) {
t.Parallel()
mockTokenData := &TokenData{
Status: struct {
Height int `json:"height"`
Timestamp int `json:"timestamp"`
}{
Height: 61946,
Timestamp: 1715064552,
},
TokenRatio: []struct {
TokenName string `json:"token"`
Ratio string `json:"ratio"`
}{
{
TokenName: "gno.land/r/demo/wugnot",
Ratio: "79228162514264337593543950336",
},
{
TokenName: "gno.land/r/demo/qux",
Ratio: "60536002769587966558221762891",
},
{
TokenName: "gno.land/r/demo/foo",
Ratio: "121074204438706762251182081654",
},
{
TokenName: "gno.land/r/demo/gns",
Ratio: "236174327852992866806677676716",
},
},
}

baseTokenPrice := 1.0
tokenPrices := calculateTokenUSDPrices(mockTokenData, baseTokenPrice)

assert.InDelta(t, 1.3087775685458196, tokenPrices["gno.land/r/demo/qux"], 1e-5)
assert.InDelta(t, 0.6543768995349725, tokenPrices["gno.land/r/demo/foo"], 1e-5)
assert.InDelta(t, 0.3354647528142011, tokenPrices["gno.land/r/demo/gns"], 1e-5)
}

0 comments on commit 328b3dd

Please sign in to comment.