Skip to content

Commit

Permalink
Merge pull request #128 from gnoswap-labs/GSW-687-feat-incentive-stak…
Browse files Browse the repository at this point in the history
…e-getter

GSW-687 feat: staker contract data getter
  • Loading branch information
notJoon authored Dec 14, 2023
2 parents 9f2f4bb + 630b294 commit b2f05c3
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 60 deletions.
75 changes: 75 additions & 0 deletions staker/_RPC_api_incentive.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package staker

import (
"encoding/json"

pl "gno.land/r/demo/pool"

"gno.land/p/demo/ufmt"
)

const INTERNAL_REWARD_TOKEN_PATH = "gno.land/r/demo/gns"

// type ApiQueryBase struct {
// Height int64 `json:"height"`
// Timestamp int64 `json:"timestamp"`
// }

type RewardToken struct {
PoolPath string `json:"poolPath"`
RewardsTokenList []string `json:"rewardsTokenList"`
}

type ResponseRewardTokens struct {
Stat ApiQueryBase `json:"stat"`
Response struct {
Data []RewardToken `json:"data"`
} `json:"response"`
}

func ApiGetRewardTokens() string {
rewardTokens := []RewardToken{}

poolList := pl.PoolGetPoolList()
for _, poolPath := range poolList {
thisPoolRewardTokens := []string{}

// HANDLE INTERNAL
_, ok := poolTiers[poolPath]
if ok {
thisPoolRewardTokens = append(thisPoolRewardTokens, INTERNAL_REWARD_TOKEN_PATH)
}

// HANDLE EXTERNAL
for _, incentiveId := range poolIncentives[poolPath] {
thisPoolRewardTokens = append(thisPoolRewardTokens, incentives[incentiveId].rewardToken)
}

rewardTokens = append(rewardTokens, RewardToken{
PoolPath: poolPath,
RewardsTokenList: thisPoolRewardTokens,
})
}

// JSON
qb := ApiQueryBase{
Height: GetHeight(),
Timestamp: int64(GetTimestamp()),
}

r := ResponseRewardTokens{
Stat: qb,
Response: struct {
Data []RewardToken `json:"data"`
}{
Data: rewardTokens,
},
}

rr, err := json.Marshal(r)
if err != nil {
panic(ufmt.Sprintf("[STAKER] _RPC_api_incentive.gno__ApiGetRewardTokens() || json marshal error: %v", err))
}

return string(rr)
}
119 changes: 105 additions & 14 deletions staker/_RPC_api.gno → staker/_RPC_api_stake.gno
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,94 @@ type ApiQueryBase struct {
Timestamp int64 `json:"timestamp"`
}

type Reward struct {
IncentiveType string `json:"incentiveType"`
TargetPoolPath string `json:"targetPoolPath"`
RewardTokenPath string `json:"rewardTokenPath"`
RewardTokenAmount uint64 `json:"rewardTokenAmount"`
}

type LpTokenReward struct {
LpTokenId uint64 `json:"lpTokenId"`
Address string `json:"address"`
Rewards []Reward `json:"rewards"`
}

type ResponseApiGetRewards struct {
Stat ApiQueryBase `json:"stat"`
Response struct {
Data []LpTokenReward `json:"data"`
} `json:"response"`
}

func ApiGetRewards() string {
lpTokenRewards := []LpTokenReward{}

for tokenId, deposit := range deposits {
rewards := []Reward{}

// get internal gns reward
internalGNS := rewardMathComputeInternalRewardAmount(tokenId, deposit)
if internalGNS > 0 {
rewards = append(rewards, Reward{
IncentiveType: "INTERNAL",
TargetPoolPath: deposit.targetPoolPath,
RewardTokenPath: INTERNAL_REWARD_TOKEN_PATH,
RewardTokenAmount: internalGNS,
})
}

// find all external reward list for poolPath which lpTokenId is staked
for _, incentiveId := range poolIncentives[deposit.targetPoolPath] {
externalReward := rewardMathComputeExternalRewardAmount(tokenId, deposit, incentives[incentiveId])
rewards = append(rewards, Reward{
IncentiveType: "EXTERNAL",
TargetPoolPath: deposit.targetPoolPath,
RewardTokenPath: incentives[incentiveId].rewardToken,
RewardTokenAmount: externalReward,
})
}

lpTokenReward := LpTokenReward{
LpTokenId: tokenId,
Address: deposit.owner.String(),
Rewards: rewards,
}
lpTokenRewards = append(lpTokenRewards, lpTokenReward)
}

qb := ApiQueryBase{
Height: GetHeight(),
Timestamp: int64(GetTimestamp()),
}

r := ResponseApiGetRewards{
Stat: qb,
Response: struct {
Data []LpTokenReward `json:"data"`
}{
Data: lpTokenRewards,
},
}

rr, err := json.Marshal(r)
if err != nil {
panic(ufmt.Sprintf("[STAKER] _RPC_api.gno__ApiGetRewards() || json marshal error: %v", err))
}

return string(rr)
}

