Skip to content

Commit 8ecfdd2

Browse files
satawatnacksatawatnackRogerKSInkitlabs
authored
Add feeds signature order (#151)
* add feeds signature order * fix import * add tick price * typo * fix review * change feed type * add feeds price data * change timestamp * update getFeedsPriceData and test case * fix review --------- Co-authored-by: satawatnack <[email protected]> Co-authored-by: Kitipong Sirirueangsakul <[email protected]> Co-authored-by: nkitlabs <[email protected]>
1 parent 1421e19 commit 8ecfdd2

17 files changed

+1465
-66
lines changed

app/app.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ import (
124124
bandbank "github.com/bandprotocol/chain/v2/x/bank"
125125
bandbankkeeper "github.com/bandprotocol/chain/v2/x/bank/keeper"
126126
"github.com/bandprotocol/chain/v2/x/feeds"
127+
feedsclient "github.com/bandprotocol/chain/v2/x/feeds/client"
127128
feedskeeper "github.com/bandprotocol/chain/v2/x/feeds/keeper"
128129
feedstypes "github.com/bandprotocol/chain/v2/x/feeds/types"
129130
"github.com/bandprotocol/chain/v2/x/globalfee"
@@ -188,7 +189,10 @@ var (
188189
oracle.AppModuleBasic{},
189190
tss.AppModuleBasic{},
190191
rollingseed.AppModuleBasic{},
191-
bandtss.NewAppModuleBasic(oracleclient.OracleRequestSignatureHandler),
192+
bandtss.NewAppModuleBasic(
193+
oracleclient.OracleRequestSignatureHandler,
194+
feedsclient.FeedsRequestSignatureHandler,
195+
),
192196
feeds.AppModuleBasic{},
193197
globalfee.AppModule{},
194198
)
@@ -579,23 +583,25 @@ func NewBandApp(
579583
)
580584
oracleIBCModule := oracle.NewIBCModule(app.OracleKeeper)
581585

586+
app.FeedsKeeper = feedskeeper.NewKeeper(
587+
appCodec,
588+
keys[feedstypes.StoreKey],
589+
app.OracleKeeper,
590+
app.StakingKeeper,
591+
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
592+
)
593+
582594
// Add TSS route
583595
tssRouter.
584596
AddRoute(tsstypes.RouterKey, tsstypes.NewSignatureOrderHandler()).
585597
AddRoute(oracletypes.RouterKey, oracle.NewSignatureOrderHandler(app.OracleKeeper)).
586-
AddRoute(bandtsstypes.RouterKey, bandtsstypes.NewSignatureOrderHandler())
598+
AddRoute(bandtsstypes.RouterKey, bandtsstypes.NewSignatureOrderHandler()).
599+
AddRoute(feedstypes.RouterKey, feeds.NewSignatureOrderHandler(app.FeedsKeeper))
587600

588601
// It is vital to seal the request signature router here as to not allow
589602
// further handlers to be registered after the keeper is created since this
590603
// could create invalid or non-deterministic behavior.
591604
tssRouter.Seal()
592-
app.FeedsKeeper = feedskeeper.NewKeeper(
593-
appCodec,
594-
keys[feedstypes.StoreKey],
595-
app.OracleKeeper,
596-
app.StakingKeeper,
597-
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
598-
)
599605

600606
app.StakingKeeper.SetHooks(
601607
stakingtypes.NewMultiStakingHooks(

proto/feeds/v1beta1/feeds.proto

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,50 @@ message PriceService {
140140
// Url is the URL of the price service.
141141
string url = 3;
142142
}
143+
144+
// SignalPrice is a structure that defines the price of a signal id.
145+
message SignalPrice {
146+
option (gogoproto.equal) = true;
147+
148+
// SignalID is the signal id of the price.
149+
string signal_id = 1 [(gogoproto.customname) = "SignalID"];
150+
151+
// Price is the price of the signal id.
152+
uint64 price = 2;
153+
}
154+
155+
//
156+
message FeedsPriceData {
157+
option (gogoproto.equal) = true;
158+
159+
// Prices is the list of prices of the feeds.
160+
repeated SignalPrice signalPrices = 1 [(gogoproto.nullable) = false];
161+
162+
// Timestamp is the timestamp at which the price was submitted.
163+
int64 timestamp = 2;
164+
}
165+
166+
// FeedType is a structure that defines the type of feed.
167+
enum FeedType {
168+
option (gogoproto.goproto_enum_prefix) = false;
169+
170+
// FEED_TYPE_UNSPECIFIED is an unspecified feed type.
171+
FEED_TYPE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "FEED_TYPE_UNSPECIFIED"];
172+
173+
// FEED_TYPE_DEFAULT is a default feed type.
174+
FEED_TYPE_DEFAULT = 1 [(gogoproto.enumvalue_customname) = "FEED_TYPE_DEFAULT"];
175+
176+
// FEED_TYPE_TICK is a tick feed type.
177+
FEED_TYPE_TICK = 2 [(gogoproto.enumvalue_customname) = "FEED_TYPE_TICK"];
178+
}
179+
180+
// FeedSignatureOrder defines a general signature order for feed data.
181+
message FeedsSignatureOrder {
182+
option (gogoproto.goproto_getters) = false;
183+
184+
// SignalIDs is the list of signal ids that require signatures.
185+
repeated string signal_ids = 1 [(gogoproto.customname) = "SignalIDs"];
186+
187+
// FeedType is the type of feed.
188+
FeedType feed_type = 2 [(gogoproto.customname) = "FeedType"];
189+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
export WALLET_NAME=requester
4+
export SIGNAL_IDs=crypto_price.ethusd,crypto_price.usdtusd
5+
6+
# 0: Unspecified, 1: Default, 2: Tick
7+
export FEEDS_TYPE=1
8+
9+
bandd tx bandtss request-signature feeds-prices $SIGNAL_IDs $FEEDS_TYPE \
10+
--from $WALLET_NAME --keyring-backend test \
11+
--gas-prices 0.0025uband --fee-limit 100uband \
12+
-b sync -y

x/feeds/client/cli/tx.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ import (
1414
"github.com/spf13/cobra"
1515

1616
"github.com/bandprotocol/chain/v2/pkg/grant"
17+
bandtsstypes "github.com/bandprotocol/chain/v2/x/bandtss/types"
1718
"github.com/bandprotocol/chain/v2/x/feeds/types"
1819
)
1920

2021
const (
2122
flagExpiration = "expiration"
23+
flagFeeLimit = "fee-limit"
2224
)
2325

2426
// getGrantMsgTypes returns types for GrantMsg.
@@ -192,3 +194,53 @@ $ %s tx feeds update-price-service 1234abcedf 1.0.0 http://www.example.com --fro
192194

193195
return cmd
194196
}
197+
198+
// GetCmdRequestSignature implements the request signature handler.
199+
func GetCmdRequestSignature() *cobra.Command {
200+
return &cobra.Command{
201+
Use: "feeds-prices [signal_id1,signal_id2,...] [feeds-type]",
202+
Short: "Request bandtss signature prices from list of signal id and feeds-type (1: default, 2: tick)",
203+
Args: cobra.ExactArgs(2),
204+
Long: strings.TrimSpace(
205+
fmt.Sprintf(`Request bandtss signature from list of signal id and feeds-type (1: default, 2: tick)
206+
Example:
207+
$ %s tx bandtss request-signature feeds-prices crypto_price.ethusd,crypto_price.usdtusd 1 --fee-limit 10uband
208+
`,
209+
version.AppName,
210+
),
211+
),
212+
RunE: func(cmd *cobra.Command, args []string) error {
213+
clientCtx, err := client.GetClientTxContext(cmd)
214+
if err != nil {
215+
return err
216+
}
217+
218+
coinStr, err := cmd.Flags().GetString(flagFeeLimit)
219+
if err != nil {
220+
return err
221+
}
222+
223+
feeLimit, err := sdk.ParseCoinsNormalized(coinStr)
224+
if err != nil {
225+
return err
226+
}
227+
228+
signalIDs := strings.Split(args[0], ",")
229+
230+
feedsType, err := strconv.ParseInt(args[1], 10, 32)
231+
if err != nil {
232+
return err
233+
}
234+
235+
from := clientCtx.GetFromAddress()
236+
content := types.NewFeedSignatureOrder(signalIDs, types.FeedType(feedsType))
237+
238+
msg, err := bandtsstypes.NewMsgRequestSignature(content, feeLimit, from)
239+
if err != nil {
240+
return err
241+
}
242+
243+
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
244+
},
245+
}
246+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package client
2+
3+
import (
4+
bandtssclient "github.com/bandprotocol/chain/v2/x/bandtss/client"
5+
"github.com/bandprotocol/chain/v2/x/feeds/client/cli"
6+
)
7+
8+
// FeedsRequestSignatureHandler is the request signature handler.
9+
var FeedsRequestSignatureHandler = bandtssclient.NewRequestSignatureHandler(cli.GetCmdRequestSignature)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package keeper
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
9+
"github.com/bandprotocol/chain/v2/x/feeds/types"
10+
)
11+
12+
// GetFeedsPriceData returns the price data of the given signalIDs
13+
func (k Keeper) GetFeedsPriceData(
14+
ctx sdk.Context,
15+
signalIDs []string,
16+
ft types.FeedType,
17+
) (*types.FeedsPriceData, error) {
18+
var prices []types.SignalPrice
19+
for _, signalID := range signalIDs {
20+
// Get the price of the signal
21+
p, err := k.GetPrice(ctx, signalID)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
// Check if the feed type is tick
27+
if ft == types.FEED_TYPE_TICK {
28+
err := p.ToTick()
29+
if err != nil {
30+
return nil, err
31+
}
32+
}
33+
34+
// Check if the price is available
35+
if p.PriceStatus != types.PriceStatusAvailable {
36+
return nil, fmt.Errorf("%s: price not available", signalID)
37+
}
38+
39+
// Check if the price is too old
40+
if ctx.BlockTime().Sub(time.Unix(p.Timestamp, 0)) > types.MAX_PRICE_TIME_DIFF {
41+
return nil, fmt.Errorf("%s: price too old", signalID)
42+
}
43+
44+
// Append the price to the list
45+
prices = append(prices, types.SignalPrice{
46+
SignalID: signalID,
47+
Price: p.Price,
48+
})
49+
}
50+
return types.NewFeedsPriceData(prices, ctx.BlockTime().Unix()), nil
51+
}

0 commit comments

Comments
 (0)