type ApiRewardByAddress struct {
Type string `json:"type"`
Token string `json:"token"`
Reward uint64 `json:"reward"`
Address string `json:"address"`
LpTokenId uint64 `json:"lpTokenId"`
IncentiveType string `json:"incentiveType"`
TargetPoolPath string `json:"targetPoolPath"`
RewardTokenPath string `json:"rewardTokenPath"`
RewardTokenAmount uint64 `json:"rewardTokenAmount"`
}

type ResponseGetRewardByAddress struct {
type ResponseGetApiRewardByAddress struct {
Stat ApiQueryBase `json:"stat"`
Response struct {
Data []ApiRewardByAddress `json:"data"`
Expand All @@ -35,19 +116,28 @@ func ApiGetRewardByAddress(address std.Address) string {

// get internal gns reward
internalGNS := rewardMathComputeInternalRewardAmount(tokenId, deposit)
rewardList = append(rewardList, ApiRewardByAddress{
Type: "Internal",
Token: "GNS",
Reward: internalGNS,
})

if internalGNS > 0 {
rewardList = append(rewardList, ApiRewardByAddress{
Address: address.String(),
LpTokenId: tokenId,
IncentiveType: "INTERNAL",
TargetPoolPath: poolPath,
RewardTokenPath: INTERNAL_REWARD_TOKEN_PATH,
RewardTokenAmount: internalGNS,
})
}

// find all external reward list for this pool
for _, incentiveId := range poolIncentives[poolPath] {
externalReward := rewardMathComputeExternalRewardAmount(tokenId, deposit, incentives[incentiveId])
rewardList = append(rewardList, ApiRewardByAddress{
Type: "External",
Token: incentives[incentiveId].rewardToken,
Reward: externalReward,
Address: address.String(),
LpTokenId: tokenId,
IncentiveType: "EXTERNAL",
TargetPoolPath: poolPath,
RewardTokenPath: incentives[incentiveId].rewardToken,
RewardTokenAmount: externalReward,
})
}
}
Expand All @@ -58,7 +148,7 @@ func ApiGetRewardByAddress(address std.Address) string {
Timestamp: int64(GetTimestamp()),
}

r := ResponseGetRewardByAddress{
r := ResponseGetApiRewardByAddress{
Stat: qb,
Response: struct {
Data []ApiRewardByAddress `json:"data"`
Expand All @@ -69,7 +159,7 @@ func ApiGetRewardByAddress(address std.Address) string {

rr, err := json.Marshal(r)
if err != nil {
panic(ufmt.Sprintf("[STAKER] _RPC_api.gno__ApiGetRewardByAddress() || json marshal error: %v", err))
panic(ufmt.Sprintf("[STAKER] _RPC_api.gno__ApiGetApiRewardByAddress() || json marshal error: %v", err))
}

return string(rr)
Expand Down Expand Up @@ -98,6 +188,7 @@ func ApiGetStakes() string {

stakes := []ApiStakes{}
for tokenId, deposit := range deposits {

stakes = append(stakes, ApiStakes{
TokenId: tokenId,
Owner: deposit.owner,
Expand Down
19 changes: 11 additions & 8 deletions staker/_TEST_staker_collect_reward_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,15 @@ func TestApiGetRewardsByAddress(t *testing.T) {
// test1 reward check
gra := ApiGetRewardByAddress(test1)
jsonStr := gjson.Parse(gra)
shouldEQ(t, jsonStr.Get("response.data.0.type").String(), "Internal")
shouldEQ(t, jsonStr.Get("response.data.0.token").String(), "GNS")
shouldEQ(t, jsonStr.Get("response.data.0.reward").Int(), 126)
shouldEQ(t, jsonStr.Get("response.data.1.type").String(), "External")
shouldEQ(t, jsonStr.Get("response.data.1.token").String(), "gno.land/r/demo/obl")
shouldEQ(t, jsonStr.Get("response.data.1.reward").Int(), 648)
shouldEQ(t, jsonStr.Get("response.data.0.incentiveType").String(), "INTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/qux:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/qux:500")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenPath").String(), "gno.land/r/demo/obl")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenAmount").Int(), 648)

}

Expand All @@ -150,7 +153,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999626) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999752) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000000648) // external
}

Expand All @@ -162,7 +165,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(2)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000451) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000004891) // external
}
}
Expand Down
19 changes: 11 additions & 8 deletions staker/_TEST_staker_one_external_native_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,15 @@ func TestApiGetRewardsByAddress(t *testing.T) {
// test1 reward check
gra := ApiGetRewardByAddress(test1)
jsonStr := gjson.Parse(gra)
shouldEQ(t, jsonStr.Get("response.data.0.type").String(), "Internal")
shouldEQ(t, jsonStr.Get("response.data.0.token").String(), "GNS")
shouldEQ(t, jsonStr.Get("response.data.0.reward").Int(), 126)
shouldEQ(t, jsonStr.Get("response.data.1.type").String(), "External")
shouldEQ(t, jsonStr.Get("response.data.1.token").String(), wgnotPath)
shouldEQ(t, jsonStr.Get("response.data.1.reward").Int(), 324)
shouldEQ(t, jsonStr.Get("response.data.0.incentiveType").String(), "INTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenPath").String(), "gno.land/r/demo/wugnot")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenAmount").Int(), 324)

}

Expand All @@ -159,7 +162,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999626) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999752) // internal
shouldEQ(t, wugnot.BalanceOf(a2u(test1)), 324) // external
}

Expand All @@ -171,7 +174,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(2)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000451) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, wugnot.BalanceOf(a2u(test1)), 2445) // external
}
}
Expand Down
25 changes: 17 additions & 8 deletions staker/_TEST_staker_one_external_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,15 @@ func TestApiGetRewardsByAddress(t *testing.T) {
// test1 reward check
gra := ApiGetRewardByAddress(test1)
jsonStr := gjson.Parse(gra)
shouldEQ(t, jsonStr.Get("response.data.0.type").String(), "Internal")
shouldEQ(t, jsonStr.Get("response.data.0.token").String(), "GNS")
shouldEQ(t, jsonStr.Get("response.data.0.reward").Int(), 126)
shouldEQ(t, jsonStr.Get("response.data.1.type").String(), "External")
shouldEQ(t, jsonStr.Get("response.data.1.token").String(), "gno.land/r/demo/obl")
shouldEQ(t, jsonStr.Get("response.data.1.reward").Int(), 324)
shouldEQ(t, jsonStr.Get("response.data.0.incentiveType").String(), "INTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenPath").String(), "gno.land/r/demo/obl")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenAmount").Int(), 324)
}

func TestApiGetStakes(t *testing.T) {
Expand All @@ -160,6 +163,12 @@ func TestApiGetStakeByAddress(t *testing.T) {
shouldEQ(t, len(jsonStr.Get("response.data").Array()), 2)
}

func TestApiGetRewardTokens(t *testing.T) {
grt := ApiGetRewardTokens()
jsonStr := gjson.Parse(grt)
shouldEQ(t, len(jsonStr.Get("response.data").Array()), 1)
}

func TestUnstakeToken(t *testing.T) {
{
std.TestSetOrigCaller(test1)
Expand All @@ -169,7 +178,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999626) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999752) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499990000000324) // external
}

Expand All @@ -181,7 +190,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(2)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000451) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499990000002445) // external
}
}
Expand Down
Loading

0 comments on commit b2f05c3

Please sign in to comment.