Merge branch 'main' into sai/upgrade_cosmos_v0.46

This commit is contained in:
Sai Kumar
2022-04-23 21:23:06 +05:30
161 changed files with 59008 additions and 258 deletions
+298
View File
@@ -0,0 +1,298 @@
# Auction Module CLI Commands
## Build the Chain
The following command builds the Ethermint daemon and places the binary in the `build` directory
```
make build
```
## Setup the Chain
The following steps need to be followed only before running the chain for the first time.
1. Add the root key:
```
./build/chibaclonkd keys add root
```
Keep a note of the keyring passphrase if you set it.
2. Init the chain:
```
./build/chibaclonkd init test-moniker --chain-id ethermint_9000-1
```
3. Add genesis account:
```
./build/chibaclonkd add-genesis-account $(./build/chibaclonkd keys show root -a) 1000000000000000000aphoton,1000000000000000000stake
```
4. Make a genesis tx:
```
./build/chibaclonkd gentx root 1000000000000000000stake --chain-id ethermint_9000-1
```
5. Collect gentxs:
```
./build/chibaclonkd collect-gentxs
```
The chain can now be started using:
```
./build/chibaclonkd start
```
## Querying the Params
The following command will dislay the default params for the `auction` module:
```
# ./build/chibaclonkd q auction params -o json | jq
{
"params": {
"commits_duration": "0s",
"reveals_duration": "0s",
"commit_fee": {
"denom": "",
"amount": "0"
},
"reveal_fee": {
"denom": "",
"amount": "0"
},
"minimum_bid": {
"denom": "",
"amount": "0"
}
}
}
```
## Auction TX CLI Commands
### Create Auction
```
# ./build/chibaclonkd tx auction create 100s 100s 10aphoton 10aphoton 1000aphoton --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
Enter keyring passphrase:
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgCreateAuction","commits_duration":"100s","reveals_duration":"100s","commit_fee":{"denom":"aphoton","amount":"10"},"reveal_fee":{"denom":"aphoton","amount":"10"},"minimum_bid":{"denom":"aphoton","amount":"1000"},"signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: ECAD6DF1ECA763FBD26EB7C2C0B77425FFE2FBEA2BEC57CE0FBC173AE0F45298
```
### Commit Bid
```
# ./build/chibaclonkd tx auction commit-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d 2000aphoton --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
Enter keyring passphrase:
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgCommitBid","auction_id":"e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d","commit_hash":"bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm","signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 71D8CF34026E32A3A34C2C2D4ADF25ABC8D7943A4619761BE27F196603D91B9D
```
### Reveal Bid
```
# ./build/chibaclonkd tx auction reveal-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d root-bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm.json --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
Enter keyring passphrase:
{"body":{"messages":[{"@type":"/vulcanize.auction.v1beta1.MsgRevealBid","auction_id":"e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d","reveal":"7b2261756374696f6e4964223a2265376431346337653761366437353337636264623866626536326632326231353533633265663463653337303561646137633238663830666166326662653064222c22626964416d6f756e74223a22323030306170686f746f6e222c2262696464657241646472657373223a226574686d316c37637374777466326c76657632376b613637633233796b376d6d6a38616437746574707163222c22636861696e4964223a2265746865726d696e745f393030302d31222c226e6f697365223a22636c69666620737566666572206472616d6120676f7370656c2077656173656c207061706572206c696272617279206469736f726465722063757276652073706f74206375727461696e207a6562726120696e76657374206465766f74652072656e64657220636c6970207377616c6c6f77206d6f6e6b6579206f62736572766520726573706f6e7365206c696e6b206372616e6520766961626c6520736576656e227d","signer":"ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 4D1C0B3DDA4050F9BB32240FBD5234229E5C32543C1A0A78033B9531EB0CF8BA
```
## Auction Query CLI Commands
### List Auctions
```
# ./build/chibaclonkd q auction list
auctions:
auctions:
- commit_fee:
amount: "10"
denom: aphoton
commits_end_time: "2021-09-30T07:57:07.933412800Z"
create_time: "2021-09-30T07:55:27.933412800Z"
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
minimum_bid:
amount: "1000"
denom: aphoton
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
reveal_fee:
amount: "10"
denom: aphoton
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
status: commit
winner_address: ""
winning_bid:
amount: "0"
denom: ""
winning_price:
amount: "0"
denom: ""
pagination: null
```
### Get Bid
```
# ./build/chibaclonkd q auction get-bid e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0e ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
bid:
auction_id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
bid_amount:
amount: "0"
denom: ""
bidder_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
commit_fee:
amount: "10"
denom: aphoton
commit_hash: bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm
commit_time: "2021-09-30T08:49:48.358878200Z"
reveal_fee:
amount: "10"
denom: aphoton
reveal_time: "0001-01-01T00:00:00Z"
status: commit
```
### Get All Bids for an Auction
```
./build/chibaclonkd q auction get-bids e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
bids:
- auction_id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
bid_amount:
amount: "0"
denom: ""
bidder_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
commit_fee:
amount: "10"
denom: aphoton
commit_hash: bafyreibt4twofrc3xi2es27cfrroy346iy6lr3gkw33i5dltkqqarlyltm
commit_time: "2021-09-30T08:49:48.358878200Z"
reveal_fee:
amount: "10"
denom: aphoton
reveal_time: "0001-01-01T00:00:00Z"
status: commit
```
### Get Auction by AuctionID
```
# ./build/chibaclonkd q auction get e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
auction:
commit_fee:
amount: "10"
denom: aphoton
commits_end_time: "2021-09-30T07:57:07.933412800Z"
create_time: "2021-09-30T07:55:27.933412800Z"
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
minimum_bid:
amount: "1000"
denom: aphoton
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
reveal_fee:
amount: "10"
denom: aphoton
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
status: commit
winner_address: ""
winning_bid:
amount: "0"
denom: ""
winning_price:
amount: "0"
denom: ""
```
### Get Auction by Bidder
```
# ./build/chibaclonkd q auction query-by-owner ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
auctions:
auctions:
- commit_fee:
amount: "10"
denom: aphoton
commits_end_time: "2021-09-30T07:57:07.933412800Z"
create_time: "2021-09-30T07:55:27.933412800Z"
id: e7d14c7e7a6d7537cbdb8fbe62f22b1553c2ef4ce3705ada7c28f80faf2fbe0d
minimum_bid:
amount: "1000"
denom: aphoton
owner_address: ethm1l7cstwtf2lvev27ka67c23yk7mmj8ad7tetpqc
reveal_fee:
amount: "10"
denom: aphoton
reveals_end_time: "2021-09-30T07:58:47.933412800Z"
status: commit
winner_address: ""
winning_bid:
amount: "0"
denom: ""
winning_price:
amount: "0"
denom: ""
```
### Query Account Balance
```
# ./build/chibaclonkd q auction balance
balance:
- amount: "20"
denom: aphoton
```
+13
View File
@@ -0,0 +1,13 @@
package auction
import (
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/auction/keeper"
)
// EndBlocker is called every block, returns updated validator set.
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
k.EndBlockerProcessAuctions(ctx)
return []abci.ValidatorUpdate{}
}
+263
View File
@@ -0,0 +1,263 @@
package cli
import (
"fmt"
"strings"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
"github.com/spf13/cobra"
"github.com/tharsis/ethermint/x/auction/types"
)
func GetQueryCmd() *cobra.Command {
auctionQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
auctionQueryCmd.AddCommand(
GetCmdList(),
GetCmdGetAuction(),
GetCmdGetBid(),
GetCmdGetBids(),
GetCmdAuctionsByBidder(),
GetCmdAuctionsByOwner(),
GetCmdQueryParams(),
GetCmdBalance(),
)
return auctionQueryCmd
}
// GetCmdList queries all auctions.
func GetCmdList() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List auctions.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Auctions(cmd.Context(), &types.AuctionsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdGetBid queries an auction bid.
func GetCmdGetBid() *cobra.Command {
cmd := &cobra.Command{
Use: "get-bid [auction-id] [bidder]",
Short: "Get auction bid.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
id := args[0]
bidder := args[1]
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetBid(cmd.Context(), &types.BidRequest{AuctionId: id, Bidder: bidder})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdGetBids queries all auction bids.
func GetCmdGetBids() *cobra.Command {
cmd := &cobra.Command{
Use: "get-bids [auction-id]",
Short: "Get all auction bids.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
id := args[0]
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetBids(cmd.Context(), &types.BidsRequest{AuctionId: id})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdGetAuction queries an auction.
func GetCmdGetAuction() *cobra.Command {
cmd := &cobra.Command{
Use: "get [ID]",
Short: "Get auction.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
id := args[0]
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetAuction(cmd.Context(), &types.AuctionRequest{Id: id})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdAuctionsByBidder queries auctions by bidder.
func GetCmdAuctionsByBidder() *cobra.Command {
cmd := &cobra.Command{
Use: "query-by-bidder [address]",
Short: "Query auctions by bidder.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
address := args[0]
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.AuctionsByBidder(cmd.Context(), &types.AuctionsByBidderRequest{BidderAddress: address})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdAuctionsByOwner queries auctions by owner
func GetCmdAuctionsByOwner() *cobra.Command {
cmd := &cobra.Command{
Use: "query-by-owner [address]",
Short: "Query auctions by owner/creator.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
address := args[0]
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.AuctionsByOwner(cmd.Context(), &types.AuctionsByOwnerRequest{OwnerAddress: address})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdQueryParams implements the params query command.
func GetCmdQueryParams() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Args: cobra.NoArgs,
Short: "Query the current auction parameters information.",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values set as auction parameters.
Example:
$ %s query auction params
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.QueryParams(cmd.Context(), &types.QueryParamsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdBalance queries the auction module account balance.
func GetCmdBalance() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "Get auction module account balance.",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Balance(cmd.Context(), &types.BalanceRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
+187
View File
@@ -0,0 +1,187 @@
package cli
import (
"encoding/hex"
"fmt"
"io/ioutil"
"time"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tharsis/ethermint/x/auction/types"
wnsUtils "github.com/tharsis/ethermint/utils"
)
// GetTxCmd returns transaction commands for this module.
func GetTxCmd() *cobra.Command {
auctionTxCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Auction transactions subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
auctionTxCmd.AddCommand(
GetCmdCreateAuction(),
GetCmdCommitBid(),
GetCmdRevealBid(),
)
return auctionTxCmd
}
func GetCmdCreateAuction() *cobra.Command {
cmd := &cobra.Command{
Use: "create [commits-duration] [reveals-duration] [commit-fee] [reveal-fee] [minimum-bid]",
Short: "Create auction.",
Args: cobra.ExactArgs(5),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
commitsDuration, err := time.ParseDuration(args[0])
if err != nil {
return err
}
revealsDuration, err := time.ParseDuration(args[1])
if err != nil {
return err
}
commitFee, err := sdk.ParseCoinNormalized(args[2])
if err != nil {
return err
}
revealFee, err := sdk.ParseCoinNormalized(args[3])
if err != nil {
return err
}
minimumBid, err := sdk.ParseCoinNormalized(args[4])
if err != nil {
return err
}
params := types.Params{
CommitsDuration: commitsDuration,
RevealsDuration: revealsDuration,
CommitFee: commitFee,
RevealFee: revealFee,
MinimumBid: minimumBid,
}
msg := types.NewMsgCreateAuction(params, clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
// GetCmdCommitBid is the CLI command for committing a bid.
func GetCmdCommitBid() *cobra.Command {
cmd := &cobra.Command{
Use: "commit-bid [auction-id] [bid-amount]",
Short: "Commit sealed bid.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
bidAmount, err := sdk.ParseCoinNormalized(args[1])
if err != nil {
return err
}
mnemonic, err := wnsUtils.GenerateMnemonic()
if err != nil {
return err
}
chainID := viper.GetString("chain-id")
auctionID := args[0]
reveal := map[string]interface{}{
"chainId": chainID,
"auctionId": auctionID,
"bidderAddress": clientCtx.GetFromAddress().String(),
"bidAmount": bidAmount.String(),
"noise": mnemonic,
}
commitHash, content, err := wnsUtils.GenerateHash(reveal)
if err != nil {
return err
}
// Save reveal file.
ioutil.WriteFile(fmt.Sprintf("%s-%s.json", clientCtx.GetFromName(), commitHash), content, 0600)
msg := types.NewMsgCommitBid(auctionID, commitHash, clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
// GetCmdRevealBid is the CLI command for revealing a bid.
func GetCmdRevealBid() *cobra.Command {
cmd := &cobra.Command{
Use: "reveal-bid [auction-id] [reveal-file-path]",
Short: "Reveal bid.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
auctionID := args[0]
revealFilePath := args[1]
revealBytes, err := ioutil.ReadFile(revealFilePath)
if err != nil {
return err
}
msg := types.NewMsgRevealBid(auctionID, hex.EncodeToString(revealBytes), clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
+16
View File
@@ -0,0 +1,16 @@
package testutil
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/tharsis/ethermint/testutil/network"
)
func TestIntegrationTestSuite(t *testing.T) {
cfg := network.DefaultConfig()
cfg.NumValidators = 1
suite.Run(t, NewIntegrationTestSuite(cfg))
}
+80
View File
@@ -0,0 +1,80 @@
package testutil
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/crypto/hd"
"github.com/tharsis/ethermint/testutil/network"
)
type IntegrationTestSuite struct {
suite.Suite
cfg network.Config
network *network.Network
defaultAuctionID string
}
var (
ownerAccount = "owner"
bidderAccount = "bidder"
ownerAddress string
bidderAddress string
)
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
return &IntegrationTestSuite{cfg: cfg}
}
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
// setting up random owner and bidder accounts
s.createAccountWithBalance(ownerAccount, &ownerAddress)
s.createAccountWithBalance(bidderAccount, &bidderAddress)
s.defaultAuctionID = s.createAuctionAndBid(true, false)
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func (s *IntegrationTestSuite) createAccountWithBalance(accountName string, accountAddress *string) {
val := s.network.Validators[0]
sr := s.Require()
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.EthSecp256k1)
sr.NoError(err)
val.ClientCtx.Keyring.SavePubKey(accountName, info.GetPubKey(), hd.EthSecp256k1Type)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
_, err = banktestutil.MsgSendExec(
val.ClientCtx,
val.Address,
newAddr,
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200000))),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
)
sr.NoError(err)
*accountAddress = newAddr.String()
}
+255
View File
@@ -0,0 +1,255 @@
package testutil
import (
"fmt"
"github.com/cosmos/cosmos-sdk/types/rest"
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
)
const (
randomAuctionID = "randomAuctionID"
randomBidderAddress = "randomBidderAddress"
randomOwnerAddress = "randomOwnerAddress"
)
func (suite *IntegrationTestSuite) TestGetAllAuctionsGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/auctions", val.APIAddress)
testCases := []struct {
msg string
url string
errorMsg string
isErrorExpected bool
}{
{
"invalid request to get all auctions",
reqUrl + randomAuctionID,
"",
true,
},
{
"valid request to get all auctions",
reqUrl,
"",
false,
},
}
for _, tc := range testCases {
suite.Run(tc.msg, func() {
resp, err := rest.GetRequest(tc.url)
if tc.isErrorExpected {
sr.Contains(string(resp), tc.errorMsg)
} else {
sr.NoError(err)
var auctions auctiontypes.AuctionsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
sr.NotZero(len(auctions.Auctions.Auctions))
}
})
}
}
func (suite *IntegrationTestSuite) TestQueryParamsGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/params", val.APIAddress)
suite.Run("valid request to get auction params", func() {
resp, err := rest.GetRequest(reqUrl)
suite.Require().NoError(err)
var params auctiontypes.QueryParamsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &params)
sr.NoError(err)
sr.Equal(*params.GetParams(), auctiontypes.DefaultParams())
})
}
func (suite *IntegrationTestSuite) TestGetAuctionGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/auctions/", val.APIAddress)
testCases := []struct {
msg string
url string
errorMsg string
isErrorExpected bool
preRun func() string
}{
{
"invalid request to get an auction",
reqUrl + randomAuctionID,
"",
true,
func() string { return "" },
},
{
"valid request to get an auction",
reqUrl,
"",
false,
func() string { return suite.defaultAuctionID },
},
}
for _, tc := range testCases {
suite.Run(tc.msg, func() {
auctionID := tc.preRun()
resp, err := rest.GetRequest(tc.url + auctionID)
if tc.isErrorExpected {
sr.Contains(string(resp), tc.errorMsg)
} else {
sr.NoError(err)
var auction auctiontypes.AuctionResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auction)
sr.NoError(err)
sr.Equal(auctionID, auction.Auction.Id)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetBidsGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/bids/", val.APIAddress)
testCases := []struct {
msg string
url string
errorMsg string
isErrorExpected bool
preRun func() string
}{
{
"invalid request to get all bids",
reqUrl,
"",
true,
func() string { return "" },
},
{
"valid request to get all bids",
reqUrl,
"",
false,
func() string { return suite.createAuctionAndBid(false, true) },
},
}
for _, tc := range testCases {
suite.Run(tc.msg, func() {
auctionID := tc.preRun()
tc.url += auctionID
resp, err := rest.GetRequest(tc.url)
if tc.isErrorExpected {
sr.Contains(string(resp), tc.errorMsg)
} else {
sr.NoError(err)
var bids auctiontypes.BidsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bids)
sr.NoError(err)
sr.Equal(auctionID, bids.Bids[0].AuctionId)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetBidGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/bids/", val.APIAddress)
testCases := []struct {
msg string
url string
errorMsg string
isErrorExpected bool
}{
{
"invalid request to get bid",
fmt.Sprintf("%s/%s/", reqUrl, randomAuctionID),
"",
true,
},
{
"valid request to get bid",
fmt.Sprintf("%s/%s/%s", reqUrl, randomAuctionID, randomBidderAddress),
"",
false,
},
}
for _, tc := range testCases {
suite.Run(tc.msg, func() {
resp, err := rest.GetRequest(tc.url)
if tc.isErrorExpected {
sr.Contains(string(resp), tc.errorMsg)
} else {
sr.NoError(err)
var bid auctiontypes.BidResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bid)
sr.NoError(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetAuctionsByOwnerGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/by-owner/", val.APIAddress)
testCases := []struct {
msg string
url string
errorMsg string
isErrorExpected bool
}{
{
"invalid request to get auctions by owner",
reqUrl,
"",
true,
},
{
"valid request to get auctions by owner",
fmt.Sprintf("%s/%s", reqUrl, randomOwnerAddress),
"",
false,
},
}
for _, tc := range testCases {
suite.Run(tc.msg, func() {
resp, err := rest.GetRequest(tc.url)
if tc.isErrorExpected {
sr.Contains(string(resp), tc.errorMsg)
} else {
sr.NoError(err)
var auctions auctiontypes.AuctionsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
sr.NoError(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestQueryBalanceGrpc() {
val := suite.network.Validators[0]
sr := suite.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/auction/v1beta1/balance", val.APIAddress)
msg := "valid request to get the auction module balance"
suite.createAuctionAndBid(false, true)
suite.Run(msg, func() {
resp, err := rest.GetRequest(reqUrl)
sr.NoError(err)
var response auctiontypes.BalanceResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetBalance()))
})
}
+311
View File
@@ -0,0 +1,311 @@
package testutil
import (
"fmt"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/auction/client/cli"
"github.com/tharsis/ethermint/x/auction/types"
)
var queryJSONFlag = []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
func (suite *IntegrationTestSuite) TestGetCmdQueryParams() {
val := suite.network.Validators[0]
sr := suite.Require()
suite.Run(fmt.Sprintf("Case %s", "fetch query params"), func() {
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdQueryParams(), queryJSONFlag)
sr.NoError(err)
var params types.QueryParamsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &params)
sr.NoError(err)
sr.Equal(types.DefaultParams(), *params.Params)
})
}
func (suite *IntegrationTestSuite) TestGetCmdBalance() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
createAuctionAndBid bool
}{
{
"fetch module balance without creating auction and bid",
false,
},
{
"fetch module balance with valid auction and bid",
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndBid {
suite.createAuctionAndBid(false, true)
}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdBalance(), queryJSONFlag)
sr.NoError(err)
var balance types.BalanceResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &balance)
sr.NoError(err)
if test.createAuctionAndBid {
sr.NotZero(len(balance.Balance))
}
})
}
}
func (suite *IntegrationTestSuite) TestGetCmdList() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
createAuction bool
}{
{
"list auctions when no auctions exist",
false,
},
{
"list auctions after creating an auction",
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
sr.NoError(err)
var auctions types.AuctionsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auctions)
sr.NoError(err)
if test.createAuction {
sr.NotZero(len(auctions.Auctions.Auctions))
}
})
}
}
func (suite *IntegrationTestSuite) TestGetCmdGetBid() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
args []string
createAuctionAndBid bool
}{
{
"get bid without creating auction",
[]string{},
false,
},
{
"get bid after creating auction and bid",
[]string{},
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndBid {
auctionID := suite.createAuctionAndBid(false, true)
test.args = append(test.args, auctionID)
getBidsArgs := []string{auctionID, queryJSONFlag[0]}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), getBidsArgs)
sr.NoError(err)
var bids types.BidsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
sr.NoError(err)
test.args = append(test.args, bids.GetBids()[0].BidderAddress)
}
test.args = append(test.args, queryJSONFlag...)
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBid(), test.args)
if test.createAuctionAndBid {
sr.NoError(err)
var bid types.BidResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bid)
sr.NoError(err)
sr.NotNil(bid.GetBid())
} else {
sr.Error(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetCmdGetBids() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
args []string
createAuctionAndBid bool
}{
{
"get bids without creating auction",
[]string{},
false,
},
{
"get bids after creating auction and bid",
[]string{},
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndBid {
auctionID := suite.createAuctionAndBid(false, true)
test.args = append(test.args, auctionID)
}
test.args = append(test.args, queryJSONFlag...)
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), test.args)
if test.createAuctionAndBid {
sr.NoError(err)
var bids types.BidsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
sr.NoError(err)
sr.NotZero(len(bids.Bids))
} else {
sr.Error(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetCmdGetAuction() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
auctionID string
createAuction bool
}{
{
"get auction with empty auction ID",
"",
false,
},
{
"get auction with valid auction ID",
"",
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuction {
test.auctionID = suite.defaultAuctionID
}
args := []string{test.auctionID, queryJSONFlag[0]}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetAuction(), args)
if test.createAuction {
sr.NoError(err)
var auction types.AuctionResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auction)
sr.NoError(err)
sr.NotNil(auction.GetAuction())
sr.Equal(test.auctionID, auction.GetAuction().Id)
} else {
sr.Error(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetCmdAuctionsByBidder() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
createAuctionAndBid bool
bidderAddress string
}{
{
"get auctions by bidder without creating auctions",
false,
"",
},
{
"get auctions by bidder for valid bidder address",
true,
"",
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndBid {
auctionID := suite.createAuctionAndBid(false, true)
args := []string{auctionID, queryJSONFlag[0]}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdGetBids(), args)
sr.NoError(err)
var bids types.BidsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &bids)
sr.NoError(err)
test.bidderAddress = bids.Bids[0].BidderAddress
}
getByBidderArgs := []string{test.bidderAddress, queryJSONFlag[0]}
_, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdAuctionsByBidder(), getByBidderArgs)
if test.createAuctionAndBid {
sr.NoError(err)
} else {
sr.Error(err)
}
})
}
}
func (suite IntegrationTestSuite) createAuctionAndBid(createAuction, createBid bool) string {
val := suite.network.Validators[0]
sr := suite.Require()
auctionID := ""
if createAuction {
auctionArgs := []string{
sampleCommitTime, sampleRevealTime,
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("100%s", suite.cfg.BondDenom),
}
resp, err := suite.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
sr.NoError(err)
sr.Zero(resp.Code)
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
sr.NoError(err)
var queryResponse types.AuctionsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
auctionID = queryResponse.Auctions.Auctions[0].Id
} else {
auctionID = suite.defaultAuctionID
}
if createBid {
bidArgs := []string{auctionID, fmt.Sprintf("200%s", suite.cfg.BondDenom)}
resp, err := suite.executeTx(cli.GetCmdCommitBid(), bidArgs, bidderAccount)
sr.NoError(err)
sr.Zero(resp.Code)
}
return auctionID
}
+141
View File
@@ -0,0 +1,141 @@
package testutil
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/auction/client/cli"
"github.com/tharsis/ethermint/x/auction/types"
)
const (
sampleCommitTime = "90s"
sampleRevealTime = "5s"
placeholderAuctionID = "placeholder_auction_id"
)
func (suite *IntegrationTestSuite) TestTxCreateAuction() {
sr := suite.Require()
testCases := []struct {
msg string
args []string
expectErr bool
}{
{
"create auction with missing arguments",
[]string{sampleCommitTime, sampleRevealTime},
true,
},
{
"create auction with proper arguments",
[]string{
sampleCommitTime, sampleRevealTime,
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("100%s", suite.cfg.BondDenom),
},
false,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
resp, err := suite.executeTx(cli.GetCmdCreateAuction(), test.args, ownerAccount)
if test.expectErr {
sr.Error(err)
} else {
sr.NoError(err)
sr.Zero(resp.Code)
}
})
}
}
func (suite *IntegrationTestSuite) TestTxCommitBid() {
val := suite.network.Validators[0]
sr := suite.Require()
testCases := []struct {
msg string
args []string
createAuction bool
}{
{
"commit bid with missing args",
[]string{fmt.Sprintf("200%s", suite.cfg.BondDenom)},
false,
},
{
"commit bid with valid args",
[]string{
placeholderAuctionID,
fmt.Sprintf("200%s", suite.cfg.BondDenom),
},
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuction {
auctionArgs := []string{
sampleCommitTime, sampleRevealTime,
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("10%s", suite.cfg.BondDenom),
fmt.Sprintf("100%s", suite.cfg.BondDenom),
}
_, err := suite.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
sr.NoError(err)
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(),
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)})
sr.NoError(err)
var queryResponse types.AuctionsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.NotNil(queryResponse.GetAuctions())
test.args[0] = queryResponse.GetAuctions().Auctions[0].Id
}
resp, err := suite.executeTx(cli.GetCmdCommitBid(), test.args, bidderAccount)
if test.createAuction {
sr.NoError(err)
sr.Zero(resp.Code)
} else {
sr.Error(err)
}
})
}
}
func (suite *IntegrationTestSuite) executeTx(cmd *cobra.Command, args []string, caller string) (sdk.TxResponse, error) {
val := suite.network.Validators[0]
additionalArgs := []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, caller),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", suite.cfg.BondDenom)),
}
args = append(args, additionalArgs...)
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
if err != nil {
return sdk.TxResponse{}, err
}
var resp sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
if err != nil {
return sdk.TxResponse{}, err
}
err = suite.network.WaitForNextBlock()
if err != nil {
return sdk.TxResponse{}, err
}
return resp, nil
}
+44
View File
@@ -0,0 +1,44 @@
package auction
import (
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/auction/keeper"
"github.com/tharsis/ethermint/x/auction/types"
)
// func NewGenesisState(params types.Params, auctions []types.Auction) types.GenesisState {
// return types.GenesisState{Params: params, Auctions: &types.Auctions{Auctions: auctions}}
// }
func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data types.GenesisState) []abci.ValidatorUpdate {
keeper.SetParams(ctx, data.Params)
for _, auction := range data.Auctions {
keeper.SaveAuction(ctx, auction)
}
return []abci.ValidatorUpdate{}
}
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) types.GenesisState {
params := keeper.GetParams(ctx)
auctions := keeper.ListAuctions(ctx)
var genesisAuctions []*types.Auction
for _, auction := range auctions {
genesisAuctions = append(genesisAuctions, &auction)
}
return types.GenesisState{Params: params, Auctions: genesisAuctions}
}
func ValidateGenesis(data types.GenesisState) error {
err := data.Params.Validate()
if err != nil {
return err
}
return nil
}
+91
View File
@@ -0,0 +1,91 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/tharsis/ethermint/x/auction/types"
)
type Querier struct {
Keeper
}
var _ types.QueryServer = Querier{}
// Auctions queries all auctions
func (q Querier) Auctions(c context.Context, req *types.AuctionsRequest) (*types.AuctionsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
resp := q.Keeper.ListAuctions(ctx)
return &types.AuctionsResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
}
// GetAuction queries an auction
func (q Querier) GetAuction(c context.Context, req *types.AuctionRequest) (*types.AuctionResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if req.Id == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
}
resp := q.Keeper.GetAuction(ctx, req.Id)
return &types.AuctionResponse{Auction: resp}, nil
}
// GetBid queries and auction bid
func (q Querier) GetBid(c context.Context, req *types.BidRequest) (*types.BidResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if req.AuctionId == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
}
if req.Bidder == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bidder address is required")
}
resp := q.Keeper.GetBid(ctx, req.AuctionId, req.Bidder)
return &types.BidResponse{Bid: &resp}, nil
}
// GetBids queries all auction bids
func (q Querier) GetBids(c context.Context, req *types.BidsRequest) (*types.BidsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if req.AuctionId == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "auction ID is required")
}
resp := q.Keeper.GetBids(ctx, req.AuctionId)
return &types.BidsResponse{Bids: resp}, nil
}
// AuctionsByBidder queries auctions by bidder
func (q Querier) AuctionsByBidder(c context.Context, req *types.AuctionsByBidderRequest) (*types.AuctionsByBidderResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if req.BidderAddress == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bidder address is required")
}
resp := q.Keeper.QueryAuctionsByBidder(ctx, req.BidderAddress)
return &types.AuctionsByBidderResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
}
// AuctionsByOwner queries auctions by owner
func (q Querier) AuctionsByOwner(c context.Context, req *types.AuctionsByOwnerRequest) (*types.AuctionsByOwnerResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if req.OwnerAddress == "" {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "owner address is required")
}
resp := q.Keeper.QueryAuctionsByOwner(ctx, req.OwnerAddress)
return &types.AuctionsByOwnerResponse{Auctions: &types.Auctions{Auctions: resp}}, nil
}
// QueryParams implements the params query command
func (q Querier) QueryParams(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
resp := q.Keeper.GetParams(ctx)
return &types.QueryParamsResponse{Params: &resp}, nil
}
// Balance queries the auction module account balance
func (q Querier) Balance(c context.Context, req *types.BalanceRequest) (*types.BalanceResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
resp := q.Keeper.GetAuctionModuleBalances(ctx)
return &types.BalanceResponse{Balance: resp}, nil
}
+355
View File
@@ -0,0 +1,355 @@
package keeper_test
import (
"context"
"fmt"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/app"
"github.com/tharsis/ethermint/x/auction/types"
)
const testCommitHash = "71D8CF34026E32A3A34C2C2D4ADF25ABC8D7943A4619761BE27F196603D91B9D"
func (suite *KeeperTestSuite) TestGrpcGetAllAuctions() {
client, ctx, k := suite.queryClient, suite.ctx, suite.app.AuctionKeeper
testCases := []struct {
msg string
req *types.AuctionsRequest
createAuctions bool
auctionCount int
}{
{
"fetch auctions when no auctions exist",
&types.AuctionsRequest{},
false,
0,
},
{
"fetch auctions with one auction created",
&types.AuctionsRequest{},
true,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctions {
account := app.CreateRandomAccounts(1)[0]
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
))
_, err = k.CreateAuction(ctx, types.NewMsgCreateAuction(k.GetParams(ctx), account))
suite.Require().NoError(err)
}
resp, _ := client.Auctions(context.Background(), test.req)
suite.Require().Equal(test.auctionCount, len(resp.GetAuctions().Auctions))
})
}
}
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
testCases := []struct {
msg string
req *types.QueryParamsRequest
}{
{
"fetch params",
&types.QueryParamsRequest{},
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
resp, err := suite.queryClient.QueryParams(context.Background(), test.req)
suite.Require().Nil(err)
suite.Require().Equal(*(resp.Params), types.DefaultParams())
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetAuction() {
testCases := []struct {
msg string
req *types.AuctionRequest
createAuction bool
}{
{
"fetch auction with empty auction ID",
&types.AuctionRequest{},
false,
},
{
"fetch auction with valid auction ID",
&types.AuctionRequest{},
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuction {
auction, _, err := suite.createAuctionAndCommitBid(false)
suite.Require().NoError(err)
test.req.Id = auction.Id
}
resp, err := suite.queryClient.GetAuction(context.Background(), test.req)
if test.createAuction {
suite.Require().Nil(err)
suite.Require().NotNil(resp.GetAuction())
suite.Require().Equal(test.req.Id, resp.GetAuction().Id)
} else {
suite.Require().NotNil(err)
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetBids() {
testCases := []struct {
msg string
req *types.BidsRequest
createAuction bool
commitBid bool
bidCount int
}{
{
"fetch all bids when no auction exists",
&types.BidsRequest{},
false,
false,
0,
},
{
"fetch all bids for valid auction but no added bids",
&types.BidsRequest{},
true,
false,
0,
},
{
"fetch all bids for valid auction and valid bid",
&types.BidsRequest{},
true,
true,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuction {
auction, _, err := suite.createAuctionAndCommitBid(test.commitBid)
suite.Require().NoError(err)
test.req.AuctionId = auction.Id
}
resp, err := suite.queryClient.GetBids(context.Background(), test.req)
if test.createAuction {
suite.Require().Nil(err)
suite.Require().Equal(test.bidCount, len(resp.GetBids()))
} else {
suite.Require().NotNil(err)
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetBid() {
testCases := []struct {
msg string
req *types.BidRequest
createAuctionAndBid bool
}{
{
"fetch bid when bid does not exist",
&types.BidRequest{},
false,
},
{
"fetch bid when valid bid exists",
&types.BidRequest{},
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndBid {
auction, bid, err := suite.createAuctionAndCommitBid(test.createAuctionAndBid)
suite.Require().NoError(err)
test.req.AuctionId = auction.Id
test.req.Bidder = bid.BidderAddress
}
resp, err := suite.queryClient.GetBid(context.Background(), test.req)
if test.createAuctionAndBid {
suite.Require().NoError(err)
suite.Require().NotNil(resp.Bid)
suite.Require().Equal(test.req.Bidder, resp.Bid.BidderAddress)
} else {
suite.Require().NotNil(err)
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetAuctionsByBidder() {
testCases := []struct {
msg string
req *types.AuctionsByBidderRequest
createAuctionAndCommitBid bool
auctionCount int
}{
{
"get auctions by bidder with invalid bidder address",
&types.AuctionsByBidderRequest{},
false,
0,
},
{
"get auctions by bidder with valid auction and bid",
&types.AuctionsByBidderRequest{},
true,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuctionAndCommitBid {
_, bid, err := suite.createAuctionAndCommitBid(test.createAuctionAndCommitBid)
suite.Require().NoError(err)
test.req.BidderAddress = bid.BidderAddress
}
resp, err := suite.queryClient.AuctionsByBidder(context.Background(), test.req)
if test.createAuctionAndCommitBid {
suite.Require().NoError(err)
suite.Require().NotNil(resp.Auctions)
suite.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
} else {
suite.Require().NotNil(err)
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetAuctionsByOwner() {
testCases := []struct {
msg string
req *types.AuctionsByOwnerRequest
createAuction bool
auctionCount int
}{
{
"get auctions by owner with invalid owner address",
&types.AuctionsByOwnerRequest{},
false,
0,
},
{
"get auctions by owner with valid auction",
&types.AuctionsByOwnerRequest{},
true,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
if test.createAuction {
auction, _, err := suite.createAuctionAndCommitBid(false)
suite.Require().NoError(err)
test.req.OwnerAddress = auction.OwnerAddress
}
resp, err := suite.queryClient.AuctionsByOwner(context.Background(), test.req)
if test.createAuction {
suite.Require().NoError(err)
suite.Require().NotNil(resp.Auctions)
suite.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
} else {
suite.Require().NotNil(err)
suite.Require().Error(err)
}
})
}
}
func (suite KeeperTestSuite) TestGrpcQueryBalance() {
testCases := []struct {
msg string
req *types.BalanceRequest
createAuction bool
auctionCount int
}{
{
"get balance with no auctions created",
&types.BalanceRequest{},
false,
0,
},
{
"get balance with single auction created",
&types.BalanceRequest{},
true,
1,
},
}
for _, test := range testCases {
if test.createAuction {
_, _, err := suite.createAuctionAndCommitBid(true)
suite.Require().NoError(err)
}
resp, err := suite.queryClient.Balance(context.Background(), test.req)
suite.Require().NoError(err)
suite.Require().Equal(test.auctionCount, len(resp.GetBalance()))
}
}
func (suite *KeeperTestSuite) createAuctionAndCommitBid(commitBid bool) (*types.Auction, *types.Bid, error) {
ctx, k := suite.ctx, suite.app.AuctionKeeper
accCount := 1
if commitBid {
accCount++
}
accounts := app.CreateRandomAccounts(accCount)
for _, account := range accounts {
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
))
if err != nil {
return nil, nil, err
}
}
auction, err := k.CreateAuction(ctx, types.NewMsgCreateAuction(k.GetParams(ctx), accounts[0]))
if err != nil {
return nil, nil, err
}
if commitBid {
bid, err := k.CommitBid(ctx, types.NewMsgCommitBid(auction.Id, testCommitHash, accounts[1]))
if err != nil {
return nil, nil, err
}
return auction, bid, nil
}
return auction, nil, nil
}
+37
View File
@@ -0,0 +1,37 @@
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/auction/types"
)
// RegisterInvariants registers all auction module invariants.
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k))
}
// ModuleAccountInvariant checks that the 'auction' module account balance is non-negative.
func ModuleAccountInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() {
return sdk.FormatInvariant(
types.ModuleName,
"module-account",
fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName)),
true
}
return "", false
}
}
// AllInvariants runs all invariants of the auctions module.
func AllInvariants(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
return ModuleAccountInvariant(k)(ctx)
}
}
+658
View File
@@ -0,0 +1,658 @@
package keeper
import (
"encoding/hex"
"encoding/json"
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
params "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tharsis/ethermint/x/auction/types"
wnsUtils "github.com/tharsis/ethermint/utils"
)
// CompletedAuctionDeleteTimeout => Completed auctions are deleted after this timeout (after reveals end time).
const CompletedAuctionDeleteTimeout = time.Hour * 24
// PrefixIDToAuctionIndex is the prefix for Id -> Auction index in the KVStore.
// Note: This is the primary index in the system.
// Note: Golang doesn't support const arrays.
var PrefixIDToAuctionIndex = []byte{0x00}
// prefixOwnerToAuctionsIndex is the prefix for the Owner -> [Auction] index in the KVStore.
var prefixOwnerToAuctionsIndex = []byte{0x01}
// PrefixAuctionBidsIndex is the prefix for the (auction, bidder) -> Bid index in the KVStore.
var PrefixAuctionBidsIndex = []byte{0x02}
// PrefixBidderToAuctionsIndex is the prefix for the Bidder -> [Auction] index in the KVStore.
var PrefixBidderToAuctionsIndex = []byte{0x03}
// Keeper maintains the link to storage and exposes getter/setter methods for the various parts of the state machine
type Keeper struct {
accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper
// Track auction usage in other cosmos-sdk modules (more like a usage tracker).
usageKeepers []types.AuctionUsageKeeper
storeKey sdk.StoreKey // Unexposed key to access store from sdk.Context
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
paramSubspace params.Subspace
}
// AuctionClientKeeper is the subset of functionality exposed to other modules.
type AuctionClientKeeper interface {
HasAuction(ctx sdk.Context, id string) bool
GetAuction(ctx sdk.Context, id string) types.Auction
MatchAuctions(ctx sdk.Context, matchFn func(*types.Auction) bool) []*types.Auction
}
// NewKeeper creates new instances of the auction Keeper
func NewKeeper(accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, storeKey sdk.StoreKey, cdc codec.BinaryCodec, ps params.Subspace) Keeper {
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}
return Keeper{
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
storeKey: storeKey,
cdc: cdc,
paramSubspace: ps,
}
}
func (k *Keeper) SetUsageKeepers(usageKeepers []types.AuctionUsageKeeper) {
k.usageKeepers = usageKeepers
}
func (k Keeper) GetUsageKeepers() []types.AuctionUsageKeeper {
return k.usageKeepers
}
// Generates Auction Id -> Auction index key.
func GetAuctionIndexKey(id string) []byte {
return append(PrefixIDToAuctionIndex, []byte(id)...)
}
// Generates Owner -> Auctions index key.
func GetOwnerToAuctionsIndexKey(owner string, auctionID string) []byte {
return append(append(prefixOwnerToAuctionsIndex, []byte(owner)...), []byte(auctionID)...)
}
func GetBidderToAuctionsIndexKey(bidder string, auctionID string) []byte {
return append(append(PrefixBidderToAuctionsIndex, []byte(bidder)...), []byte(auctionID)...)
}
func GetBidIndexKey(auctionID string, bidder string) []byte {
return append(GetAuctionBidsIndexPrefix(auctionID), []byte(bidder)...)
}
func GetAuctionBidsIndexPrefix(auctionID string) []byte {
return append(append(PrefixAuctionBidsIndex, []byte(auctionID)...))
}
// SaveAuction - saves a auction to the store.
func (k Keeper) SaveAuction(ctx sdk.Context, auction *types.Auction) {
store := ctx.KVStore(k.storeKey)
// Auction Id -> Auction index.
store.Set(GetAuctionIndexKey(auction.Id), k.cdc.MustMarshal(auction))
// Owner -> [Auction] index.
store.Set(GetOwnerToAuctionsIndexKey(auction.OwnerAddress, auction.Id), []byte{})
// Notify interested parties.
for _, keeper := range k.usageKeepers {
keeper.OnAuction(ctx, auction.Id)
}
}
func (k Keeper) SaveBid(ctx sdk.Context, bid *types.Bid) {
store := ctx.KVStore(k.storeKey)
store.Set(GetBidIndexKey(bid.AuctionId, bid.BidderAddress), k.cdc.MustMarshal(bid))
store.Set(GetBidderToAuctionsIndexKey(bid.BidderAddress, bid.AuctionId), []byte{})
// Notify interested parties.
for _, keeper := range k.usageKeepers {
keeper.OnAuctionBid(ctx, bid.AuctionId, bid.BidderAddress)
}
}
func (k Keeper) DeleteBid(ctx sdk.Context, bid types.Bid) {
store := ctx.KVStore(k.storeKey)
store.Delete(GetBidIndexKey(bid.AuctionId, bid.BidderAddress))
store.Delete(GetOwnerToAuctionsIndexKey(bid.BidderAddress, bid.AuctionId))
}
// HasAuction - checks if a auction by the given Id exists.
func (k Keeper) HasAuction(ctx sdk.Context, id string) bool {
store := ctx.KVStore(k.storeKey)
return store.Has(GetAuctionIndexKey(id))
}
func (k Keeper) HasBid(ctx sdk.Context, id string, bidder string) bool {
store := ctx.KVStore(k.storeKey)
return store.Has(GetBidIndexKey(id, bidder))
}
// DeleteAuction - deletes the auction.
func (k Keeper) DeleteAuction(ctx sdk.Context, auction types.Auction) {
// Delete all bids first.
bids := k.GetBids(ctx, auction.Id)
for _, bid := range bids {
k.DeleteBid(ctx, *bid)
}
// Delete the auction itself.
store := ctx.KVStore(k.storeKey)
store.Delete(GetAuctionIndexKey(auction.Id))
store.Delete(GetOwnerToAuctionsIndexKey(auction.OwnerAddress, auction.Id))
}
// GetAuction - gets a record from the store.
func (k Keeper) GetAuction(ctx sdk.Context, id string) *types.Auction {
store := ctx.KVStore(k.storeKey)
auctionKey := GetAuctionIndexKey(id)
if !store.Has(auctionKey) {
return nil
}
bz := store.Get(auctionKey)
var obj types.Auction
k.cdc.MustUnmarshal(bz, &obj)
return &obj
}
// GetBids gets the auction bids.
func (k Keeper) GetBids(ctx sdk.Context, id string) []*types.Bid {
store := ctx.KVStore(k.storeKey)
bids := []*types.Bid{}
itr := sdk.KVStorePrefixIterator(store, GetAuctionBidsIndexPrefix(id))
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Bid
k.cdc.MustUnmarshal(bz, &obj)
bids = append(bids, &obj)
}
}
return bids
}
func (k Keeper) GetBid(ctx sdk.Context, id string, bidder string) types.Bid {
store := ctx.KVStore(k.storeKey)
bz := store.Get(GetBidIndexKey(id, bidder))
var obj types.Bid
k.cdc.MustUnmarshal(bz, &obj)
return obj
}
// ListAuctions - get all auctions.
func (k Keeper) ListAuctions(ctx sdk.Context) []types.Auction {
var auctions []types.Auction
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixIDToAuctionIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Auction
k.cdc.MustUnmarshal(bz, &obj)
auctions = append(auctions, obj)
}
}
return auctions
}
// QueryAuctionsByOwner - query auctions by owner.
func (k Keeper) QueryAuctionsByOwner(ctx sdk.Context, ownerAddress string) []types.Auction {
auctions := []types.Auction{}
ownerPrefix := append(prefixOwnerToAuctionsIndex, []byte(ownerAddress)...)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, ownerPrefix)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
auctionID := itr.Key()[len(ownerPrefix):]
bz := store.Get(append(PrefixIDToAuctionIndex, auctionID...))
if bz != nil {
var obj types.Auction
k.cdc.MustUnmarshal(bz, &obj)
auctions = append(auctions, obj)
}
}
return auctions
}
// QueryAuctionsByBidder - query auctions by bidder
func (k Keeper) QueryAuctionsByBidder(ctx sdk.Context, bidderAddress string) []types.Auction {
auctions := []types.Auction{}
bidderPrefix := append(PrefixBidderToAuctionsIndex, []byte(bidderAddress)...)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, []byte(bidderPrefix))
defer itr.Close()
for ; itr.Valid(); itr.Next() {
auctionID := itr.Key()[len(bidderPrefix):]
bz := store.Get(append(PrefixIDToAuctionIndex, auctionID...))
if bz != nil {
var obj types.Auction
k.cdc.MustUnmarshal(bz, &obj)
auctions = append(auctions, obj)
}
}
return auctions
}
// MatchAuctions - get all matching auctions.
func (k Keeper) MatchAuctions(ctx sdk.Context, matchFn func(*types.Auction) bool) []*types.Auction {
var auctions []*types.Auction
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixIDToAuctionIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Auction
k.cdc.MustUnmarshal(bz, &obj)
if matchFn(&obj) {
auctions = append(auctions, &obj)
}
}
}
return auctions
}
// CreateAuction creates a new auction.
func (k Keeper) CreateAuction(ctx sdk.Context, msg types.MsgCreateAuction) (*types.Auction, error) {
// Might be called from another module directly, always validate.
err := msg.ValidateBasic()
if err != nil {
return nil, err
}
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
// Generate auction Id.
account := k.accountKeeper.GetAccount(ctx, signerAddress)
if account == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "Account not found.")
}
auctionID := types.AuctionID{
Address: signerAddress,
AccNum: account.GetAccountNumber(),
Sequence: account.GetSequence(),
}.Generate()
// Compute timestamps.
now := ctx.BlockTime()
commitsEndTime := now.Add(time.Duration(msg.CommitsDuration))
revealsEndTime := now.Add(time.Duration(msg.CommitsDuration + msg.RevealsDuration))
auction := types.Auction{
Id: auctionID,
Status: types.AuctionStatusCommitPhase,
OwnerAddress: signerAddress.String(),
CreateTime: now,
CommitsEndTime: commitsEndTime,
RevealsEndTime: revealsEndTime,
CommitFee: msg.CommitFee,
RevealFee: msg.RevealFee,
MinimumBid: msg.MinimumBid,
}
// Save auction in store.
k.SaveAuction(ctx, &auction)
return &auction, nil
}
func (k Keeper) CommitBid(ctx sdk.Context, msg types.MsgCommitBid) (*types.Bid, error) {
if !k.HasAuction(ctx, msg.AuctionId) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.")
}
auction := k.GetAuction(ctx, msg.AuctionId)
if auction.Status != types.AuctionStatusCommitPhase {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in commit phase.")
}
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
// Take auction fees from account.
totalFee := auction.CommitFee.Add(auction.RevealFee)
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, types.ModuleName, sdk.NewCoins(totalFee))
if sdkErr != nil {
return nil, sdkErr
}
// Check if an old bid already exists, if so, return old bids auction fee (update bid scenario).
bidder := signerAddress.String()
if k.HasBid(ctx, msg.AuctionId, bidder) {
oldBid := k.GetBid(ctx, msg.AuctionId, bidder)
oldTotalFee := oldBid.CommitFee.Add(oldBid.RevealFee)
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, signerAddress, sdk.NewCoins(oldTotalFee))
if sdkErr != nil {
return nil, sdkErr
}
}
// Save new bid.
bid := types.Bid{
AuctionId: msg.AuctionId,
BidderAddress: bidder,
Status: types.BidStatusCommitted,
CommitHash: msg.CommitHash,
CommitTime: ctx.BlockTime(),
CommitFee: auction.CommitFee,
RevealFee: auction.RevealFee,
}
k.SaveBid(ctx, &bid)
return &bid, nil
}
// RevealBid reeals a bid comitted earlier.
func (k Keeper) RevealBid(ctx sdk.Context, msg types.MsgRevealBid) (*types.Auction, error) {
if !k.HasAuction(ctx, msg.AuctionId) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.")
}
auction := k.GetAuction(ctx, msg.AuctionId)
if auction.Status != types.AuctionStatusRevealPhase {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in reveal phase.")
}
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
if !k.HasBid(ctx, msg.AuctionId, signerAddress.String()) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid not found.")
}
bid := k.GetBid(ctx, auction.Id, signerAddress.String())
if bid.Status != types.BidStatusCommitted {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid not in committed state.")
}
revealBytes, err := hex.DecodeString(msg.Reveal)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal string.")
}
cid, err := wnsUtils.CIDFromJSONBytes(revealBytes)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal JSON.")
}
if bid.CommitHash != cid {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Commit hash mismatch.")
}
var reveal map[string]interface{}
err = json.Unmarshal(revealBytes, &reveal)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Reveal JSON unmarshal error.")
}
chainID, err := wnsUtils.GetAttributeAsString(reveal, "chainId")
if err != nil || chainID != ctx.ChainID() {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal chainID.")
}
auctionID, err := wnsUtils.GetAttributeAsString(reveal, "auctionId")
if err != nil || auctionID != msg.AuctionId {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal auction Id.")
}
bidderAddress, err := wnsUtils.GetAttributeAsString(reveal, "bidderAddress")
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid address.")
}
if bidderAddress != signerAddress.String() {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Reveal bid address mismatch.")
}
bidAmountStr, err := wnsUtils.GetAttributeAsString(reveal, "bidAmount")
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.")
}
bidAmount, err := sdk.ParseCoinNormalized(bidAmountStr)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.")
}
if bidAmount.IsLT(auction.MinimumBid) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bid is lower than minimum bid.")
}
// Lock bid amount.
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, types.ModuleName, sdk.NewCoins(bidAmount))
if sdkErr != nil {
return nil, sdkErr
}
// Update bid.
bid.BidAmount = bidAmount
bid.RevealTime = ctx.BlockTime()
bid.Status = types.BidStatusRevealed
k.SaveBid(ctx, &bid)
return auction, nil
}
// GetAuctionModuleBalances gets the auction module account(s) balances.
func (k Keeper) GetAuctionModuleBalances(ctx sdk.Context) sdk.Coins {
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
balances := k.bankKeeper.GetAllBalances(ctx, moduleAddress)
return balances
}
func (k Keeper) EndBlockerProcessAuctions(ctx sdk.Context) {
// Transition auction state (commit, reveal, expired, completed).
k.processAuctionPhases(ctx)
// Delete stale auctions.
k.deleteCompletedAuctions(ctx)
}
func (k Keeper) processAuctionPhases(ctx sdk.Context) {
auctions := k.MatchAuctions(ctx, func(_ *types.Auction) bool {
return true
})
for _, auction := range auctions {
// Commit -> Reveal state.
if auction.Status == types.AuctionStatusCommitPhase && ctx.BlockTime().After(auction.CommitsEndTime) {
auction.Status = types.AuctionStatusRevealPhase
k.SaveAuction(ctx, auction)
ctx.Logger().Info(fmt.Sprintf("Moved auction %s to reveal phase.", auction.Id))
}
// Reveal -> Expired state.
if auction.Status == types.AuctionStatusRevealPhase && ctx.BlockTime().After(auction.RevealsEndTime) {
auction.Status = types.AuctionStatusExpired
k.SaveAuction(ctx, auction)
ctx.Logger().Info(fmt.Sprintf("Moved auction %s to expired state.", auction.Id))
}
// If auction has expired, pick a winner from revealed bids.
if auction.Status == types.AuctionStatusExpired {
k.pickAuctionWinner(ctx, auction)
}
}
}
// Delete completed stale auctions.
func (k Keeper) deleteCompletedAuctions(ctx sdk.Context) {
auctions := k.MatchAuctions(ctx, func(auction *types.Auction) bool {
deleteTime := auction.RevealsEndTime.Add(CompletedAuctionDeleteTimeout)
return auction.Status == types.AuctionStatusCompleted && ctx.BlockTime().After(deleteTime)
})
for _, auction := range auctions {
ctx.Logger().Info(fmt.Sprintf("Deleting completed auction %s after timeout.", auction.Id))
k.DeleteAuction(ctx, *auction)
}
}
func (k Keeper) pickAuctionWinner(ctx sdk.Context, auction *types.Auction) {
ctx.Logger().Info(fmt.Sprintf("Picking auction %s winner.", auction.Id))
var highestBid *types.Bid
var secondHighestBid *types.Bid
bids := k.GetBids(ctx, auction.Id)
for _, bid := range bids {
ctx.Logger().Info(fmt.Sprintf("Processing bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
// Only consider revealed bids.
if bid.Status != types.BidStatusRevealed {
ctx.Logger().Info(fmt.Sprintf("Ignoring unrevealed bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
continue
}
// Init highest bid.
if highestBid == nil {
highestBid = bid
ctx.Logger().Info(fmt.Sprintf("Initializing 1st bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
continue
}
if highestBid.BidAmount.IsLT(bid.BidAmount) {
ctx.Logger().Info(fmt.Sprintf("New highest bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
secondHighestBid = highestBid
highestBid = bid
ctx.Logger().Info(fmt.Sprintf("Updated 1st bid %s %s", highestBid.BidderAddress, highestBid.BidAmount.String()))
ctx.Logger().Info(fmt.Sprintf("Updated 2nd bid %s %s", secondHighestBid.BidderAddress, secondHighestBid.BidAmount.String()))
} else if secondHighestBid == nil || secondHighestBid.BidAmount.IsLT(bid.BidAmount) {
ctx.Logger().Info(fmt.Sprintf("New 2nd highest bid %s %s", bid.BidderAddress, bid.BidAmount.String()))
secondHighestBid = bid
ctx.Logger().Info(fmt.Sprintf("Updated 2nd bid %s %s", secondHighestBid.BidderAddress, secondHighestBid.BidAmount.String()))
} else {
ctx.Logger().Info(fmt.Sprintf("Ignoring bid as it doesn't affect 1st/2nd price %s %s", bid.BidderAddress, bid.BidAmount.String()))
}
}
// Highest bid is the winner, but pays second highest bid price.
auction.Status = types.AuctionStatusCompleted
if highestBid != nil {
auction.WinnerAddress = highestBid.BidderAddress
auction.WinningBid = highestBid.BidAmount
// Winner pays 2nd price, if a 2nd price exists.
auction.WinningPrice = highestBid.BidAmount
if secondHighestBid != nil {
auction.WinningPrice = secondHighestBid.BidAmount
}
ctx.Logger().Info(fmt.Sprintf("Auction %s winner %s.", auction.Id, auction.WinnerAddress))
ctx.Logger().Info(fmt.Sprintf("Auction %s winner bid %s.", auction.Id, auction.WinningBid.String()))
ctx.Logger().Info(fmt.Sprintf("Auction %s winner price %s.", auction.Id, auction.WinningPrice.String()))
} else {
ctx.Logger().Info(fmt.Sprintf("Auction %s has no valid revealed bids (no winner).", auction.Id))
}
k.SaveAuction(ctx, auction)
for _, bid := range bids {
bidderAddress, err := sdk.AccAddressFromBech32(bid.BidderAddress)
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Invalid bidderAddress address. %v", err))
panic("Invalid bidder address.")
}
if bid.Status == types.BidStatusRevealed {
// Send reveal fee back to bidders that've revealed the bid.
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidderAddress, sdk.NewCoins(bid.RevealFee))
if sdkErr != nil {
ctx.Logger().Error(fmt.Sprintf("Auction error returning reveal fee: %v", sdkErr))
panic(sdkErr)
}
}
// Send back locked bid amount to all bidders.
sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, bidderAddress, sdk.NewCoins(bid.BidAmount))
if sdkErr != nil {
ctx.Logger().Error(fmt.Sprintf("Auction error returning bid amount: %v", sdkErr))
panic(sdkErr)
}
}
// Process winner account (if nobody bids, there won't be a winner).
if auction.WinnerAddress != "" {
winnerAddress, err := sdk.AccAddressFromBech32(auction.WinnerAddress)
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Invalid winner address. %v", err))
panic("Invalid winner address.")
}
// Take 2nd price from winner.
sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, winnerAddress, types.ModuleName, sdk.NewCoins(auction.WinningPrice))
if sdkErr != nil {
ctx.Logger().Error(fmt.Sprintf("Auction error taking funds from winner: %v", sdkErr))
panic(sdkErr)
}
// Burn anything over the min. bid amount.
amountToBurn := auction.WinningPrice.Sub(auction.MinimumBid)
if amountToBurn.IsNegative() {
ctx.Logger().Error(fmt.Sprintf("Auction coins to burn cannot be negative."))
panic("Auction coins to burn cannot be negative.")
}
// Use auction burn module account instead of actually burning coins to better keep track of supply.
sdkErr = k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.AuctionBurnModuleAccountName, sdk.NewCoins(amountToBurn))
if sdkErr != nil {
ctx.Logger().Error(fmt.Sprintf("Auction error burning coins: %v", sdkErr))
panic(sdkErr)
}
}
// Notify other modules (hook).
ctx.Logger().Info(fmt.Sprintf("Auction %s notifying %d modules.", auction.Id, len(k.usageKeepers)))
for _, keeper := range k.usageKeepers {
ctx.Logger().Info(fmt.Sprintf("Auction %s notifying module %s.", auction.Id, keeper.ModuleName()))
keeper.OnAuctionWinnerSelected(ctx, auction.Id)
}
}
+56
View File
@@ -0,0 +1,56 @@
package keeper_test
import (
"testing"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tharsis/ethermint/app"
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
"github.com/tharsis/ethermint/x/auction/types"
)
type KeeperTestSuite struct {
suite.Suite
app *app.EthermintApp
ctx sdk.Context
queryClient types.QueryClient
}
func (suite *KeeperTestSuite) SetupTest() {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
querier := auctionkeeper.Querier{Keeper: testApp.AuctionKeeper}
queryHelper := baseapp.NewQueryServerTestHelper(ctx, testApp.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, querier)
queryClient := types.NewQueryClient(queryHelper)
suite.app, suite.ctx, suite.queryClient = testApp, ctx, queryClient
}
func TestParams(t *testing.T) {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
expParams := types.DefaultParams()
params := testApp.AuctionKeeper.GetParams(ctx)
require.Equal(t, expParams.CommitsDuration, params.CommitsDuration)
require.Equal(t, expParams.RevealsDuration, params.RevealsDuration)
require.Equal(t, expParams.CommitFee, params.CommitFee)
require.Equal(t, expParams.RevealFee, params.RevealFee)
require.Equal(t, expParams.MinimumBid, params.MinimumBid)
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
+110
View File
@@ -0,0 +1,110 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/auction/types"
)
type msgServer struct {
Keeper
}
func NewMsgServer(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}
var _ types.MsgServer = msgServer{}
func (s msgServer) CreateAuction(c context.Context, msg *types.MsgCreateAuction) (*types.MsgCreateAuctionResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := s.Keeper.CreateAuction(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCreateAuction,
sdk.NewAttribute(types.AttributeKeyCommitsDuration, msg.CommitsDuration.String()),
sdk.NewAttribute(types.AttributeKeyCommitFee, msg.CommitFee.String()),
sdk.NewAttribute(types.AttributeKeyRevealFee, msg.RevealFee.String()),
sdk.NewAttribute(types.AttributeKeyMinimumBid, msg.MinimumBid.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
),
})
return &types.MsgCreateAuctionResponse{Auction: resp}, nil
}
// CommitBid is the command for committing a bid
func (s msgServer) CommitBid(c context.Context, msg *types.MsgCommitBid) (*types.MsgCommitBidResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := s.Keeper.CommitBid(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCommitBid,
sdk.NewAttribute(types.AttributeKeyAuctionID, msg.AuctionId),
sdk.NewAttribute(types.AttributeKeyCommitHash, msg.CommitHash),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
),
})
return &types.MsgCommitBidResponse{Bid: resp}, nil
}
//RevealBid is the command for revealing a bid
func (s msgServer) RevealBid(c context.Context, msg *types.MsgRevealBid) (*types.MsgRevealBidResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
resp, err := s.Keeper.RevealBid(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRevealBid,
sdk.NewAttribute(types.AttributeKeyAuctionID, msg.AuctionId),
sdk.NewAttribute(types.AttributeKeyReveal, msg.Reveal),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, signerAddress.String()),
),
})
return &types.MsgRevealBidResponse{Auction: resp}, nil
}
+18
View File
@@ -0,0 +1,18 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/auction/types"
)
// GetParams - Get all parameteras as types.Params.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSubspace.GetParamSet(ctx, &params)
return
}
// SetParams - set the params.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSubspace.SetParamSet(ctx, &params)
}
+142
View File
@@ -0,0 +1,142 @@
package auction
import (
"context"
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/auction/client/cli"
"github.com/tharsis/ethermint/x/auction/keeper"
"github.com/tharsis/ethermint/x/auction/types"
)
// type check to ensure the interface is properly implemented
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)
// app module Basics object
type AppModuleBasic struct {
cdc codec.Codec
}
func (b AppModuleBasic) Name() string {
return types.ModuleName
}
func (b AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
types.RegisterLegacyAminoCodec(cdc)
}
func (b AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
types.RegisterInterfaces(registry)
}
func (b AppModuleBasic) DefaultGenesis(jsonCodec codec.JSONCodec) json.RawMessage {
return jsonCodec.MustMarshalJSON(types.DefaultGenesisState())
}
// Validation check of the Genesis
func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
var data types.GenesisState
err := cdc.UnmarshalJSON(bz, &data)
if err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}
// Once json successfully marshalled, passes along to genesis.go
return ValidateGenesis(data)
}
// Register rest routes
func (b AppModuleBasic) RegisterRESTRoutes(ctx client.Context, rtr *mux.Router) {
// No-op.
}
func (b AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, serveMux *runtime.ServeMux) {
err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(clientCtx))
if err != nil {
panic(err)
}
}
// Get the root query command of this module
func (b AppModuleBasic) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd()
}
// Get the root tx command of this module
func (b AppModuleBasic) GetTxCmd() *cobra.Command {
return cli.GetTxCmd()
}
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper
}
// NewAppModule creates a new AppModule Object
func NewAppModule(cdc codec.Codec, k keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{cdc: cdc},
keeper: k,
}
}
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
keeper.RegisterInvariants(ir, am.keeper)
}
func (am AppModule) Route() sdk.Route {
return sdk.Route{}
}
func (am AppModule) QuerierRoute() string {
return types.QuerierRoute
}
func (am AppModule) LegacyQuerierHandler(cdc *codec.LegacyAmino) sdk.Querier {
return nil
}
func (am AppModule) RegisterServices(cfg module.Configurator) {
querier := keeper.Querier{Keeper: am.keeper}
types.RegisterQueryServer(cfg.QueryServer(), querier)
msgServer := keeper.NewMsgServer(am.keeper)
types.RegisterMsgServer(cfg.MsgServer(), msgServer)
}
func (am AppModule) ConsensusVersion() uint64 {
return 1
}
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
}
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState types.GenesisState
cdc.MustUnmarshalJSON(data, &genesisState)
InitGenesis(ctx, am.keeper, genesisState)
return []abci.ValidatorUpdate{}
}
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return cdc.MustMarshalJSON(&gs)
}
+14
View File
@@ -0,0 +1,14 @@
package auction_test
// func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
// app := app2.Setup(false)
// ctx := app.BaseApp.NewContext(false, tmproto.Header{})
// app.InitChain(abcitypes.RequestInitChain{
// AppStateBytes: []byte("{}"),
// ChainId: "test-chain-id",
// })
// acc := app.AccountKeeper.GetModuleAccount(ctx, auctiontypes.ModuleName)
// require.NotNil(t, acc)
// }
+37
View File
@@ -0,0 +1,37 @@
package types
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/msgservice"
)
// RegisterLegacyAminoCodec registers the necessary x/auction interfaces and concrete types
// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgCreateAuction{}, "auction/MsgCreateAuction", nil)
cdc.RegisterConcrete(&MsgCommitBid{}, "auction/MsgCommitBid", nil)
cdc.RegisterConcrete(&MsgRevealBid{}, "auction/MsgRevealBid", nil)
}
func RegisterInterfaces(registry types.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgCreateAuction{},
&MsgCommitBid{},
&MsgRevealBid{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
var (
amino = codec.NewLegacyAmino()
ModuleCdc = codec.NewAminoCodec(amino)
)
func init() {
RegisterLegacyAminoCodec(amino)
cryptocodec.RegisterCrypto(amino)
amino.Seal()
}
+19
View File
@@ -0,0 +1,19 @@
package types
const (
EventTypeCreateAuction = "create-auction"
EventTypeCommitBid = "commit-bid"
EventTypeRevealBid = "reveal-bid"
AttributeKeyCommitsDuration = "commits-duration"
AttributeKeyRevealsDuration = "reveals-duration"
AttributeKeyCommitFee = "commit-fee"
AttributeKeyRevealFee = "reveal-fee"
AttributeKeyMinimumBid = "minimum-bid"
AttributeKeySigner = "signer"
AttributeKeyAuctionID = "auction-id"
AttributeKeyCommitHash = "commit-hash"
AttributeKeyReveal = "reveal"
AttributeValueCategory = ModuleName
)
+16
View File
@@ -0,0 +1,16 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// AuctionUsageKeeper keep track of auction usage in other modules.
// Used to, for example, prevent deletion of a auction that's in use.
type AuctionUsageKeeper interface {
ModuleName() string
UsesAuction(ctx sdk.Context, auctionID string) bool
OnAuction(ctx sdk.Context, auctionID string)
OnAuctionBid(ctx sdk.Context, auctionID string, bidderAddress string)
OnAuctionWinnerSelected(ctx sdk.Context, auctionID string)
}
+9
View File
@@ -0,0 +1,9 @@
package types
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
// chain config values.
func DefaultGenesisState() *GenesisState {
return &GenesisState{
Params: DefaultParams(),
}
}
+389
View File
@@ -0,0 +1,389 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: vulcanize/auction/v1beta1/genesis.proto
package types
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the genesis state of the auction module
type GenesisState struct {
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
Auctions []*Auction `protobuf:"bytes,2,rep,name=auctions,proto3" json:"auctions,omitempty" json:"bonds" yaml:"bonds"`
}
func (m *GenesisState) Reset() { *m = GenesisState{} }
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
func (*GenesisState) ProtoMessage() {}
func (*GenesisState) Descriptor() ([]byte, []int) {
return fileDescriptor_23ebfbd3a1e67fe6, []int{0}
}
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GenesisState) XXX_Merge(src proto.Message) {
xxx_messageInfo_GenesisState.Merge(m, src)
}
func (m *GenesisState) XXX_Size() int {
return m.Size()
}
func (m *GenesisState) XXX_DiscardUnknown() {
xxx_messageInfo_GenesisState.DiscardUnknown(m)
}
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
func (m *GenesisState) GetParams() Params {
if m != nil {
return m.Params
}
return Params{}
}
func (m *GenesisState) GetAuctions() []*Auction {
if m != nil {
return m.Auctions
}
return nil
}
func init() {
proto.RegisterType((*GenesisState)(nil), "vulcanize.auction.v1beta1.GenesisState")
}
func init() {
proto.RegisterFile("vulcanize/auction/v1beta1/genesis.proto", fileDescriptor_23ebfbd3a1e67fe6)
}
var fileDescriptor_23ebfbd3a1e67fe6 = []byte{
// 264 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x2b, 0xcd, 0x49,
0x4e, 0xcc, 0xcb, 0xac, 0x4a, 0xd5, 0x4f, 0x2c, 0x4d, 0x2e, 0xc9, 0xcc, 0xcf, 0xd3, 0x2f, 0x33,
0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0x92, 0x84, 0x2b, 0xd4, 0x83, 0x2a, 0xd4, 0x83, 0x2a, 0x94, 0x12, 0x49,
0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd2, 0x07, 0xb1, 0x20, 0x1a, 0xa4, 0x54, 0x71, 0x9b, 0x5c, 0x52,
0x59, 0x90, 0x0a, 0x35, 0x57, 0x69, 0x1d, 0x23, 0x17, 0x8f, 0x3b, 0xc4, 0xa6, 0xe0, 0x92, 0xc4,
0x92, 0x54, 0x21, 0x7b, 0x2e, 0xb6, 0x82, 0xc4, 0xa2, 0xc4, 0xdc, 0x62, 0x09, 0x46, 0x05, 0x46,
0x0d, 0x6e, 0x23, 0x45, 0x3d, 0x9c, 0x36, 0xeb, 0x05, 0x80, 0x15, 0x3a, 0xb1, 0x9c, 0xb8, 0x27,
0xcf, 0x10, 0x04, 0xd5, 0x26, 0x14, 0xcb, 0xc5, 0x01, 0x55, 0x57, 0x2c, 0xc1, 0xa4, 0xc0, 0xac,
0xc1, 0x6d, 0xa4, 0x84, 0xc7, 0x08, 0x47, 0x08, 0xdf, 0x49, 0xf6, 0xd3, 0x3d, 0x79, 0xc9, 0xac,
0xe2, 0xfc, 0x3c, 0x2b, 0xa5, 0xa4, 0xfc, 0xbc, 0x94, 0x62, 0x25, 0x85, 0xca, 0xc4, 0xdc, 0x1c,
0x18, 0x27, 0x08, 0x6e, 0xa4, 0x93, 0xdb, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e,
0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31,
0x44, 0xe9, 0xa4, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x97, 0x64, 0x24,
0x16, 0x15, 0x67, 0x16, 0xeb, 0xa7, 0x96, 0x64, 0xa4, 0x16, 0xe5, 0x66, 0xe6, 0x95, 0xe8, 0x57,
0xc0, 0x83, 0x01, 0xec, 0xfd, 0x24, 0x36, 0xb0, 0xff, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff,
0x40, 0x0a, 0x31, 0x1a, 0x82, 0x01, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Auctions) > 0 {
for iNdEx := len(m.Auctions) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Auctions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
{
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.Params.Size()
n += 1 + l + sovGenesis(uint64(l))
if len(m.Auctions) > 0 {
for _, e := range m.Auctions {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Auctions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Auctions = append(m.Auctions, &Auction{})
if err := m.Auctions[len(m.Auctions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)
+18
View File
@@ -0,0 +1,18 @@
package types
const (
// ModuleName is the name of the module
ModuleName = "auction"
// AuctionBurnModuleAccountName is the name of the auction burn module account.
AuctionBurnModuleAccountName = "auction_burn"
// StoreKey to be used when creating the KVStore
StoreKey = ModuleName
// QuerierRoute is the querier route for the staking module
QuerierRoute = ModuleName
// RouterKey is the msg router key for the staking module
RouterKey = ModuleName
)
+150
View File
@@ -0,0 +1,150 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
_ sdk.Msg = &MsgCreateAuction{}
_ sdk.Msg = &MsgCommitBid{}
_ sdk.Msg = &MsgRevealBid{}
)
// NewMsgCreateAuction is the constructor function for MsgCreateAuction.
func NewMsgCreateAuction(params Params, signer sdk.AccAddress) MsgCreateAuction {
return MsgCreateAuction{
CommitsDuration: params.CommitsDuration,
RevealsDuration: params.RevealsDuration,
CommitFee: params.CommitFee,
RevealFee: params.RevealFee,
MinimumBid: params.MinimumBid,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgCreateAuction) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgCreateAuction) Type() string { return "create" }
// ValidateBasic Implements Msg.
func (msg MsgCreateAuction) ValidateBasic() error {
if msg.Signer == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
if msg.CommitsDuration <= 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "commit phase duration invalid.")
}
if msg.RevealsDuration <= 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reveal phase duration invalid.")
}
if !msg.MinimumBid.IsPositive() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "minimum bid should be greater than zero.")
}
return nil
}
// GetSignBytes Implements Msg.
func (msg MsgCreateAuction) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}
// GetSigners Implements Msg.
func (msg MsgCreateAuction) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgCommitBid is the constructor function for MsgCommitBid.
func NewMsgCommitBid(auctionID string, commitHash string, signer sdk.AccAddress) MsgCommitBid {
return MsgCommitBid{
AuctionId: auctionID,
CommitHash: commitHash,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgCommitBid) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgCommitBid) Type() string { return "commit" }
// ValidateBasic Implements Msg.
func (msg MsgCommitBid) ValidateBasic() error {
if msg.Signer == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address.")
}
if msg.AuctionId == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction ID.")
}
if msg.CommitHash == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid commit hash.")
}
return nil
}
// GetSignBytes Implements Msg.
func (msg MsgCommitBid) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}
// GetSigners Implements Msg.
func (msg MsgCommitBid) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgRevealBid is the constructor function for MsgRevealBid.
func NewMsgRevealBid(auctionID string, reveal string, signer sdk.AccAddress) MsgRevealBid {
return MsgRevealBid{
AuctionId: auctionID,
Reveal: reveal,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgRevealBid) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgRevealBid) Type() string { return "reveal" }
// ValidateBasic Implements Msg.
func (msg MsgRevealBid) ValidateBasic() error {
if msg.Signer == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address.")
}
if msg.AuctionId == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction ID.")
}
if msg.Reveal == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid reveal data.")
}
return nil
}
// GetSignBytes Implements Msg.
func (msg MsgRevealBid) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}
// GetSigners Implements Msg.
func (msg MsgRevealBid) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
+173
View File
@@ -0,0 +1,173 @@
package types
import (
"bytes"
"errors"
"fmt"
"strings"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params/types"
)
// Default parameter namespace.
const (
DefaultParamspace = ModuleName
)
var (
DefaultCommitsDuration = 5 * time.Minute
DefaultRevealsDuration = 5 * time.Minute
DefaultCommitFee = sdk.Coin{Amount: sdk.NewInt(10), Denom: sdk.DefaultBondDenom}
DefaultRevealFee = sdk.Coin{Amount: sdk.NewInt(10), Denom: sdk.DefaultBondDenom}
DefaultMinimumBid = sdk.Coin{Amount: sdk.NewInt(1000), Denom: sdk.DefaultBondDenom}
ParamStoreKeyCommitsDuration = []byte("CommitsDuration")
ParamStoreKeyRevealsDuration = []byte("RevealsDuration")
ParamStoreKeyCommitFee = []byte("CommitFee")
ParamStoreKeyRevealFee = []byte("RevealFee")
ParamStoreKeyMinimumBid = []byte("MinimumBid")
)
var _ types.ParamSet = &Params{}
func NewParams() Params {
return DefaultParams()
}
// ParamKeyTable - ParamTable for bond module.
func ParamKeyTable() types.KeyTable {
return types.NewKeyTable().RegisterParamSet(&Params{})
}
// ParamSetPairs - implements params.ParamSet
func (p *Params) ParamSetPairs() types.ParamSetPairs {
return types.ParamSetPairs{
types.NewParamSetPair(ParamStoreKeyCommitsDuration, &p.CommitsDuration, validateCommitsDuration),
types.NewParamSetPair(ParamStoreKeyRevealsDuration, &p.RevealsDuration, validateRevealsDuration),
types.NewParamSetPair(ParamStoreKeyCommitFee, &p.CommitFee, validateCommitFee),
types.NewParamSetPair(ParamStoreKeyRevealFee, &p.RevealFee, validateRevealFee),
types.NewParamSetPair(ParamStoreKeyMinimumBid, &p.MinimumBid, validateMinimumBid),
}
}
// Equal returns a boolean determining if two Params types are identical.
func (p Params) Equal(p2 Params) bool {
bz1 := ModuleCdc.MustMarshalLengthPrefixed(&p)
bz2 := ModuleCdc.MustMarshalLengthPrefixed(&p2)
return bytes.Equal(bz1, bz2)
}
// DefaultParams returns a default set of parameters.
func DefaultParams() Params {
return Params{
CommitsDuration: DefaultCommitsDuration,
RevealsDuration: DefaultRevealsDuration,
CommitFee: DefaultCommitFee,
RevealFee: DefaultRevealFee,
MinimumBid: DefaultMinimumBid,
}
}
// String returns a human readable string representation of the parameters.
func (p Params) String() string {
var sb strings.Builder
sb.WriteString("Params: \n")
sb.WriteString(fmt.Sprintf("CommitsDuration: %s\n", p.CommitsDuration.String()))
sb.WriteString(fmt.Sprintf("RevealsDuration: %s\n", p.RevealsDuration.String()))
sb.WriteString(fmt.Sprintf("CommitFee: %s\n", p.CommitFee.String()))
sb.WriteString(fmt.Sprintf("RevealFee: %s\n", p.RevealFee.String()))
sb.WriteString(fmt.Sprintf("MinimumBid: %s\n", p.MinimumBid.String()))
return sb.String()
}
func validateCommitsDuration(i interface{}) error {
v, ok := i.(time.Duration)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v < 0 {
return errors.New("commits duration cannot be negative")
}
return nil
}
func validateRevealsDuration(i interface{}) error {
v, ok := i.(time.Duration)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v < 0 {
return errors.New("commits duration cannot be negative")
}
return nil
}
func validateCommitFee(i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.Amount.IsNegative() {
return errors.New("commit fee must be positive")
}
return nil
}
func validateRevealFee(i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.Amount.IsNegative() {
return errors.New("reveal fee must be positive")
}
return nil
}
func validateMinimumBid(i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.Amount.IsNegative() {
return errors.New("minimum bid must be positive")
}
return nil
}
// Validate a set of params.
func (p Params) Validate() error {
if err := validateCommitsDuration(p.CommitsDuration); err != nil {
return err
}
if err := validateRevealsDuration(p.RevealsDuration); err != nil {
return err
}
if err := validateCommitFee(p.CommitFee); err != nil {
return err
}
if err := validateRevealFee(p.RevealFee); err != nil {
return err
}
if err := validateMinimumBid(p.MinimumBid); err != nil {
return err
}
return nil
}
+3390
View File
File diff suppressed because it is too large Load Diff
+802
View File
@@ -0,0 +1,802 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: vulcanize/auction/v1beta1/query.proto
/*
Package types is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package types
import (
"context"
"io"
"net/http"
"github.com/golang/protobuf/descriptor"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/status"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = descriptor.ForMessage
var (
filter_Query_Auctions_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_Query_Auctions_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Auctions_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.Auctions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_Auctions_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Auctions_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.Auctions(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_GetAuction_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.GetAuction(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetAuction_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.GetAuction(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_GetBid_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BidRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auction_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
}
protoReq.AuctionId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
}
val, ok = pathParams["bidder"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder")
}
protoReq.Bidder, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder", err)
}
msg, err := client.GetBid(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetBid_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BidRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auction_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
}
protoReq.AuctionId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
}
val, ok = pathParams["bidder"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder")
}
protoReq.Bidder, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder", err)
}
msg, err := server.GetBid(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_GetBids_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BidsRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auction_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
}
protoReq.AuctionId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
}
msg, err := client.GetBids(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetBids_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BidsRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["auction_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auction_id")
}
protoReq.AuctionId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auction_id", err)
}
msg, err := server.GetBids(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_AuctionsByBidder_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsByBidderRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["bidder_address"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder_address")
}
protoReq.BidderAddress, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder_address", err)
}
msg, err := client.AuctionsByBidder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_AuctionsByBidder_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsByBidderRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["bidder_address"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bidder_address")
}
protoReq.BidderAddress, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bidder_address", err)
}
msg, err := server.AuctionsByBidder(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_AuctionsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner_address"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner_address")
}
protoReq.OwnerAddress, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner_address", err)
}
msg, err := client.AuctionsByOwner(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_AuctionsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuctionsByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner_address"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner_address")
}
protoReq.OwnerAddress, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner_address", err)
}
msg, err := server.AuctionsByOwner(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_QueryParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryParamsRequest
var metadata runtime.ServerMetadata
msg, err := client.QueryParams(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_QueryParams_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryParamsRequest
var metadata runtime.ServerMetadata
msg, err := server.QueryParams(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BalanceRequest
var metadata runtime.ServerMetadata
msg, err := client.Balance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BalanceRequest
var metadata runtime.ServerMetadata
msg, err := server.Balance(ctx, &protoReq)
return msg, metadata, err
}
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Auctions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_Auctions_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Auctions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetAuction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetAuction_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetAuction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBid_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetBid_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBid_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBids_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetBids_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBids_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_AuctionsByBidder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_AuctionsByBidder_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_AuctionsByBidder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_AuctionsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_AuctionsByOwner_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_AuctionsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_QueryParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_QueryParams_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_QueryParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_Balance_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterQueryHandler(ctx, mux, conn)
}
// RegisterQueryHandler registers the http handlers for service Query to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
}
// RegisterQueryHandlerClient registers the http handlers for service Query
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "QueryClient" to call the correct interceptors.
func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
mux.Handle("GET", pattern_Query_Auctions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_Auctions_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Auctions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetAuction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetAuction_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetAuction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBid_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetBid_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBid_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBids_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetBids_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBids_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_AuctionsByBidder_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_AuctionsByBidder_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_AuctionsByBidder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_AuctionsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_AuctionsByOwner_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_AuctionsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_QueryParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_QueryParams_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_QueryParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_Balance_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_Query_Auctions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "auctions"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetAuction_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "auctions", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetBid_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"vulcanize", "auction", "v1beta1", "bids", "auction_id", "bidder"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetBids_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "bids", "auction_id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_AuctionsByBidder_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "by-bidder", "bidder_address"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_AuctionsByOwner_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "auction", "v1beta1", "by-owner", "owner_address"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_QueryParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_Balance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "auction", "v1beta1", "balance"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (
forward_Query_Auctions_0 = runtime.ForwardResponseMessage
forward_Query_GetAuction_0 = runtime.ForwardResponseMessage
forward_Query_GetBid_0 = runtime.ForwardResponseMessage
forward_Query_GetBids_0 = runtime.ForwardResponseMessage
forward_Query_AuctionsByBidder_0 = runtime.ForwardResponseMessage
forward_Query_AuctionsByOwner_0 = runtime.ForwardResponseMessage
forward_Query_QueryParams_0 = runtime.ForwardResponseMessage
forward_Query_Balance_0 = runtime.ForwardResponseMessage
)
+1777
View File
File diff suppressed because it is too large Load Diff
+65
View File
@@ -0,0 +1,65 @@
package types
import (
"crypto/sha256"
"encoding/hex"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Auction status values.
const (
// Auction is in commit phase.
AuctionStatusCommitPhase = "commit"
// Auction is in reveal phase.
AuctionStatusRevealPhase = "reveal"
// Auction has ended (no reveals allowed).
AuctionStatusExpired = "expired"
// Auction has completed (winner selected).
AuctionStatusCompleted = "completed"
)
// Bid status values.
const (
BidStatusCommitted = "commit"
BidStatusRevealed = "reveal"
)
// AuctionID simplifies generation of auction IDs.
type AuctionID struct {
Address sdk.Address
AccNum uint64
Sequence uint64
}
// Generate creates the auction ID.
func (auctionID AuctionID) Generate() string {
hasher := sha256.New()
str := fmt.Sprintf("%s:%d:%d", auctionID.Address.String(), auctionID.AccNum, auctionID.Sequence)
hasher.Write([]byte(str))
return hex.EncodeToString(hasher.Sum(nil))
}
func (auction Auction) GetCreateTime() string {
return string(sdk.FormatTimeBytes(auction.CreateTime))
}
func (auction Auction) GetCommitsEndTime() string {
return string(sdk.FormatTimeBytes(auction.CommitsEndTime))
}
func (auction Auction) GetRevealsEndTime() string {
return string(sdk.FormatTimeBytes(auction.RevealsEndTime))
}
func (bid Bid) GetCommitTime() string {
return string(sdk.FormatTimeBytes(bid.CommitTime))
}
func (bid Bid) GetRevealTime() string {
return string(sdk.FormatTimeBytes(bid.RevealTime))
}
+1943
View File
File diff suppressed because it is too large Load Diff
+196
View File
@@ -0,0 +1,196 @@
# Build chain
```bash
# it will create binary in build folder with `ethermintd`
$ make build
```
# Setup Chain
```bash
./build/chibaclonkd keys add root
./build/chibaclonkd init test-moniker --chain-id ethermint_9000-1
./build/chibaclonkd add-genesis-account $(./build/chibaclonkd keys show root -a) 1000000000000000000aphoton,1000000000000000000stake
./build/chibaclonkd gentx root 1000000000000000000stake --chain-id ethermint_9000-1
./build/chibaclonkd collect-gentxs
./build/chibaclonkd start
```
# Params
```
$ ./build/chibaclonkd q bond params -o json | jq .
{
"params": {
"max_bond_amount": {
"denom": "stake",
"amount": "100000000000"
}
}
}
```
# Create Bond
```
$ ./build/chibaclonkd tx bond create 100aphoton --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgCreateBond","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"100"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: C6D362E11D4C9FB06D620F3CCAF363A69A074297A00E9CAECBDA5BE1CC302EB8
```
# Refill Bond
```
$ ./build/chibaclonkd tx bond refill c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 1000aphoton --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgRefillBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"1000"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 025B04E2C923EFE2299CD171B40829CB1FE4D1A69DA7563C64AAC3D5C27BDFC9
```
# Withdraw from bond
```
$ ./build/chibaclonkd tx bond withdraw c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 1000aphoton --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgWithdrawBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk","coins":[{"denom":"aphoton","amount":"1000"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 7C5E2FE674577CD6BFFF9F92FCCBC61EDFE8F1A00CE29AC84D58FB8F013D2F03
```
# List Bond
```
$ ./build/chibaclonkd q bond list -o json | jq .
{
"bonds": [
{
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
"balance": [
{
"denom": "aphoton",
"amount": "100"
}
]
}
],
"pagination": null
}
```
# Get Bond by Id
```
$ ./build/chibaclonkd q bond get c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 -o json | jq .
{
"bond": {
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
"balance": [
{
"denom": "aphoton",
"amount": "100"
}
]
}
}
```
# Get Bond Module Balance
```
$ ./build/chibaclonkd q bond balance -o json | jq .
{
"balance": [
{
"denom": "aphoton",
"amount": "100"
}
]
}
```
# Get Bonds By Owner
```
$ ./build/chibaclonkd q bond by-owner ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk -o json | jq .
{
"bonds": [
{
"id": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
"owner": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
"balance": [
{
"denom": "aphoton",
"amount": "100"
}
]
}
],
"pagination": null
}
```
# Cancel the bond
```
$ ./build/chibaclonkd tx bond cancel c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 --from root --chain-id $(./build/chibaclonkd status | jq .NodeInfo.network -r)
{"body":{"messages":[{"@type":"/vulcanize.bond.v1beta1.MsgCancelBond","id":"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 06440D0B35A862E3A6783E147F0E1CDD3374870DAE07E471D465E2830DAF7044
```
Note : After the bond create and withdraw bond and cancel bond , account amount needs change as per module
```
$ ./build/chibaclonkd q bank balances $(./build/chibaclonkd keys show root -a) -o json | jq .
{
"balances": [
{
"denom": "aphoton",
"amount": "1000000000000000000"
}
],
"pagination": {
"next_key": null,
"total": "0"
}
}
```
+17
View File
@@ -0,0 +1,17 @@
package bond
import (
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/bond/keeper"
)
// BeginBlocker will persist the current header and validator set as a historical entry
// and prune the oldest entry based on the HistoricalEntries parameter
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
}
// EndBlocker Called every block, update validator set
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
+203
View File
@@ -0,0 +1,203 @@
package cli
import (
"fmt"
"strings"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
"github.com/spf13/cobra"
"github.com/tharsis/ethermint/x/bond/types"
)
// GetQueryCmd returns the cli query commands for this module
func GetQueryCmd() *cobra.Command {
bondQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the bond module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
bondQueryCmd.AddCommand(
GetQueryParamsCmd(),
GetQueryBondLists(),
GetBondByIdCmd(),
GetBondListByOwnerCmd(),
GetBondModuleBalanceCmd(),
)
return bondQueryCmd
}
// GetQueryParamsCmd implements the params query command.
func GetQueryParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Args: cobra.NoArgs,
Short: "Query the current bond parameters information.",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values set as bond parameters.
Example:
$ %s query %s params
`,
version.AppName, types.ModuleName,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetQueryBondLists implements the bond lists query command.
func GetQueryBondLists() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List bonds.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get bond list .
Example:
$ %s query %s list
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Bonds(cmd.Context(), &types.QueryGetBondsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetBondByIdCmd implements the bond info by id query command.
func GetBondByIdCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "get [bond Id]",
Short: "Get bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get bond info by bond id .
Example:
$ %s query bond get {BOND ID}
`,
version.AppName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
id := args[0]
res, err := queryClient.GetBondById(cmd.Context(), &types.QueryGetBondByIdRequest{Id: id})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetBondListByOwnerCmd queries the bond list by owner.
func GetBondListByOwnerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "by-owner [address]",
Short: "Query bonds by owner.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get bond list by owner.
Example:
$ %s query %s query-by-owner [address]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
owner := args[0]
res, err := queryClient.GetBondsByOwner(cmd.Context(), &types.QueryGetBondsByOwnerRequest{Owner: owner})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetBondModuleBalanceCmd queries the bond module account balance.
func GetBondModuleBalanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "Get bond module account balance.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get bond module balance.
Example:
$ %s query %s balance
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetBondsModuleBalance(cmd.Context(), &types.QueryGetBondModuleBalanceRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
+125
View File
@@ -0,0 +1,125 @@
package cli
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/tharsis/ethermint/server/flags"
"github.com/tharsis/ethermint/x/bond/types"
)
// NewTxCmd returns a root CLI command handler for all x/bond transaction commands.
func NewTxCmd() *cobra.Command {
bondTxCmd := &cobra.Command{
Use: types.ModuleName,
Short: "bond transaction subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
bondTxCmd.AddCommand(
NewCreateBondCmd(),
RefillBondCmd(),
WithdrawBondCmd(),
CancelBondCmd(),
)
return bondTxCmd
}
// NewCreateBondCmd is the CLI command for creating a bond.
func NewCreateBondCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create [amount]",
Short: "Create bond.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
coin, err := sdk.ParseCoinNormalized(args[0])
if err != nil {
return err
}
msg := types.NewMsgCreateBond(sdk.NewCoins(coin), clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// RefillBondCmd is the CLI command for creating a bond.
func RefillBondCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "refill [bond Id] [amount]",
Short: "Refill bond.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
bondId := args[0]
coin, err := sdk.ParseCoinNormalized(args[1])
if err != nil {
return err
}
msg := types.NewMsgRefillBond(bondId, coin, clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// WithdrawBondCmd is the CLI command for withdrawing funds from a bond.
func WithdrawBondCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "withdraw [bond Id] [amount]",
Short: "Withdraw amount from bond.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
bondId := args[0]
coin, err := sdk.ParseCoinNormalized(args[1])
if err != nil {
return err
}
msg := types.NewMsgWithdrawBond(bondId, coin, clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// CancelBondCmd is the CLI command for cancelling a bond.
func CancelBondCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "cancel [bond Id]",
Short: "cancel bond.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
bondId := args[0]
msg := types.NewMsgCancelBond(bondId, clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
+14
View File
@@ -0,0 +1,14 @@
package testutil
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/tharsis/ethermint/testutil/network"
)
func TestIntegrationTestSuite(t *testing.T) {
cfg := network.DefaultConfig()
cfg.NumValidators = 1
suite.Run(t, NewIntegrationTestSuite(cfg))
}
+213
View File
@@ -0,0 +1,213 @@
package testutil
import (
"fmt"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/cosmos/cosmos-sdk/types/rest"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/bond/client/cli"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
)
func (s *IntegrationTestSuite) TestGRPCGetBonds() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/bonds", val.APIAddress)
testCases := []struct {
name string
url string
expErr bool
errorMsg string
preRun func()
}{
{
"invalid request with headers",
reqUrl + "asdasdas",
true,
"",
func() {
},
},
{
"valid request",
reqUrl,
false,
"",
func() {
s.createBond()
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
resp, _ := rest.GetRequest(tc.url)
if tc.expErr {
sr.Contains(string(resp), tc.errorMsg)
} else {
var response bondtypes.QueryGetBondsResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetBonds()))
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCGetParams() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/params", val.APIAddress)
resp, err := rest.GetRequest(reqUrl)
s.Require().NoError(err)
var params bondtypes.QueryParamsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &params)
sr.NoError(err)
sr.Equal(params.GetParams().MaxBondAmount, bondtypes.DefaultParams().MaxBondAmount)
}
func (s *IntegrationTestSuite) TestGRPCGetBondsByOwner() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/bond/v1beta1/by-owner/%s"
testCases := []struct {
name string
url string
expErr bool
preRun func()
}{
{
"empty list",
fmt.Sprintf(reqUrl, "asdasd"),
true,
func() {
},
},
{
"valid request",
fmt.Sprintf(reqUrl, s.accountAddress),
false,
func() {
s.createBond()
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expErr {
tc.preRun()
}
resp, err := rest.GetRequest(tc.url)
s.Require().NoError(err)
var bonds bondtypes.QueryGetBondsByOwnerResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
sr.NoError(err)
if tc.expErr {
sr.Empty(bonds.GetBonds())
} else {
bondsList := bonds.GetBonds()
sr.NotZero(len(bondsList))
sr.Equal(s.accountAddress, bondsList[0].GetOwner())
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCGetBondById() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/bond/v1beta1/bonds/%s"
testCases := []struct {
name string
url string
expErr bool
preRun func() string
}{
{
"invalid request",
fmt.Sprintf(reqUrl, "asdadad"),
true,
func() string {
return ""
},
},
{
"valid request",
reqUrl,
false,
func() string {
// creating the bond
s.createBond()
// getting the bonds list and returning the bond-id
clientCtx := val.ClientCtx
cmd := cli.GetQueryBondLists()
args := []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var queryResponse bondtypes.QueryGetBondsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
return bond.GetId()
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
var bondId string
if !tc.expErr {
bondId = tc.preRun()
tc.url = fmt.Sprintf(reqUrl, bondId)
}
resp, err := rest.GetRequest(tc.url)
s.Require().NoError(err)
var bonds bondtypes.QueryGetBondByIdResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
if tc.expErr {
sr.Empty(bonds.GetBond().GetId())
} else {
sr.NoError(err)
sr.NotZero(bonds.GetBond().GetId())
sr.Equal(bonds.GetBond().GetId(), bondId)
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCGetBondModuleBalance() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := fmt.Sprintf("%s/vulcanize/bond/v1beta1/balance", val.APIAddress)
// creating the bond
s.createBond()
s.Run("valid request", func() {
resp, err := rest.GetRequest(reqUrl)
sr.NoError(err)
var response bondtypes.QueryGetBondModuleBalanceResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.False(response.GetBalance().IsZero())
})
}
+330
View File
@@ -0,0 +1,330 @@
package testutil
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/testutil/network"
"github.com/tharsis/ethermint/x/bond/client/cli"
"github.com/tharsis/ethermint/x/bond/types"
)
type IntegrationTestSuite struct {
suite.Suite
cfg network.Config
network *network.Network
accountName string
accountAddress string
}
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
return &IntegrationTestSuite{cfg: cfg}
}
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
var err error
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
s.accountName = "accountName"
// setting up random account
s.createAccountWithBalance(s.accountName)
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
val := s.network.Validators[0]
testCases := []struct {
name string
args []string
outputType string
}{
{
"json output",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
"json",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryParamsCmd()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
s.Require().NoError(err)
var response types.QueryParamsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
s.Require().NoError(err)
s.Require().Equal(response.Params.MaxBondAmount, types.DefaultParams().MaxBondAmount)
})
}
}
func (s *IntegrationTestSuite) createAccountWithBalance(accountName string) {
val := s.network.Validators[0]
sr := s.Require()
consPrivKey := ed25519.GenPrivKey()
consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
sr.NoError(err)
sr.NotNil(consPubKeyBz)
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
sr.NoError(err)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
_, err = banktestutil.MsgSendExec(
val.ClientCtx,
val.Address,
newAddr,
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))),
fmt.Sprintf("--%s", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
)
sr.NoError(err)
s.accountAddress = newAddr.String()
}
func (s *IntegrationTestSuite) createBond() {
val := s.network.Validators[0]
sr := s.Require()
createBondCmd := cli.NewCreateBondCmd()
args := []string{
fmt.Sprintf("10%s", s.cfg.BondDenom),
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, createBondCmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
err = s.network.WaitForNextBlock()
sr.NoError(err)
}
func (s *IntegrationTestSuite) TestGetQueryBondLists() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
createBond bool
preRun func()
}{
{
"create and get bond lists",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
func() {
s.createBond()
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
if tc.createBond {
tc.preRun()
}
cmd := cli.GetQueryBondLists()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.NotZero(len(queryResponse.GetBonds()))
})
}
}
func (s *IntegrationTestSuite) TestGetQueryBondById() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
preRun func() string
}{
{
"invalid bond id",
[]string{
fmt.Sprint("not_found_bond_id"),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
true,
func() string {
return ""
},
},
{
"create and get bond by id",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
func() string {
// creating the bond
s.createBond()
// getting the bonds list and returning the bond-id
clientCtx := val.ClientCtx
cmd := cli.GetQueryBondLists()
args := []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
return bond.GetId()
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
if !tc.err {
bondId := tc.preRun()
tc.args = append([]string{bondId}, tc.args...)
}
cmd := cli.GetBondByIdCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
sr.NoError(err)
var queryResponse types.QueryGetBondByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
if tc.err {
sr.Zero(len(queryResponse.GetBond().GetId()))
} else {
sr.NotZero(len(queryResponse.GetBond().GetId()))
sr.Equal(s.accountAddress, queryResponse.GetBond().GetOwner())
}
})
}
}
func (s *IntegrationTestSuite) TestGetQueryBondListsByOwner() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
preRun func()
}{
{
"invalid owner address",
[]string{
fmt.Sprint("not_found_bond_id"),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
true,
func() {
},
},
{
"get bond lists by owner address",
[]string{
fmt.Sprint(s.accountAddress),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
false,
func() {
s.createBond()
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
if !tc.err {
tc.preRun()
}
cmd := cli.GetBondListByOwnerCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
sr.NoError(err)
var queryResponse types.QueryGetBondsByOwnerResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
if tc.err {
sr.Zero(len(queryResponse.GetBonds()))
} else {
sr.NotZero(len(queryResponse.GetBonds()))
sr.Equal(s.accountAddress, queryResponse.GetBonds()[0].GetOwner())
}
})
}
}
func (s *IntegrationTestSuite) TestGetQueryBondModuleBalance() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
preRun func()
}{
{
"get bond module balance",
[]string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
false,
func() {
s.createBond()
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
if !tc.err {
tc.preRun()
}
cmd := cli.GetBondModuleBalanceCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
sr.NoError(err)
var queryResponse types.QueryGetBondModuleBalanceResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.False(queryResponse.GetBalance().IsZero())
})
}
}
+317
View File
@@ -0,0 +1,317 @@
package testutil
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/bond/client/cli"
"github.com/tharsis/ethermint/x/bond/types"
)
func (s *IntegrationTestSuite) TestTxCreateBond() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
}{
{
"without deposit",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
},
{
"create bond",
[]string{
fmt.Sprintf("10%s", s.cfg.BondDenom),
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := cli.NewCreateBondCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.Nil(err)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestTxRefillBond() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
getBondId bool
err bool
}{
{
"without refill amount and bond id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
true,
},
{
"refill bond",
[]string{
fmt.Sprintf("10%s", s.cfg.BondDenom),
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := cli.RefillBondCmd()
if tc.getBondId {
cmd := cli.GetQueryBondLists()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
tc.args = append([]string{bond.GetId()}, tc.args...)
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// checking the balance of bond
cmd := cli.GetBondByIdCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf(tc.args[0]),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.True(queryResponse.GetBond().GetBalance().IsEqual(
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20)))))
}
})
}
}
func (s *IntegrationTestSuite) TestTxWithdrawAmountFromBond() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
getBondId bool
err bool
}{
{
"without withdraw amount and bond id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
true,
},
{
"withdraw amount from bond",
[]string{
fmt.Sprintf("10%s", s.cfg.BondDenom),
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := cli.WithdrawBondCmd()
if tc.getBondId {
cmd := cli.GetQueryBondLists()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
tc.args = append([]string{bond.GetId()}, tc.args...)
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// checking the balance of bond
cmd := cli.GetBondByIdCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf(tc.args[0]),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.True(queryResponse.GetBond().GetBalance().IsEqual(
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)))))
}
})
}
}
func (s *IntegrationTestSuite) TestTxCancelBond() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
getBondId bool
err bool
}{
{
"without bond id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
true,
},
{
"cancel bond",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := cli.CancelBondCmd()
if tc.getBondId {
cmd := cli.GetQueryBondLists()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
tc.args = append([]string{bond.GetId()}, tc.args...)
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// checking the bond exists or not after cancel
cmd := cli.GetBondByIdCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{
fmt.Sprintf(tc.args[0]),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
sr.NoError(err)
var queryResponse types.QueryGetBondByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
sr.Zero(queryResponse.GetBond().GetId())
}
})
}
}
+40
View File
@@ -0,0 +1,40 @@
package bond
import (
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/bond/keeper"
"github.com/tharsis/ethermint/x/bond/types"
)
// InitGenesis initializes genesis state based on exported genesis
func InitGenesis(
ctx sdk.Context,
k keeper.Keeper, data types.GenesisState) []abci.ValidatorUpdate {
k.SetParams(ctx, data.Params)
for _, bond := range data.Bonds {
k.SaveBond(ctx, bond)
}
return []abci.ValidatorUpdate{}
}
// ExportGenesis - output genesis parameters
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) types.GenesisState {
params := keeper.GetParams(ctx)
bonds := keeper.ListBonds(ctx)
return types.GenesisState{Params: params, Bonds: bonds}
}
// ValidateGenesis - validating the genesis data
func ValidateGenesis(data types.GenesisState) error {
err := data.Params.Validate()
if err != nil {
return err
}
return nil
}
+53
View File
@@ -0,0 +1,53 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/tharsis/ethermint/x/bond/types"
)
type Querier struct {
Keeper
}
var _ types.QueryServer = Querier{}
func (q Querier) Bonds(c context.Context, _ *types.QueryGetBondsRequest) (*types.QueryGetBondsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
resp := q.Keeper.ListBonds(ctx)
return &types.QueryGetBondsResponse{Bonds: resp}, nil
}
func (q Querier) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
params := q.Keeper.GetParams(ctx)
return &types.QueryParamsResponse{Params: &params}, nil
}
func (q Querier) GetBondById(c context.Context, req *types.QueryGetBondByIdRequest) (*types.QueryGetBondByIdResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
bondId := req.GetId()
if len(bondId) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bond id required")
}
bond := q.Keeper.GetBond(ctx, req.GetId())
return &types.QueryGetBondByIdResponse{Bond: &bond}, nil
}
func (q Querier) GetBondsByOwner(c context.Context, req *types.QueryGetBondsByOwnerRequest) (*types.QueryGetBondsByOwnerResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
owner := req.GetOwner()
if len(owner) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "owner id required")
}
bonds := q.Keeper.QueryBondsByOwner(ctx, owner)
return &types.QueryGetBondsByOwnerResponse{Bonds: bonds}, nil
}
func (q Querier) GetBondsModuleBalance(c context.Context, _ *types.QueryGetBondModuleBalanceRequest) (*types.QueryGetBondModuleBalanceResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
balance := q.Keeper.GetBondModuleBalances(ctx)
return &types.QueryGetBondModuleBalanceResponse{Balance: balance}, nil
}
+221
View File
@@ -0,0 +1,221 @@
package keeper_test
import (
"context"
"fmt"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/app"
"github.com/tharsis/ethermint/x/bond/types"
)
func (suite *KeeperTestSuite) TestGrpcQueryBondsList() {
grpcClient, ctx, k := suite.queryClient, suite.ctx, suite.app.BondKeeper
testCases := []struct {
msg string
req *types.QueryGetBondsRequest
resp *types.QueryGetBondsResponse
noOfBonds int
createBonds bool
}{
{
"empty request",
&types.QueryGetBondsRequest{},
&types.QueryGetBondsResponse{},
0,
false,
},
{
"Get Bonds",
&types.QueryGetBondsRequest{},
&types.QueryGetBondsResponse{},
1,
true,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createBonds {
account := app.CreateRandomAccounts(1)[0]
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
Denom: sdk.DefaultBondDenom,
Amount: sdk.NewInt(1000),
}))
_, err = k.CreateBond(ctx, account, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))))
suite.Require().NoError(err)
}
resp, _ := grpcClient.Bonds(context.Background(), test.req)
suite.Require().Equal(test.noOfBonds, len(resp.GetBonds()))
})
}
}
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
grpcClient := suite.queryClient
testCases := []struct {
msg string
req *types.QueryParamsRequest
}{
{
"Get Params",
&types.QueryParamsRequest{},
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
resp, _ := grpcClient.Params(context.Background(), test.req)
suite.Require().Equal(resp.GetParams().MaxBondAmount, types.DefaultParams().MaxBondAmount)
})
}
}
func (suite *KeeperTestSuite) TestGrpcQueryBondBondId() {
grpcClient, ctx, k, suiteRequire := suite.queryClient, suite.ctx, suite.app.BondKeeper, suite.Require()
testCases := []struct {
msg string
req *types.QueryGetBondByIdRequest
createBonds bool
errResponse bool
bondId string
}{
{
"empty request",
&types.QueryGetBondByIdRequest{},
false,
true,
"",
},
{
"Get Bond By ID",
&types.QueryGetBondByIdRequest{},
true,
false,
"",
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createBonds {
account := app.CreateRandomAccounts(1)[0]
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
Denom: sdk.DefaultBondDenom,
Amount: sdk.NewInt(1000),
}))
bond, err := k.CreateBond(ctx, account, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))))
suiteRequire.NoError(err)
test.req.Id = bond.Id
}
resp, err := grpcClient.GetBondById(context.Background(), test.req)
if !test.errResponse {
suiteRequire.Nil(err)
suiteRequire.NotNil(resp.GetBond())
suiteRequire.Equal(test.req.Id, resp.GetBond().GetId())
} else {
suiteRequire.NotNil(err)
suiteRequire.Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetBondsByOwner() {
grpcClient, ctx, k, suiteRequire := suite.queryClient, suite.ctx, suite.app.BondKeeper, suite.Require()
testCases := []struct {
msg string
req *types.QueryGetBondsByOwnerRequest
noOfBonds int
createBonds bool
errResponse bool
bondId string
}{
{
"empty request",
&types.QueryGetBondsByOwnerRequest{},
0,
false,
true,
"",
},
{
"Get Bond By Owner",
&types.QueryGetBondsByOwnerRequest{},
1,
true,
false,
"",
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createBonds {
account := app.CreateRandomAccounts(1)[0]
_ = simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
Denom: sdk.DefaultBondDenom,
Amount: sdk.NewInt(1000),
}))
_, err := k.CreateBond(ctx, account, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))))
suiteRequire.NoError(err)
test.req.Owner = account.String()
}
resp, err := grpcClient.GetBondsByOwner(context.Background(), test.req)
if !test.errResponse {
suiteRequire.Nil(err)
suiteRequire.NotNil(resp.GetBonds())
suiteRequire.Equal(test.noOfBonds, len(resp.GetBonds()))
} else {
suiteRequire.NotNil(err)
suiteRequire.Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetModuleBalance() {
grpcClient, ctx, k, suiteRequire := suite.queryClient, suite.ctx, suite.app.BondKeeper, suite.Require()
testCases := []struct {
msg string
req *types.QueryGetBondModuleBalanceRequest
noOfBonds int
createBonds bool
errResponse bool
}{
{
"empty request",
&types.QueryGetBondModuleBalanceRequest{},
0,
true,
false,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createBonds {
account := app.CreateRandomAccounts(1)[0]
_ = simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
Denom: sdk.DefaultBondDenom,
Amount: sdk.NewInt(1000),
}))
_, err := k.CreateBond(ctx, account, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))))
suiteRequire.NoError(err)
}
resp, err := grpcClient.GetBondsModuleBalance(context.Background(), test.req)
if !test.errResponse {
suiteRequire.Nil(err)
suiteRequire.NotNil(resp.GetBalance())
suiteRequire.Equal(resp.GetBalance(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))))
} else {
suiteRequire.NotNil(err)
suiteRequire.Error(err)
}
})
}
}
+37
View File
@@ -0,0 +1,37 @@
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/bond/types"
)
// RegisterInvariants registers all bond invariants
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k))
}
// ModuleAccountInvariant checks that the 'bond' module account balance is non-negative.
func ModuleAccountInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
balances := k.bankKeeper.GetAllBalances(ctx, moduleAddress)
for _, balance := range balances {
if balance.IsNegative() {
return sdk.FormatInvariant(
types.ModuleName,
"module-account",
fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName)),
true
}
}
return "", false
}
}
// AllInvariants runs all invariants of the bonds module.
func AllInvariants(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
return ModuleAccountInvariant(k)(ctx)
}
}
+355
View File
@@ -0,0 +1,355 @@
package keeper
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tharsis/ethermint/x/bond/types"
)
// prefixIDToBondIndex is the prefix for ID -> Bond index in the KVStore.
// Note: This is the primary index in the system.
// Note: Golang doesn't support const arrays.
var prefixIDToBondIndex = []byte{0x00}
// prefixOwnerToBondsIndex is the prefix for the Owner -> [Bond] index in the KVStore.
var prefixOwnerToBondsIndex = []byte{0x01}
// Keeper maintains the link to storage and exposes getter/setter methods for the various parts of the state machine
type Keeper struct {
accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper
// Track bond usage in other cosmos-sdk modules (more like a usage tracker).
usageKeepers []types.BondUsageKeeper
storeKey sdk.StoreKey
cdc codec.BinaryCodec
paramSubspace paramtypes.Subspace
}
// NewKeeper creates new instances of the bond Keeper
func NewKeeper(cdc codec.BinaryCodec, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, usageKeepers []types.BondUsageKeeper, storeKey sdk.StoreKey, ps paramtypes.Subspace) Keeper {
// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}
return Keeper{
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
storeKey: storeKey,
cdc: cdc,
usageKeepers: usageKeepers,
paramSubspace: ps,
}
}
// Generates Bond ID -> Bond index key.
func getBondIndexKey(id string) []byte {
return append(prefixIDToBondIndex, []byte(id)...)
}
// Generates Owner -> Bonds index key.
func getOwnerToBondsIndexKey(owner string, bondID string) []byte {
return append(append(prefixOwnerToBondsIndex, []byte(owner)...), []byte(bondID)...)
}
// BondID simplifies generation of bond IDs.
type BondID struct {
Address sdk.Address
AccNum uint64
Sequence uint64
}
// Generate creates the bond ID.
func (bondID BondID) Generate() string {
hasher := sha256.New()
str := fmt.Sprintf("%s:%d:%d", bondID.Address.String(), bondID.AccNum, bondID.Sequence)
hasher.Write([]byte(str))
return hex.EncodeToString(hasher.Sum(nil))
}
// MatchBonds - get all matching bonds.
func (k Keeper) MatchBonds(ctx sdk.Context, matchFn func(*types.Bond) bool) []*types.Bond {
var bonds []*types.Bond
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, prefixIDToBondIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Bond
k.cdc.MustUnmarshal(bz, &obj)
if matchFn(&obj) {
bonds = append(bonds, &obj)
}
}
}
return bonds
}
// CreateBond creates a new bond.
func (k Keeper) CreateBond(ctx sdk.Context, ownerAddress sdk.AccAddress, coins sdk.Coins) (*types.Bond, error) {
// Check if account has funds.
for _, coin := range coins {
balance := k.bankKeeper.HasBalance(ctx, ownerAddress, coin)
if !balance {
return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "failed to create bond; Insufficient funds")
}
}
// Generate bond ID.
account := k.accountKeeper.GetAccount(ctx, ownerAddress)
bondID := BondID{
Address: ownerAddress,
AccNum: account.GetAccountNumber(),
Sequence: account.GetSequence(),
}.Generate()
maxBondAmount, err := k.getMaxBondAmount(ctx)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid max bond amount.")
}
bond := types.Bond{Id: bondID, Owner: ownerAddress.String(), Balance: coins}
if bond.Balance.IsAnyGT(maxBondAmount) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Max bond amount exceeded.")
}
// Move funds into the bond account module.
err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, ownerAddress, types.ModuleName, bond.Balance)
if err != nil {
return nil, err
}
// Save bond in store.
k.SaveBond(ctx, &bond)
return &bond, nil
}
// SaveBond - saves a bond to the store.
func (k Keeper) SaveBond(ctx sdk.Context, bond *types.Bond) {
store := ctx.KVStore(k.storeKey)
// Bond ID -> Bond index.
store.Set(getBondIndexKey(bond.Id), k.cdc.MustMarshal(bond))
// Owner -> [Bond] index.
store.Set(getOwnerToBondsIndexKey(bond.Owner, bond.Id), []byte{})
}
// HasBond - checks if a bond by the given ID exists.
func (k Keeper) HasBond(ctx sdk.Context, id string) bool {
store := ctx.KVStore(k.storeKey)
return store.Has(getBondIndexKey(id))
}
// GetBond - gets a record from the store.
func (k Keeper) GetBond(ctx sdk.Context, id string) types.Bond {
store := ctx.KVStore(k.storeKey)
bz := store.Get(getBondIndexKey(id))
var obj types.Bond
k.cdc.MustUnmarshal(bz, &obj)
return obj
}
// DeleteBond - deletes the bond.
func (k Keeper) DeleteBond(ctx sdk.Context, bond types.Bond) {
store := ctx.KVStore(k.storeKey)
store.Delete(getBondIndexKey(bond.Id))
store.Delete(getOwnerToBondsIndexKey(bond.Owner, bond.Id))
}
// ListBonds - get all bonds.
func (k Keeper) ListBonds(ctx sdk.Context) []*types.Bond {
var bonds []*types.Bond
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, prefixIDToBondIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Bond
k.cdc.MustUnmarshal(bz, &obj)
bonds = append(bonds, &obj)
}
}
return bonds
}
// QueryBondsByOwner - query bonds by owner.
func (k Keeper) QueryBondsByOwner(ctx sdk.Context, ownerAddress string) []types.Bond {
var bonds []types.Bond
ownerPrefix := append(prefixOwnerToBondsIndex, []byte(ownerAddress)...)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, ownerPrefix)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bondID := itr.Key()[len(ownerPrefix):]
bz := store.Get(append(prefixIDToBondIndex, bondID...))
if bz != nil {
var obj types.Bond
k.cdc.MustUnmarshal(bz, &obj)
bonds = append(bonds, obj)
}
}
return bonds
}
// RefillBond refills an existing bond.
func (k Keeper) RefillBond(ctx sdk.Context, id string, ownerAddress sdk.AccAddress, coins sdk.Coins) (*types.Bond, error) {
if !k.HasBond(ctx, id) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
bond := k.GetBond(ctx, id)
if bond.Owner != ownerAddress.String() {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
// Check if account has funds.
for _, coin := range coins {
if !k.bankKeeper.HasBalance(ctx, ownerAddress, coin) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "Insufficient funds.")
}
}
maxBondAmount, err := k.getMaxBondAmount(ctx)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid max bond amount.")
}
updatedBalance := bond.Balance.Add(coins...)
if updatedBalance.IsAnyGT(maxBondAmount) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Max bond amount exceeded.")
}
// Move funds into the bond account module.
err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, ownerAddress, types.ModuleName, coins)
if err != nil {
return nil, err
}
// Update bond balance and save.
bond.Balance = updatedBalance
k.SaveBond(ctx, &bond)
return &bond, nil
}
// WithdrawBond withdraws funds from a bond.
func (k Keeper) WithdrawBond(ctx sdk.Context, id string, ownerAddress sdk.AccAddress, coins sdk.Coins) (*types.Bond, error) {
if !k.HasBond(ctx, id) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
bond := k.GetBond(ctx, id)
if bond.Owner != ownerAddress.String() {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
updatedBalance, isNeg := bond.Balance.SafeSub(coins)
if isNeg {
return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "Insufficient bond balance.")
}
// Move funds from the bond into the account.
err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, ownerAddress, coins)
if err != nil {
return nil, err
}
// Update bond balance and save.
bond.Balance = updatedBalance
k.SaveBond(ctx, &bond)
return &bond, nil
}
// CancelBond cancels a bond, returning funds to the owner.
func (k Keeper) CancelBond(ctx sdk.Context, id string, ownerAddress sdk.AccAddress) (*types.Bond, error) {
if !k.HasBond(ctx, id) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
bond := k.GetBond(ctx, id)
if bond.Owner != ownerAddress.String() {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
// Check if bond is used in other modules.
for _, usageKeeper := range k.usageKeepers {
if usageKeeper.UsesBond(ctx, id) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("Bond in use by the '%s' module.", usageKeeper.ModuleName()))
}
}
// Move funds from the bond into the account.
err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, ownerAddress, bond.Balance)
if err != nil {
return nil, err
}
k.DeleteBond(ctx, bond)
return &bond, nil
}
func (k Keeper) getMaxBondAmount(ctx sdk.Context) (sdk.Coins, error) {
params := k.GetParams(ctx)
maxBondAmount := params.MaxBondAmount
return sdk.NewCoins(maxBondAmount), nil
}
// GetBondModuleBalances gets the bond module account(s) balances.
func (k Keeper) GetBondModuleBalances(ctx sdk.Context) sdk.Coins {
moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
balances := k.bankKeeper.GetAllBalances(ctx, moduleAddress)
return balances
}
// TransferCoinsToModuleAccount moves funds from the bonds module account to another module account.
func (k Keeper) TransferCoinsToModuleAccount(ctx sdk.Context, id, moduleAccount string, coins sdk.Coins) error {
if !k.HasBond(ctx, id) {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond not found.")
}
bondObj := k.GetBond(ctx, id)
// Deduct rent from bond.
updatedBalance, isNeg := bondObj.Balance.SafeSub(coins)
if isNeg {
// Check if bond has sufficient funds.
return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "Insufficient funds.")
}
// Move funds from bond module to record rent module.
err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, moduleAccount, coins)
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Error transferring funds.")
}
// Update bond balance.
bondObj.Balance = updatedBalance
k.SaveBond(ctx, &bondObj)
return nil
}
+52
View File
@@ -0,0 +1,52 @@
package keeper_test
import (
"testing"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tharsis/ethermint/app"
bondkeeper "github.com/tharsis/ethermint/x/bond/keeper"
"github.com/tharsis/ethermint/x/bond/types"
)
type KeeperTestSuite struct {
suite.Suite
app *app.EthermintApp
ctx sdk.Context
queryClient types.QueryClient
}
func (suite *KeeperTestSuite) SetupTest() {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
querier := bondkeeper.Querier{Keeper: testApp.BondKeeper}
queryHelper := baseapp.NewQueryServerTestHelper(ctx, testApp.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, querier)
queryClient := types.NewQueryClient(queryHelper)
suite.app, suite.ctx, suite.queryClient = testApp, ctx, queryClient
}
func TestParams(t *testing.T) {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
expParams := types.DefaultParams()
params := testApp.BondKeeper.GetParams(ctx)
require.Equal(t, expParams.MaxBondAmount, params.MaxBondAmount)
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
+130
View File
@@ -0,0 +1,130 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/bond/types"
)
type msgServer struct {
Keeper
}
// NewMsgServerImpl returns an implementation of the bond MsgServer interface for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}
var _ types.MsgServer = msgServer{}
func (k msgServer) CreateBond(c context.Context, msg *types.MsgCreateBond) (*types.MsgCreateBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
_, err = k.Keeper.CreateBond(ctx, signerAddress, msg.Coins)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCreateBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Coins.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgCreateBondResponse{}, nil
}
func (k msgServer) RefillBond(c context.Context, msg *types.MsgRefillBond) (*types.MsgRefillBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
_, err = k.Keeper.RefillBond(ctx, msg.Id, signerAddress, msg.Coins)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRefillBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyBondId, msg.Id),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Coins.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgRefillBondResponse{}, nil
}
func (k msgServer) WithdrawBond(c context.Context, msg *types.MsgWithdrawBond) (*types.MsgWithdrawBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
_, err = k.Keeper.WithdrawBond(ctx, msg.Id, signerAddress, msg.Coins)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeWithdrawBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyBondId, msg.Id),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Coins.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgWithdrawBondResponse{}, nil
}
func (k msgServer) CancelBond(c context.Context, msg *types.MsgCancelBond) (*types.MsgCancelBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
_, err = k.Keeper.CancelBond(ctx, msg.Id, signerAddress)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCancelBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyBondId, msg.Id),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgCancelBondResponse{}, nil
}
+23
View File
@@ -0,0 +1,23 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/bond/types"
)
// GetMaxBondAmount max bond amount
func (k Keeper) GetMaxBondAmount(ctx sdk.Context) (res sdk.Coin) {
k.paramSubspace.Get(ctx, types.ParamStoreKeyMaxBondAmount, &res)
return
}
// GetParams - Get all parameter as types.Params.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
getMaxBondAmount := k.GetMaxBondAmount(ctx)
return types.Params{MaxBondAmount: getMaxBondAmount}
}
// SetParams - set the params.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSubspace.SetParamSet(ctx, &params)
}
+135
View File
@@ -0,0 +1,135 @@
package bond
import (
"context"
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/bond/client/cli"
"github.com/tharsis/ethermint/x/bond/keeper"
"github.com/tharsis/ethermint/x/bond/types"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)
// AppModuleBasic defines the basic application module used by the staking module.
type AppModuleBasic struct {
cdc codec.Codec
}
func (b AppModuleBasic) RegisterLegacyAminoCodec(amino *codec.LegacyAmino) {
types.RegisterLegacyAminoCodec(amino)
}
func (b AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
types.RegisterInterfaces(registry)
}
func (b AppModuleBasic) DefaultGenesis(jsonCodec codec.JSONCodec) json.RawMessage {
return jsonCodec.MustMarshalJSON(types.DefaultGenesisState())
}
func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, message json.RawMessage) error {
var data types.GenesisState
if err := cdc.UnmarshalJSON(message, &data); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}
return ValidateGenesis(data)
}
func (b AppModuleBasic) RegisterRESTRoutes(context client.Context, router *mux.Router) {
}
func (b AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, serveMux *runtime.ServeMux) {
err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(clientCtx))
if err != nil {
panic(err)
}
}
func (b AppModuleBasic) GetTxCmd() *cobra.Command {
return cli.NewTxCmd()
}
func (b AppModuleBasic) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd()
}
// Name returns the staking module's name.
func (AppModuleBasic) Name() string {
return types.ModuleName
}
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper
}
// NewAppModule creates a new AppModule Object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{cdc: cdc},
keeper: keeper,
}
}
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate {
var genesisState types.GenesisState
cdc.MustUnmarshalJSON(message, &genesisState)
return InitGenesis(ctx, am.keeper, genesisState)
}
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return cdc.MustMarshalJSON(&gs)
}
func (am AppModule) RegisterInvariants(registry sdk.InvariantRegistry) {
keeper.RegisterInvariants(registry, am.keeper)
}
func (am AppModule) Route() sdk.Route {
return sdk.Route{}
}
func (am AppModule) QuerierRoute() string {
return types.QuerierRoute
}
func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier {
return nil
}
func (am AppModule) RegisterServices(cfg module.Configurator) {
querier := keeper.Querier{Keeper: am.keeper}
types.RegisterQueryServer(cfg.QueryServer(), querier)
msgServer := keeper.NewMsgServerImpl(am.keeper)
types.RegisterMsgServer(cfg.MsgServer(), msgServer)
}
func (am AppModule) ConsensusVersion() uint64 {
return 1
}
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)
}
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
}
+27
View File
@@ -0,0 +1,27 @@
package bond_test
import (
"testing"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/stretchr/testify/require"
abcitypes "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
app "github.com/tharsis/ethermint/app"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
)
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
app := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
app.InitChain(abcitypes.RequestInitChain{
AppStateBytes: []byte("{}"),
ChainId: "test-chain-id",
})
acc := app.AccountKeeper.GetModuleAccount(ctx, bondtypes.ModuleName)
require.NotNil(t, acc)
}
+620
View File
@@ -0,0 +1,620 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: vulcanize/bond/v1beta1/bond.proto
package types
import (
fmt "fmt"
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// Params defines the bond module parameters
type Params struct {
// max_bond_amount is maximum amount to bond
MaxBondAmount types.Coin `protobuf:"bytes,1,opt,name=max_bond_amount,json=maxBondAmount,proto3" json:"max_bond_amount" json:"max_bond_amount" yaml:"max_bond_amount"`
}
func (m *Params) Reset() { *m = Params{} }
func (m *Params) String() string { return proto.CompactTextString(m) }
func (*Params) ProtoMessage() {}
func (*Params) Descriptor() ([]byte, []int) {
return fileDescriptor_ff3ef02fadb61511, []int{0}
}
func (m *Params) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Params.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Params) XXX_Merge(src proto.Message) {
xxx_messageInfo_Params.Merge(m, src)
}
func (m *Params) XXX_Size() int {
return m.Size()
}
func (m *Params) XXX_DiscardUnknown() {
xxx_messageInfo_Params.DiscardUnknown(m)
}
var xxx_messageInfo_Params proto.InternalMessageInfo
func (m *Params) GetMaxBondAmount() types.Coin {
if m != nil {
return m.MaxBondAmount
}
return types.Coin{}
}
// Bond represents funds deposited by an account for record rent payments.
type Bond struct {
// id is unique identifier of the bond
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// owner of the bond
Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"`
// balance of the bond
Balance github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=balance,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"balance" json:"balance" yaml:"balance"`
}
func (m *Bond) Reset() { *m = Bond{} }
func (m *Bond) String() string { return proto.CompactTextString(m) }
func (*Bond) ProtoMessage() {}
func (*Bond) Descriptor() ([]byte, []int) {
return fileDescriptor_ff3ef02fadb61511, []int{1}
}
func (m *Bond) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Bond) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Bond.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Bond) XXX_Merge(src proto.Message) {
xxx_messageInfo_Bond.Merge(m, src)
}
func (m *Bond) XXX_Size() int {
return m.Size()
}
func (m *Bond) XXX_DiscardUnknown() {
xxx_messageInfo_Bond.DiscardUnknown(m)
}
var xxx_messageInfo_Bond proto.InternalMessageInfo
func (m *Bond) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Bond) GetOwner() string {
if m != nil {
return m.Owner
}
return ""
}
func (m *Bond) GetBalance() github_com_cosmos_cosmos_sdk_types.Coins {
if m != nil {
return m.Balance
}
return nil
}
func init() {
proto.RegisterType((*Params)(nil), "vulcanize.bond.v1beta1.Params")
proto.RegisterType((*Bond)(nil), "vulcanize.bond.v1beta1.Bond")
}
func init() { proto.RegisterFile("vulcanize/bond/v1beta1/bond.proto", fileDescriptor_ff3ef02fadb61511) }
var fileDescriptor_ff3ef02fadb61511 = []byte{
// 344 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xc1, 0x4e, 0x32, 0x31,
0x14, 0x85, 0xa7, 0xf0, 0xff, 0x18, 0xc7, 0xa8, 0xc9, 0x84, 0x18, 0x24, 0xb1, 0x20, 0x2b, 0x5c,
0x30, 0x0d, 0x1a, 0x37, 0xee, 0x84, 0x17, 0x50, 0x96, 0x6e, 0x48, 0x67, 0xa6, 0x81, 0x2a, 0xed,
0x25, 0xd3, 0x82, 0x83, 0x4b, 0x17, 0xae, 0x7d, 0x0e, 0xf7, 0xbe, 0x03, 0x4b, 0x96, 0xae, 0xd0,
0xc0, 0x1b, 0xf8, 0x04, 0x66, 0xda, 0x19, 0x62, 0x34, 0x71, 0xd5, 0x9e, 0xdb, 0x73, 0xbf, 0x7b,
0xd2, 0xeb, 0x1e, 0x4f, 0x27, 0xa3, 0x90, 0x4a, 0xfe, 0xc0, 0x48, 0x00, 0x32, 0x22, 0xd3, 0x76,
0xc0, 0x34, 0x6d, 0x1b, 0xe1, 0x8f, 0x63, 0xd0, 0xe0, 0x1d, 0x6c, 0x2c, 0xbe, 0xa9, 0x66, 0x96,
0x6a, 0x79, 0x00, 0x03, 0x30, 0x16, 0x92, 0xde, 0xac, 0xbb, 0x8a, 0x43, 0x50, 0x02, 0x14, 0x09,
0xa8, 0x62, 0x1b, 0x5a, 0x08, 0x5c, 0xda, 0xf7, 0xc6, 0x23, 0x72, 0x4b, 0x57, 0x34, 0xa6, 0x42,
0x79, 0x89, 0xbb, 0x2f, 0x68, 0xd2, 0x4f, 0xa1, 0x7d, 0x2a, 0x60, 0x22, 0x75, 0x05, 0xd5, 0x51,
0x73, 0xe7, 0xf4, 0xd0, 0xb7, 0x10, 0x3f, 0x85, 0xe4, 0xf3, 0xfc, 0x2e, 0x70, 0xd9, 0x39, 0x9f,
0x2f, 0x6b, 0xce, 0xe7, 0xb2, 0xd6, 0xba, 0x55, 0x20, 0x2f, 0x1a, 0x3f, 0xfa, 0x1b, 0xf5, 0x19,
0x15, 0xa3, 0xdf, 0xe5, 0xde, 0xae, 0xa0, 0x49, 0x07, 0x64, 0x74, 0x69, 0xf5, 0x2b, 0x72, 0xff,
0xa5, 0xd2, 0xdb, 0x73, 0x0b, 0x3c, 0x32, 0x53, 0xb7, 0x7b, 0x05, 0x1e, 0x79, 0x65, 0xf7, 0x3f,
0xdc, 0x4b, 0x16, 0x57, 0x0a, 0xa6, 0x64, 0x85, 0xf7, 0x84, 0xdc, 0xad, 0x80, 0x8e, 0xa8, 0x0c,
0x59, 0xa5, 0x58, 0x2f, 0xfe, 0x9d, 0xf0, 0x3a, 0x4b, 0x78, 0x64, 0x13, 0x66, 0x7d, 0x79, 0xb2,
0x5c, 0xbe, 0xbc, 0xd7, 0x9a, 0x03, 0xae, 0x87, 0x93, 0xc0, 0x0f, 0x41, 0x90, 0xec, 0xd3, 0xec,
0xd1, 0x52, 0xd1, 0x1d, 0xd1, 0xb3, 0x31, 0x53, 0x86, 0xa8, 0x7a, 0xf9, 0xf0, 0x4e, 0x77, 0xbe,
0xc2, 0x68, 0xb1, 0xc2, 0xe8, 0x63, 0x85, 0xd1, 0xf3, 0x1a, 0x3b, 0x8b, 0x35, 0x76, 0xde, 0xd6,
0xd8, 0xb9, 0x39, 0xf9, 0x06, 0xd3, 0x43, 0x1a, 0x2b, 0xae, 0x08, 0xd3, 0x43, 0x16, 0x0b, 0x2e,
0x35, 0x49, 0xec, 0x72, 0x0d, 0x33, 0x28, 0x99, 0x45, 0x9c, 0x7d, 0x05, 0x00, 0x00, 0xff, 0xff,
0x45, 0xf7, 0x5e, 0x13, 0xfb, 0x01, 0x00, 0x00,
}
func (m *Params) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Params) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size, err := m.MaxBondAmount.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintBond(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func (m *Bond) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Bond) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Bond) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Balance) > 0 {
for iNdEx := len(m.Balance) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Balance[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintBond(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
if len(m.Owner) > 0 {
i -= len(m.Owner)
copy(dAtA[i:], m.Owner)
i = encodeVarintBond(dAtA, i, uint64(len(m.Owner)))
i--
dAtA[i] = 0x12
}
if len(m.Id) > 0 {
i -= len(m.Id)
copy(dAtA[i:], m.Id)
i = encodeVarintBond(dAtA, i, uint64(len(m.Id)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintBond(dAtA []byte, offset int, v uint64) int {
offset -= sovBond(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Params) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.MaxBondAmount.Size()
n += 1 + l + sovBond(uint64(l))
return n
}
func (m *Bond) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Id)
if l > 0 {
n += 1 + l + sovBond(uint64(l))
}
l = len(m.Owner)
if l > 0 {
n += 1 + l + sovBond(uint64(l))
}
if len(m.Balance) > 0 {
for _, e := range m.Balance {
l = e.Size()
n += 1 + l + sovBond(uint64(l))
}
}
return n
}
func sovBond(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozBond(x uint64) (n int) {
return sovBond(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Params) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Params: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MaxBondAmount", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthBond
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthBond
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.MaxBondAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipBond(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthBond
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Bond) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Bond: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Bond: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthBond
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthBond
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Id = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthBond
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthBond
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Owner = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBond
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthBond
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthBond
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Balance = append(m.Balance, types.Coin{})
if err := m.Balance[len(m.Balance)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipBond(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthBond
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipBond(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowBond
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowBond
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowBond
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthBond
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupBond
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthBond
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthBond = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowBond = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupBond = fmt.Errorf("proto: unexpected end of group")
)
+39
View File
@@ -0,0 +1,39 @@
package types
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/msgservice"
)
// RegisterLegacyAminoCodec registers the necessary x/bond interfaces and concrete types
// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgCreateBond{}, "bond/MsgCreateBond", nil)
cdc.RegisterConcrete(&MsgRefillBond{}, "bond/MsgRefillBond", nil)
cdc.RegisterConcrete(&MsgWithdrawBond{}, "bond/MsgWithdrawBond", nil)
cdc.RegisterConcrete(&MsgCancelBond{}, "bond/MsgCancelBond", nil)
}
func RegisterInterfaces(registry types.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgCreateBond{},
&MsgRefillBond{},
&MsgCancelBond{},
&MsgWithdrawBond{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
var (
amino = codec.NewLegacyAmino()
ModuleCdc = codec.NewAminoCodec(amino)
)
func init() {
RegisterLegacyAminoCodec(amino)
cryptocodec.RegisterCrypto(amino)
amino.Seal()
}
+15
View File
@@ -0,0 +1,15 @@
package types
// bond module event types
const (
EventTypeCreateBond = "crate_bond"
EventTypeRefillBond = "refill_bond"
EventTypeCancelBond = "cancel_bond"
EventTypeWithdrawBond = "withdraw_bond"
AttributeKeySigner = "signer"
AttributeKeyAmount = "amount"
AttributeKeyBondId = "bond_id"
AttributeValueCategory = ModuleName
)
+12
View File
@@ -0,0 +1,12 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// BondUsageKeeper keep track of bond usage in other modules.
// Used to, for example, prevent deletion of a bond that's in use.
type BondUsageKeeper interface {
ModuleName() string
UsesBond(ctx sdk.Context, bondId string) bool
}
+9
View File
@@ -0,0 +1,9 @@
package types
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
// chain config values.
func DefaultGenesisState() *GenesisState {
return &GenesisState{
Params: DefaultParams(),
}
}
+391
View File
@@ -0,0 +1,391 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: vulcanize/bond/v1beta1/genesis.proto
package types
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the bond module's genesis state.
type GenesisState struct {
// params defines all the parameters of the module.
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// bonds defines all the bonds
Bonds []*Bond `protobuf:"bytes,2,rep,name=bonds,proto3" json:"bonds,omitempty" json:"bonds" yaml:"bonds"`
}
func (m *GenesisState) Reset() { *m = GenesisState{} }
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
func (*GenesisState) ProtoMessage() {}
func (*GenesisState) Descriptor() ([]byte, []int) {
return fileDescriptor_f9582eb9edb1dcdf, []int{0}
}
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GenesisState) XXX_Merge(src proto.Message) {
xxx_messageInfo_GenesisState.Merge(m, src)
}
func (m *GenesisState) XXX_Size() int {
return m.Size()
}
func (m *GenesisState) XXX_DiscardUnknown() {
xxx_messageInfo_GenesisState.DiscardUnknown(m)
}
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
func (m *GenesisState) GetParams() Params {
if m != nil {
return m.Params
}
return Params{}
}
func (m *GenesisState) GetBonds() []*Bond {
if m != nil {
return m.Bonds
}
return nil
}
func init() {
proto.RegisterType((*GenesisState)(nil), "vulcanize.bond.v1beta1.GenesisState")
}
func init() {
proto.RegisterFile("vulcanize/bond/v1beta1/genesis.proto", fileDescriptor_f9582eb9edb1dcdf)
}
var fileDescriptor_f9582eb9edb1dcdf = []byte{
// 259 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x29, 0x2b, 0xcd, 0x49,
0x4e, 0xcc, 0xcb, 0xac, 0x4a, 0xd5, 0x4f, 0xca, 0xcf, 0x4b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d,
0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
0x17, 0x12, 0x83, 0xab, 0xd2, 0x03, 0xa9, 0xd2, 0x83, 0xaa, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf,
0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0x14, 0x71, 0x98, 0x09, 0xd6, 0x0a, 0x56, 0xa2,
0x34, 0x9f, 0x91, 0x8b, 0xc7, 0x1d, 0x62, 0x45, 0x70, 0x49, 0x62, 0x49, 0xaa, 0x90, 0x0d, 0x17,
0x5b, 0x41, 0x62, 0x51, 0x62, 0x6e, 0xb1, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0x9c, 0x1e,
0x76, 0x2b, 0xf5, 0x02, 0xc0, 0xaa, 0x9c, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, 0x82, 0xea, 0x11,
0x0a, 0xe4, 0x62, 0x05, 0x29, 0x2a, 0x96, 0x60, 0x52, 0x60, 0xd6, 0xe0, 0x36, 0x92, 0xc1, 0xa5,
0xd9, 0x29, 0x3f, 0x2f, 0xc5, 0x49, 0xf6, 0xd3, 0x3d, 0x79, 0xc9, 0xac, 0xe2, 0xfc, 0x3c, 0x2b,
0x25, 0xb0, 0x26, 0x25, 0x85, 0xca, 0xc4, 0xdc, 0x1c, 0x18, 0x27, 0x08, 0x62, 0x92, 0x93, 0xf3,
0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c,
0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94,
0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x97, 0x64, 0x24, 0x16, 0x15, 0x67, 0x16, 0xeb, 0xa7, 0x96,
0x64, 0xa4, 0x16, 0xe5, 0x66, 0xe6, 0x95, 0xe8, 0x57, 0x40, 0xfc, 0x5c, 0x52, 0x59, 0x90, 0x5a,
0x9c, 0xc4, 0x06, 0xf6, 0xad, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xe9, 0x23, 0x03, 0x66,
0x01, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Bonds) > 0 {
for iNdEx := len(m.Bonds) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Bonds[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
{
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.Params.Size()
n += 1 + l + sovGenesis(uint64(l))
if len(m.Bonds) > 0 {
for _, e := range m.Bonds {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Bonds", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Bonds = append(m.Bonds, &Bond{})
if err := m.Bonds[len(m.Bonds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)
+15
View File
@@ -0,0 +1,15 @@
package types
const (
// ModuleName is the name of the staking module
ModuleName = "bond"
// StoreKey is the string store representation
StoreKey = ModuleName
// QuerierRoute is the querier route for the staking module
QuerierRoute = ModuleName
// RouterKey is the msg router key for the staking module
RouterKey = ModuleName
)
+161
View File
@@ -0,0 +1,161 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
_ sdk.Msg = &MsgCreateBond{}
_ sdk.Msg = &MsgRefillBond{}
_ sdk.Msg = &MsgWithdrawBond{}
_ sdk.Msg = &MsgCancelBond{}
)
// NewMsgCreateBond is the constructor function for MsgCreateBond.
func NewMsgCreateBond(coins sdk.Coins, signer sdk.AccAddress) MsgCreateBond {
return MsgCreateBond{
Coins: coins,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgCreateBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgCreateBond) Type() string { return "create" }
func (msg MsgCreateBond) ValidateBasic() error {
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
if len(msg.Coins) == 0 || !msg.Coins.IsValid() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.")
}
return nil
}
func (msg MsgCreateBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// GetSignBytes gets the sign bytes for the msg MsgCreateBond
func (msg MsgCreateBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// NewMsgRefillBond is the constructor function for MsgRefillBond.
func NewMsgRefillBond(id string, amount sdk.Coin, signer sdk.AccAddress) MsgRefillBond {
return MsgRefillBond{
Id: id,
Coins: sdk.NewCoins(amount),
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgRefillBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgRefillBond) Type() string { return "refill" }
func (msg MsgRefillBond) ValidateBasic() error {
if len(msg.Id) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, msg.Id)
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
if len(msg.Coins) == 0 || !msg.Coins.IsValid() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.")
}
return nil
}
func (msg MsgRefillBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// GetSignBytes gets the sign bytes for the msg MsgCreateBond
func (msg MsgRefillBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// NewMsgWithdrawBond is the constructor function for NewMsgWithdrawBond.
func NewMsgWithdrawBond(id string, amount sdk.Coin, signer sdk.AccAddress) MsgWithdrawBond {
return MsgWithdrawBond{
Id: id,
Coins: sdk.NewCoins(amount),
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgWithdrawBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgWithdrawBond) Type() string { return "withdraw" }
func (msg MsgWithdrawBond) ValidateBasic() error {
if len(msg.Id) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, msg.Id)
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
if len(msg.Coins) == 0 || !msg.Coins.IsValid() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.")
}
return nil
}
func (msg MsgWithdrawBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// GetSignBytes gets the sign bytes for the msg MsgCreateBond
func (msg MsgWithdrawBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// NewMsgCancelBond is the constructor function for CalcelBond.
func NewMsgCancelBond(id string, signer sdk.AccAddress) MsgCancelBond {
return MsgCancelBond{
Id: id,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgCancelBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgCancelBond) Type() string { return "cancel" }
func (msg MsgCancelBond) ValidateBasic() error {
if len(msg.Id) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, msg.Id)
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
return nil
}
func (msg MsgCancelBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// GetSignBytes gets the sign bytes for the msg MsgCreateBond
func (msg MsgCancelBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
+64
View File
@@ -0,0 +1,64 @@
package types
import (
"errors"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
var _ paramtypes.ParamSet = &Params{}
// Default parameter values.
var (
DefaultMaxBondAmountTokens = sdk.NewInt(100000000000)
)
// Parameter keys
var (
ParamStoreKeyMaxBondAmount = []byte("MaxBondAmount")
)
// ParamKeyTable ParamTable for staking module
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}
func NewParams(maxBondAmount sdk.Coin) Params {
return Params{MaxBondAmount: maxBondAmount}
}
// DefaultParams returns default evm parameters
// ExtraEIPs is empty to prevent overriding the latest hard fork instruction set
func DefaultParams() Params {
return NewParams(sdk.NewCoin(sdk.DefaultBondDenom, DefaultMaxBondAmountTokens))
}
// ParamSetPairs returns the parameter set pairs.
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(ParamStoreKeyMaxBondAmount, &p.MaxBondAmount, validateMaxBondAmount),
}
}
func validateMaxBondAmount(i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.Amount.IsNegative() {
return errors.New("max bond amount must be positive")
}
return nil
}
// Validate checks that the parameters have valid values.
func (p Params) Validate() error {
if err := validateMaxBondAmount(p.MaxBondAmount); err != nil {
return err
}
return nil
}
+2280
View File
File diff suppressed because it is too large Load Diff
+504
View File
@@ -0,0 +1,504 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: vulcanize/bond/v1beta1/query.proto
/*
Package types is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package types
import (
"context"
"io"
"net/http"
"github.com/golang/protobuf/descriptor"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/status"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = descriptor.ForMessage
func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryParamsRequest
var metadata runtime.ServerMetadata
msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryParamsRequest
var metadata runtime.ServerMetadata
msg, err := server.Params(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_Query_Bonds_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_Query_Bonds_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Bonds_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.Bonds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_Bonds_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Bonds_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.Bonds(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_GetBondById_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondByIdRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.GetBondById(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetBondById_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondByIdRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.GetBondById(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_Query_GetBondsByOwner_0 = &utilities.DoubleArray{Encoding: map[string]int{"owner": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_Query_GetBondsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondsByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner")
}
protoReq.Owner, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GetBondsByOwner_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.GetBondsByOwner(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetBondsByOwner_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondsByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner")
}
protoReq.Owner, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GetBondsByOwner_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.GetBondsByOwner(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_GetBondsModuleBalance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondModuleBalanceRequest
var metadata runtime.ServerMetadata
msg, err := client.GetBondsModuleBalance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_GetBondsModuleBalance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryGetBondModuleBalanceRequest
var metadata runtime.ServerMetadata
msg, err := server.GetBondsModuleBalance(ctx, &protoReq)
return msg, metadata, err
}
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Bonds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_Bonds_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Bonds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondById_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetBondById_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondById_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetBondsByOwner_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondsModuleBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_GetBondsModuleBalance_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondsModuleBalance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterQueryHandler(ctx, mux, conn)
}
// RegisterQueryHandler registers the http handlers for service Query to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
}
// RegisterQueryHandlerClient registers the http handlers for service Query
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "QueryClient" to call the correct interceptors.
func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Bonds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_Bonds_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_Bonds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondById_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetBondById_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondById_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondsByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetBondsByOwner_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondsByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_GetBondsModuleBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_GetBondsModuleBalance_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_GetBondsModuleBalance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "bond", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_Bonds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "bond", "v1beta1", "bonds"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetBondById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "bond", "v1beta1", "bonds", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetBondsByOwner_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"vulcanize", "bond", "v1beta1", "by-owner", "owner"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_GetBondsModuleBalance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"vulcanize", "bond", "v1beta1", "balance"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (
forward_Query_Params_0 = runtime.ForwardResponseMessage
forward_Query_Bonds_0 = runtime.ForwardResponseMessage
forward_Query_GetBondById_0 = runtime.ForwardResponseMessage
forward_Query_GetBondsByOwner_0 = runtime.ForwardResponseMessage
forward_Query_GetBondsModuleBalance_0 = runtime.ForwardResponseMessage
)
+1921
View File
File diff suppressed because it is too large Load Diff
+340
View File
@@ -0,0 +1,340 @@
# Build chain
```bash
# it will create binary in build folder with `ethermintd`
$ make build
```
# Setup Chain
```bash
./build/chibaclonkd keys add root
./build/chibaclonkd init test-moniker --chain-id ethermint_9000-1
./build/chibaclonkd add-genesis-account $(./build/chibaclonkd keys show root -a) 1000000000000000000aphoton,1000000000000000000stake
./build/chibaclonkd gentx root 1000000000000000000stake --chain-id ethermint_9000-1
./build/chibaclonkd collect-gentxs
./build/chibaclonkd start
```
## Get Params
```bash
$ ./build/chibaclonkd q nameservice params -o json | jq .
{
"params": {
"record_rent": {
"denom": "stake",
"amount": "1000000"
},
"record_rent_duration": "31536000s",
"authority_rent": {
"denom": "stake",
"amount": "1000000"
},
"authority_rent_duration": "31536000s",
"authority_grace_period": "172800s",
"authority_auction_enabled": false,
"authority_auction_commits_duration": "86400s",
"authority_auction_reveals_duration": "86400s",
"authority_auction_commit_fee": {
"denom": "stake",
"amount": "1000000"
},
"authority_auction_reveal_fee": {
"denom": "stake",
"amount": "1000000"
},
"authority_auction_minimum_bid": {
"denom": "stake",
"amount": "5000000"
}
}
```
## Create (Set) Record
> First you have to Create bond
```bash
$ ./build/chibaclonkd tx nameservice set ~/Desktop/examples/records/example1.yml 95f68b1b862bfd1609b0c9aaf7300287b92fec90ac64027092c3e723af36e83d --from root --chain-id ethermint_9000-1 --yes -o json
{
"height": "0",
"txhash": "BA44ABE1194724694E7CB290F9F3121DB4E63E1A030D95CB84813EEA132CF95F",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "[]",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": ""
}
```
## Get records list
```bash
$ ./build/chibaclonkd q nameservice list -o json | jq
[
{
"id": "bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae",
"bondId": "c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440",
"createTime": "2021-10-04T06:50:06.369025861Z",
"expiryTime": "2022-10-04T06:50:06.369025861Z",
"attributes": {
"attr1": "value1",
"attr2": "value2",
"link1": {
"/": "QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D"
},
"link2": {
"/": "QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9"
}
}
}
]
```
## Get record by id
```bash
$ ./build/chibaclonkd q nameservice get bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae -o json | jq .
{
"record": {
"id": "bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae",
"bond_id": "95f68b1b862bfd1609b0c9aaf7300287b92fec90ac64027092c3e723af36e83d",
"create_time": "2021-09-27T07:23:25.558111606Z",
"expiry_time": "2022-09-27T07:23:25.558111606Z",
"deleted": false,
"owners": [],
"attributes": "eyJhdHRyMSI6InZhbHVlMSIsImF0dHIyIjoidmFsdWUyIiwibGluazEiOnsiLyI6IlFtU251V214cHRKWmRMSnBLUmFyeEJNUzJKdTJvQU5WcmdicjJ4V2JpZTliMkQifSwibGluazIiOnsiLyI6IlFtUDhqVEcxbTlHU0RKTENiZVdoVlNWZ0V6Q1BQd1hSZENSdUp0UTVUejlLYzkifX0="
}
}
```
## Reserve name
```bash
./build/chibaclonkd tx nameservice reserve-name hello --from root --chain-id ethermint_9000-1 --owner $(./build/chibaclonkd key
s show root -a) -y -o json | jq .
{
"height": "0",
"txhash": "7EC19157AC89279DEBE840EA3384FC95D1E2A0931C27746CA42AC23AE285B7ED",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "[]",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": ""
}
```
## Query Whois for name authority
```bash
./build/chibaclonkd q nameservice whois hello -o json | jq .
{
"name_authority": {
"owner_public_key": "Au3hH1tzL1KgZfXfA71jGYSe5RV9Wg95kwhBWs8V+N+h",
"owner_address": "ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk",
"height": "174",
"status": "active",
"auction_id": "",
"bond_id": "",
"expiry_time": "2021-09-29T07:34:36.304545965Z"
}
}
```
## Query the nameservice module balance
```bash
$ ./build/chibaclonkd q nameservice balance -o json | jq .
{
"balances": [
{
"account_name": "record_rent",
"balance": [
{
"denom": "stake",
"amount": "1000000"
}
]
}
]
}
```
## add bond to the authority
```bash
$ ./build/chibaclonkd tx nameservice authority-bond [Authority Name] [Bond ID ] --from root --chain-id ethermint_9000-1 -y -o json | jq .
$ ./build/chibaclonkd tx nameservice authority-bond hello 95f68b1b862bfd1609b0c9aaf7300287b92fec90ac64027092c3e723af36e83d --from root --chain-id ethermint_9000-1 -y -o json | jq .
```
## Query the records by associate bond id
```bash
$ ./build/chibaclonkd q nameservice query-by-bond 95f68b1b862bfd1609b0c9aaf7300287b92fec90ac64027092c3e723af36e83d -o json | jq .
{
"records": [
{
"id": "bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae",
"bond_id": "95f68b1b862bfd1609b0c9aaf7300287b92fec90ac64027092c3e723af36e83d",
"create_time": "2021-09-27T08:25:32.893155609Z",
"expiry_time": "2022-09-27T08:25:32.893155609Z",
"deleted": false,
"owners": [],
"attributes": "eyJhdHRyMSI6InZhbHVlMSIsImF0dHIyIjoidmFsdWUyIiwibGluazEiOnsiLyI6IlFtU251V214cHRKWmRMSnBLUmFyeEJNUzJKdTJvQU5WcmdicjJ4V2JpZTliMkQifSwibGluazIiOnsiLyI6IlFtUDhqVEcxbTlHU0RKTENiZVdoVlNWZ0V6Q1BQd1hSZENSdUp0UTVUejlLYzkifX0="
}
],
"pagination": null
}
```
## dissociate bond from record
```bash
$ ./build/chibaclonkd tx nameservice dissociate-bond bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae --from root --chain-id ethermint_9000-1
{"body":{"messages":[{"@type":"/vulcanize.nameservice.v1beta1.MsgDissociateBond","record_id":"bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae","signer":"ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 7AFEF524CB0D92D6576FC08601A787786E802449888FD8DDAA7635698CC85060
```
## Associate bond with record
```bash
./build/chibaclonkd tx nameservice associate-bond bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 --from root --chain-id ethermint_9000-1 -y -o json | jq .
{
"height": "0",
"txhash": "F75C2BF2FE73668AE1332E1237F924AC549E31E822A56394DE5AC17200B199F9",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "[]",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": ""
}
```
## dissociate-records => remove all record from bond
```bash
$./build/chibaclonkd tx nameservice dissociate-records c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440 --from root --chain-id ethermint_9000-1 -y -o json | jq .
{
"height": "0",
"txhash": "0316F503E5DEA47CB108AE6C7C7FFAF3F71CC56BC22F63CB97322E1BE48B33B9",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "[]",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": ""
}
```
## Renew a record
> When a record is expires , needs to renew record
```bash
$ ./build/chibaclonkd tx nameservice renew-record bafyreih7un2ntk235wshncebus5emlozdhdixrrv675my5umb6fgdergae --from root --chain-id ethermint_9000-1
```
## Set the authority name
```bash
$ ./build/chibaclonkd tx nameservice set-name crn://hello/test test_hello_cid --from root --chain-id ethermint_9000-1 -y -o json | jq .
{
"height": "0",
"txhash": "66A63C73B076EEE9A2F7605354448EDEB161F0115D4D03AF68C01BA28DB97486",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "[]",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": ""
}
```
## Delete the name
```bash
$./build/chibaclonkd tx nameservice delete-name crn://hello/test --from root --chain-id ethermint_9000-1 -y
code: 0
codespace: ""
data: ""
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: A3FF4C46BAC7BD6E54BBB743A49830AE8C6F6FE59282384789CBA323C1FE540C
```
## List of Authorities Expire Queue
```bash
$ ./build/chibaclonkd q nameservice authority-expiry -o json | jq .
{
"authorities": [],
"pagination": null
}
```
## List of Records Expire Queue
```bash
$ ./build/chibaclonkd q nameservice record-expiry -o json | jq .
{
"records": [],
"pagination": null
}
```
+20
View File
@@ -0,0 +1,20 @@
package nameservice
import (
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/nameservice/keeper"
)
// BeginBlocker will persist the current header and validator set as a historical entry
// and prune the oldest entry based on the HistoricalEntries parameter
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
}
// EndBlocker Called every block, update validator set
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
k.ProcessRecordExpiryQueue(ctx)
k.ProcessAuthorityExpiryQueue(ctx)
return []abci.ValidatorUpdate{}
}
+398
View File
@@ -0,0 +1,398 @@
package cli
import (
"encoding/json"
"fmt"
"strings"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
"github.com/spf13/cobra"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// GetQueryCmd returns the cli query commands for this module
func GetQueryCmd() *cobra.Command {
bondQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the nameservice module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
bondQueryCmd.AddCommand(
GetCmdWhoIs(),
GetCmdResolve(),
GetCmdLookupCRN(),
GetRecordExpiryQueue(),
GetAuthorityExpiryQueue(),
GetQueryParamsCmd(),
GetCmdList(),
GetCmdGetResource(),
GetCmdQueryByBond(),
GetCmdBalance(),
GetCmdNames(),
)
return bondQueryCmd
}
// GetCmdWhoIs queries a whois info for a name.
func GetCmdWhoIs() *cobra.Command {
cmd := &cobra.Command{
Use: "whois [name]",
Short: "Get name owner info.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get name owner info.
Example:
$ %s query %s whois [name]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Whois(cmd.Context(), &types.QueryWhoisRequest{Name: args[0]})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdLookupCRN queries naming info for a CRN.
func GetCmdLookupCRN() *cobra.Command {
cmd := &cobra.Command{
Use: "lookup [crn]",
Short: "Get naming info for CRN.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get naming info for CRN.
Example:
$ %s query %s lookup [crn]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.LookupCrn(cmd.Context(), &types.QueryLookupCrn{Crn: args[0]})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetQueryParamsCmd implements the params query command.
func GetQueryParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Args: cobra.NoArgs,
Short: "Query the current bond parameters information.",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values set as bond parameters.
Example:
$ %s query %s params
`,
version.AppName, types.ModuleName,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdList queries all records.
func GetCmdList() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List records.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get the records.
Example:
$ %s query %s list
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ListRecords(cmd.Context(), &types.QueryListRecordsRequest{})
if err != nil {
return err
}
recordsList := res.GetRecords()
records := make([]types.RecordType, len(recordsList))
for i, record := range res.GetRecords() {
records[i] = record.ToRecordType()
}
bytesResult, err := json.Marshal(records)
if err != nil {
return err
}
return clientCtx.PrintBytes(bytesResult)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdGetResource queries a record record.
func GetCmdGetResource() *cobra.Command {
cmd := &cobra.Command{
Use: "get [ID]",
Short: "Get record.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get the record by id.
Example:
$ %s query %s get [ID]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
record, err := queryClient.GetRecord(cmd.Context(), &types.QueryRecordByIdRequest{Id: args[0]})
if err != nil {
return err
}
return clientCtx.PrintProto(record)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdResolve resolves a CRN to a record.
func GetCmdResolve() *cobra.Command {
cmd := &cobra.Command{
Use: "resolve [crn]",
Short: "Resolve CRN to record.",
Long: strings.TrimSpace(
fmt.Sprintf(`Resolve CRN to record.
Example:
$ %s query %s resolve [crn]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
record, err := queryClient.ResolveCrn(cmd.Context(), &types.QueryResolveCrn{Crn: args[0]})
if err != nil {
return err
}
return clientCtx.PrintProto(record)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdQueryByBond queries records by bond ID.
func GetCmdQueryByBond() *cobra.Command {
cmd := &cobra.Command{
Use: "query-by-bond [bond-id]",
Short: "Query records by bond ID.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get the record by bond id.
Example:
$ %s query %s query-by-bond [bond id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
bondID := args[0]
res, err := queryClient.GetRecordByBondId(cmd.Context(), &types.QueryRecordByBondIdRequest{Id: bondID})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdBalance queries the bond module account balance.
func GetCmdBalance() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "Get record rent module account balance.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get the record rent module account balance.
Example:
$ %s query %s balance
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetNameServiceModuleBalance(cmd.Context(), &types.GetNameServiceModuleBalanceRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetCmdNames queries all naming records.
func GetCmdNames() *cobra.Command {
cmd := &cobra.Command{
Use: "names",
Short: "List name records.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get the names list.
Example:
$ %s query %s names
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ListNameRecords(cmd.Context(), &types.QueryListNameRecordsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetRecordExpiryQueue gets the record expiry queue.
func GetRecordExpiryQueue() *cobra.Command {
cmd := &cobra.Command{
Use: "record-expiry",
Short: "Get record expiry queue.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get record expiry queue.
Example:
$ %s query %s record-expiry
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetRecordExpiryQueue(cmd.Context(), &types.QueryGetRecordExpiryQueue{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetAuthorityExpiryQueue gets the authority expiry queue.
func GetAuthorityExpiryQueue() *cobra.Command {
cmd := &cobra.Command{
Use: "authority-expiry",
Short: "Get authority expiry queue.",
Long: strings.TrimSpace(
fmt.Sprintf(`Get authority expiry queue.
Example:
$ %s query %s authority-expiry
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.GetAuthorityExpiryQueue(cmd.Context(), &types.QueryGetAuthorityExpiryQueue{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
+389
View File
@@ -0,0 +1,389 @@
package cli
import (
"fmt"
"io/ioutil"
"strings"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/spf13/cobra"
"github.com/tharsis/ethermint/server/flags"
"github.com/tharsis/ethermint/x/nameservice/types"
"gopkg.in/yaml.v3"
)
// NewTxCmd returns a root CLI command handler for all x/bond transaction commands.
func NewTxCmd() *cobra.Command {
bondTxCmd := &cobra.Command{
Use: types.ModuleName,
Short: "nameservice transaction subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
bondTxCmd.AddCommand(
GetCmdSetRecord(),
GetCmdRenewRecord(),
GetCmdAssociateBond(),
GetCmdDissociateBond(),
GetCmdDissociateRecords(),
GetCmdReAssociateRecords(),
GetCmdSetName(),
GetCmdReserveName(),
GetCmdSetAuthorityBond(),
GetCmdDeleteName(),
)
return bondTxCmd
}
// GetCmdSetRecord is the CLI command for creating/updating a record.
func GetCmdSetRecord() *cobra.Command {
cmd := &cobra.Command{
Use: "set [payload file path] [bond-id]",
Short: "Set record.",
Long: strings.TrimSpace(
fmt.Sprintf(`Create a new record with payload and bond id.
Example:
$ %s tx %s set [payload file path] [bond-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
payload, err := GetPayloadFromFile(args[0])
if err != nil {
return err
}
msg := types.NewMsgSetRecord(payload.ToPayload(), args[1], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdRenewRecord is the CLI command for renewing an expired record.
func GetCmdRenewRecord() *cobra.Command {
cmd := &cobra.Command{
Use: "renew-record [record-id]",
Short: "Renew (expired) record.",
Long: strings.TrimSpace(
fmt.Sprintf(`Renew record.
Example:
$ %s tx %s renew-record [record-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgRenewRecord(args[0], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdAssociateBond is the CLI command for associating a record with a bond.
func GetCmdAssociateBond() *cobra.Command {
cmd := &cobra.Command{
Use: "associate-bond [record-id] [bond-id]",
Short: "Associate record with bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Associate record with bond.
Example:
$ %s tx %s associate-bond [record-id] [bond-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgAssociateBond(args[0], args[1], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdDissociateBond is the CLI command for dissociating a record from a bond.
func GetCmdDissociateBond() *cobra.Command {
cmd := &cobra.Command{
Use: "dissociate-bond [record-id]",
Short: "Dissociate record from (existing) bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Dissociate record from (existing) bond.
Example:
$ %s tx %s dissociate-bond [record-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgDissociateBond(args[0], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdDissociateRecords is the CLI command for dissociating all records from a bond.
func GetCmdDissociateRecords() *cobra.Command {
cmd := &cobra.Command{
Use: "dissociate-records [bond-id]",
Short: "Dissociate all records from bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Dissociate all records from bond.
Example:
$ %s tx %s dissociate-bond [record-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgDissociateRecords(args[0], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdReAssociateRecords is the CLI command for reassociating all records from old to new bond.
func GetCmdReAssociateRecords() *cobra.Command {
cmd := &cobra.Command{
Use: "reassociate-records [old-bond-id] [new-bond-id]",
Short: "Re-Associates all records from old to new bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Re-Associates all records from old to new bond.
Example:
$ %s tx %s reassociate-records [old-bond-id] [new-bond-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgReAssociateRecords(args[0], args[1], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdSetName is the CLI command for mapping a name to a CID.
func GetCmdSetName() *cobra.Command {
cmd := &cobra.Command{
Use: "set-name [crn] [cid]",
Short: "Set CRN to CID mapping.",
Long: strings.TrimSpace(
fmt.Sprintf(`Set name with crn and cid.
Example:
$ %s tx %s set-name [crn] [cid]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgSetName(args[0], args[1], clientCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdReserveName is the CLI command for reserving a name.
func GetCmdReserveName() *cobra.Command {
cmd := &cobra.Command{
Use: "reserve-name [name]",
Short: "Reserve name.",
Long: strings.TrimSpace(
fmt.Sprintf(`Reserver name with owner address .
Example:
$ %s tx %s reserve-name [name] --owner [ownerAddress]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
owner, err := cmd.Flags().GetString("owner")
if err != nil {
return err
}
ownerAddress, err := sdk.AccAddressFromBech32(owner)
if err != nil {
return err
}
msg := types.NewMsgReserveAuthority(args[0], clientCtx.GetFromAddress(), ownerAddress)
err = msg.ValidateBasic()
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
cmd.Flags().String("owner", "", "Owner address, if creating a sub-authority.")
flags.AddTxFlags(cmd)
return cmd
}
// GetCmdSetAuthorityBond is the CLI command for associating a bond with an authority.
func GetCmdSetAuthorityBond() *cobra.Command {
cmd := &cobra.Command{
Use: "authority-bond [name] [bond-id]",
Short: "Associate authority with bond.",
Long: strings.TrimSpace(
fmt.Sprintf(`Reserver name with owner address .
Example:
$ %s tx %s authority-bond [name] [bond-id]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgSetAuthorityBond(args[0], args[1], clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
func GetCmdDeleteName() *cobra.Command {
cmd := &cobra.Command{
Use: "delete-name [crn]",
Short: "Delete CRN.",
Long: strings.TrimSpace(
fmt.Sprintf(`Delete CRN.
Example:
$ %s tx %s delete-name [crn]
`,
version.AppName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgDeleteNameAuthority(args[0], clientCtx.GetFromAddress())
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlags(cmd)
return cmd
}
//GetPayloadFromFile Load payload object from YAML file.
func GetPayloadFromFile(filePath string) (*types.PayloadType, error) {
var payload types.PayloadType
data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(data, &payload)
if err != nil {
return nil, err
}
return &payload, nil
}
+13
View File
@@ -0,0 +1,13 @@
package testutil
import (
"github.com/stretchr/testify/suite"
"github.com/tharsis/ethermint/testutil/network"
"testing"
)
func TestIntegrationTestSuite(t *testing.T) {
cfg := network.DefaultConfig()
cfg.NumValidators = 1
suite.Run(t, NewIntegrationTestSuite(cfg))
}
@@ -0,0 +1,7 @@
record:
attr1: value1
attr2: value2
link1:
/: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
link2:
/: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
+651
View File
@@ -0,0 +1,651 @@
package testutil
import (
"encoding/json"
"fmt"
"os"
"time"
"github.com/cosmos/cosmos-sdk/client/flags"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/nameservice/client/cli"
nstypes "github.com/tharsis/ethermint/x/nameservice/types"
)
func (s *IntegrationTestSuite) TestGRPCQueryParams() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/params"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
},
{
"Success",
reqUrl,
false,
"",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryParamsResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
params := nstypes.DefaultParams()
params.RecordRent = sdk.NewCoin(s.cfg.BondDenom, nstypes.DefaultRecordRent)
params.RecordRentDuration = 10 * time.Second
params.AuthorityGracePeriod = 10 * time.Second
sr.Equal(response.GetParams().String(), params.String())
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryWhoIs() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/whois/%s"
var authorityName = "QueryWhoIS"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(authorityName string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(authorityName string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(authorityName string) {
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(authorityName)
tc.url = fmt.Sprintf(tc.url, authorityName)
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryWhoisResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.Equal(nstypes.AuthorityActive, response.GetNameAuthority().Status)
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryLookup() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/lookup?crn=%s"
var authorityName = "QueryLookUp"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(authorityName string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(authorityName string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(authorityName string) {
// create name record
createNameRecord(authorityName, s)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(authorityName)
tc.url = fmt.Sprintf(reqUrl, fmt.Sprintf("crn://%s/", authorityName))
}
resp, _ := rest.GetRequest(tc.url)
if tc.expectErr {
sr.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryLookupCrnResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.Name.Latest.Id))
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryRecordExpiryQueue() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/record-expiry"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(bondId string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(bondId string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(bondId string) {
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
args := []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
args = append([]string{payloadPath, bondId}, args...)
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(s.bondId)
}
// wait 12 seconds for records expires
time.Sleep(time.Second * 12)
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryGetRecordExpiryQueueResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetRecords()))
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryAuthorityExpiryQueue() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/authority-expiry"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(authorityName string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(authorityName string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(authorityName string) {
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun("QueryAuthorityExpiryQueue")
}
// wait 12 seconds to name authorites expires
time.Sleep(time.Second * 12)
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryGetAuthorityExpiryQueueResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
// removed from expiry queue as no bond set
sr.Zero(len(response.GetAuthorities()))
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryListRecords() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/records"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(bondId string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(bondId string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(bondId string) {
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
args := []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
args = append([]string{payloadPath, bondId}, args...)
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(s.bondId)
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryListRecordsResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetRecords()))
sr.Equal(s.bondId, response.GetRecords()[0].GetBondId())
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryGetRecordByID() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/records/%s"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(bondId string) string
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(bondId string) string {
return ""
},
},
{
"Success",
reqUrl,
false,
"",
func(bondId string) string {
// creating the record
createRecord(bondId, s)
// list the records
clientCtx := val.ClientCtx
cmd := cli.GetCmdList()
args := []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var records []nstypes.RecordType
err = json.Unmarshal(out.Bytes(), &records)
sr.NoError(err)
return records[0].Id
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
var recordId string
if !tc.expectErr {
recordId = tc.preRun(s.bondId)
tc.url = fmt.Sprintf(reqUrl, recordId)
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryRecordByIdResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
record := response.GetRecord()
sr.NotZero(len(record.GetId()))
sr.Equal(record.GetId(), recordId)
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryGetRecordByBondID() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/records-by-bond-id/%s"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(bondId string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(bondId string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(bondId string) {
// creating the record
createRecord(bondId, s)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(s.bondId)
tc.url = fmt.Sprintf(reqUrl, s.bondId)
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryRecordByBondIdResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
records := response.GetRecords()
sr.NotZero(len(records))
sr.Equal(records[0].GetBondId(), s.bondId)
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryGetNameServiceModuleBalance() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/balance"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(bondId string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(bondId string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(bondId string) {
// creating the record
createRecord(bondId, s)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun(s.bondId)
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.GetNameServiceModuleBalanceResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetBalances()))
}
})
}
}
func (s *IntegrationTestSuite) TestGRPCQueryNamesList() {
val := s.network.Validators[0]
sr := s.Require()
reqUrl := val.APIAddress + "/vulcanize/nameservice/v1beta1/names"
testCases := []struct {
name string
url string
expectErr bool
errorMsg string
preRun func(authorityName string)
}{
{
"invalid url",
reqUrl + "/asdasd",
true,
"",
func(authorityName string) {
},
},
{
"Success",
reqUrl,
false,
"",
func(authorityName string) {
// create name record
createNameRecord(authorityName, s)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expectErr {
tc.preRun("ListNameRecords")
}
resp, _ := rest.GetRequest(tc.url)
require := s.Require()
if tc.expectErr {
require.Contains(string(resp), tc.errorMsg)
} else {
var response nstypes.QueryListNameRecordsResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
sr.NoError(err)
sr.NotZero(len(response.GetNames()))
}
})
}
}
func createRecord(bondId string, s *IntegrationTestSuite) {
val := s.network.Validators[0]
sr := s.Require()
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
args := []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
args = append([]string{payloadPath, bondId}, args...)
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
+585
View File
@@ -0,0 +1,585 @@
package testutil
import (
"encoding/json"
"fmt"
"os"
"time"
"github.com/cosmos/cosmos-sdk/client/flags"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/x/nameservice/client/cli"
"github.com/tharsis/ethermint/x/nameservice/types"
)
func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
}{
{
"params",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryParamsCmd()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
sr.NoError(err)
var param types.QueryParamsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &param)
sr.NoError(err)
params := types.DefaultParams()
params.RecordRent = sdk.NewCoin(s.cfg.BondDenom, types.DefaultRecordRent)
params.RecordRentDuration = 10 * time.Second
params.AuthorityGracePeriod = 10 * time.Second
sr.Equal(param.GetParams().String(), params.String())
})
}
}
func (s *IntegrationTestSuite) TestGetCmdQueryForRecords() {
val := s.network.Validators[0]
sr := s.Require()
var recordID string
var bondId string
testCases := []struct {
name string
args []string
expErr bool
noOfRecords int
preRun func()
}{
{
"invalid request",
[]string{"invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
0,
func() {
},
},
{
"get records list",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
func() {
CreateBond(s)
// get the bond id from bond list
bondId := GetBondId(s)
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
args := []string{
payloadPath, bondId,
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
clientCtx := val.ClientCtx
if !tc.expErr {
tc.preRun()
}
cmd := cli.GetCmdList()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var records []types.RecordType
err := json.Unmarshal(out.Bytes(), &records)
sr.NoError(err)
sr.Equal(tc.noOfRecords, len(records))
recordID = records[0].Id
bondId = GetBondId(s)
}
})
}
s.T().Log("Test Cases for getting records by record-id")
testCasesByRecordID := []struct {
name string
args []string
expErr bool
}{
{
"invalid request without record id",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
},
{
"get records by id",
[]string{recordID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
},
}
for _, tc := range testCasesByRecordID {
s.Run(tc.name, func() {
cmd := cli.GetCmdGetResource()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryRecordByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
sr.NotNil(response.GetRecord())
}
})
}
s.T().Log("Test Cases for getting records by bond-id")
testCasesByRecordByBondID := []struct {
name string
args []string
expErr bool
}{
{
"invalid request without bond-id",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
},
{
"get records by bond-id",
[]string{bondId, fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
},
}
for _, tc := range testCasesByRecordByBondID {
s.Run(tc.name, func() {
cmd := cli.GetCmdQueryByBond()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryRecordByBondIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
}
})
}
s.T().Log("Test Cases for getting nameservice module account balance")
testCasesForNameServiceModuleBalance := []struct {
name string
args []string
expErr bool
noOfRecords int
}{
{
"get nameservice module accounts balance",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
},
}
for _, tc := range testCasesForNameServiceModuleBalance {
s.Run(tc.name, func() {
cmd := cli.GetCmdBalance()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.GetNameServiceModuleBalanceResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
sr.Equal(tc.noOfRecords, len(response.GetBalances()))
balance := response.GetBalances()[0]
sr.Equal(balance.AccountName, types.RecordRentModuleAccountName)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdWhoIs() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "test2"
testCases := []struct {
name string
args []string
expErr bool
noOfRecords int
preRun func(authorityName string)
}{
{
"invalid request without name",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
1,
func(authorityName string) {
},
},
{
"success query with name",
[]string{authorityName, fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
func(authorityName string) {
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expErr {
tc.preRun(authorityName)
}
cmd := cli.GetCmdWhoIs()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryWhoisResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
nameAuthority := response.GetNameAuthority()
nameAuthority.OwnerAddress = accountAddress
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdLookupCRN() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "test1"
testCases := []struct {
name string
args []string
expErr bool
noOfRecords int
preRun func(authorityName string)
}{
{
"invalid request without crn",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
0,
func(authorityName string) {
},
},
{
"success query with name",
[]string{fmt.Sprintf("crn://%s/", authorityName), fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
func(authorityName string) {
// reserving the name
createNameRecord(authorityName, s)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expErr {
// set-name with crn and bond-id
tc.preRun(authorityName)
}
cmd := cli.GetCmdLookupCRN()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryLookupCrnResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
nameRecord := response.GetName()
sr.NotNil(nameRecord.Latest.Id)
}
})
}
testCasesForNamesList := []struct {
name string
args []string
expErr bool
noOfRecords int
}{
{
"invalid request without crn",
[]string{"invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
0,
},
{
"success query with name",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
},
}
for _, tc := range testCasesForNamesList {
s.Run(tc.name, func() {
cmd := cli.GetCmdNames()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryListNameRecordsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
sr.NotZero(len(response.GetNames()))
}
})
}
}
func (s *IntegrationTestSuite) GetRecordExpiryQueue() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "GetRecordExpiryQueue"
testCasesForRecordsExpiry := []struct {
name string
args []string
expErr bool
noOfRecords int
preRun func(authorityName string, s *IntegrationTestSuite)
}{
{
"invalid request",
[]string{"invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
0,
func(authorityName string, s *IntegrationTestSuite) {
},
},
{
"get expiry records ",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
1,
func(authorityName string, s *IntegrationTestSuite) {
createNameRecord(authorityName, s)
},
},
}
for _, tc := range testCasesForRecordsExpiry {
s.Run(tc.name, func() {
if !tc.expErr {
tc.preRun(authorityName, s)
time.Sleep(time.Second * 12)
}
cmd := cli.GetRecordExpiryQueue()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryGetRecordExpiryQueueResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
sr.Equal(tc.noOfRecords, len(response.GetRecords()))
}
})
}
}
func (s *IntegrationTestSuite) TestGetAuthorityExpiryQueue() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "TestGetAuthorityExpiryQueue"
testCases := []struct {
name string
args []string
expErr bool
preRun func(authorityName string)
}{
{
"invalid request without name",
[]string{"invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
true,
func(authorityName string) {
},
},
{
"success query",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
func(authorityName string) {
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
if !tc.expErr {
tc.preRun(authorityName)
time.Sleep(time.Second * 6)
}
cmd := cli.GetAuthorityExpiryQueue()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expErr {
sr.Error(err)
} else {
sr.NoError(err)
var response types.QueryGetAuthorityExpiryQueueResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
sr.NotZero(len(response.GetAuthorities()))
}
})
}
}
func createNameRecord(authorityName string, s *IntegrationTestSuite) {
val := s.network.Validators[0]
sr := s.Require()
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// creating the bond
CreateBond(s)
// Get the bond-id
bondId := GetBondId(s)
// adding bond-id to name authority
args = []string{
authorityName, bondId,
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
cmd = cli.GetCmdSetAuthorityBond()
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
args = []string{
fmt.Sprintf("crn://%s/", authorityName),
"test_hello_cid",
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
cmd = cli.GetCmdSetName()
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
+913
View File
@@ -0,0 +1,913 @@
package testutil
import (
"encoding/json"
"fmt"
"os"
"time"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tharsis/ethermint/testutil/network"
bondcli "github.com/tharsis/ethermint/x/bond/client/cli"
"github.com/tharsis/ethermint/x/bond/types"
"github.com/tharsis/ethermint/x/nameservice/client/cli"
nstypes "github.com/tharsis/ethermint/x/nameservice/types"
)
var (
accountName = "accountName"
accountAddress string
)
type IntegrationTestSuite struct {
suite.Suite
cfg network.Config
network *network.Network
bondId string
}
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
return &IntegrationTestSuite{cfg: cfg}
}
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
var genesisState = s.cfg.GenesisState
var nsData nstypes.GenesisState
s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[nstypes.ModuleName], &nsData))
nsData.Params.RecordRent = sdk.NewCoin(s.cfg.BondDenom, nstypes.DefaultRecordRent)
nsData.Params.RecordRentDuration = 10 * time.Second
nsData.Params.AuthorityGracePeriod = 10 * time.Second
nsDataBz, err := s.cfg.Codec.MarshalJSON(&nsData)
s.Require().NoError(err)
genesisState[nstypes.ModuleName] = nsDataBz
s.cfg.GenesisState = genesisState
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(2)
s.Require().NoError(err)
// setting up random account
s.createAccountWithBalance(accountName)
CreateBond(s)
s.bondId = GetBondId(s)
}
func (s *IntegrationTestSuite) createAccountWithBalance(accountName string) {
val := s.network.Validators[0]
sr := s.Require()
consPrivKey := ed25519.GenPrivKey()
consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
sr.NoError(err)
sr.NotNil(consPubKeyBz)
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
sr.NoError(err)
// account key
newAddr := sdk.AccAddress(info.GetPubKey().Address())
_, err = banktestutil.MsgSendExec(
val.ClientCtx,
val.Address,
newAddr,
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1000000000000000000))),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
)
sr.NoError(err)
accountAddress = newAddr.String()
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func CreateBond(s *IntegrationTestSuite) {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
}{
{
"create bond",
[]string{
fmt.Sprintf("100000000000%s", s.cfg.BondDenom),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := bondcli.NewCreateBondCmd()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func GetBondId(s *IntegrationTestSuite) string {
cmd := bondcli.GetQueryBondLists()
val := s.network.Validators[0]
sr := s.Require()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)})
sr.NoError(err)
var queryResponse types.QueryGetBondsResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
sr.NoError(err)
// extract bond id from bonds list
bond := queryResponse.GetBonds()[0]
return bond.GetId()
}
func (s *IntegrationTestSuite) TestGetCmdSetRecord() {
val := s.network.Validators[0]
sr := s.Require()
testCases := []struct {
name string
args []string
err bool
}{
{
"invalid request without bond id/without payload",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
},
{
"success",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
if !tc.err {
// create the bond
CreateBond(s)
// get the bond id from bond list
bondId := GetBondId(s)
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
tc.args = append([]string{payloadPath, bondId}, tc.args...)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdReserveName() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "testtest"
testCases := []struct {
name string
args []string
err bool
}{
{
"invalid request without name",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
},
{
"success for parent name",
[]string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
},
{
"success for sub domains",
[]string{
"sub." + authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdSetName() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "TestGetCmdSetName"
testCases := []struct {
name string
args []string
err bool
preRun func(authorityName string)
}{
{
"invalid request without name",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
func(authorityName string) {
},
},
{
"success",
[]string{
fmt.Sprintf("crn://%s/", authorityName),
"test_hello_cid",
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
func(authorityName string) {
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// creating the bond
CreateBond(s)
// Get the bond-id
bondId := GetBondId(s)
// adding bond-id to name authority
args = []string{
authorityName, bondId,
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
cmd = cli.GetCmdSetAuthorityBond()
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
if !tc.err {
tc.preRun(authorityName)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetName()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdSetAuthorityBond() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "TestGetCmdSetAuthorityBond"
testCases := []struct {
name string
args []string
err bool
preRun func(authorityName string)
}{
{
"invalid request without name",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
func(authorityName string) {
},
},
{
"success with name and bond-id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
func(authorityName string) {
// reserving the name
clientCtx := val.ClientCtx
cmd := cli.GetCmdReserveName()
args := []string{
authorityName,
fmt.Sprintf("--owner=%s", accountAddress),
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
},
},
}
for _, tc := range testCases {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
if !tc.err {
// reserve the name
tc.preRun(authorityName)
// creating the bond
CreateBond(s)
// getting the bond-id
bondId := GetBondId(s)
tc.args = append([]string{authorityName, bondId}, tc.args...)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetAuthorityBond()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdDeleteName() {
val := s.network.Validators[0]
sr := s.Require()
var authorityName = "TestGetCmdDeleteName"
testCasesForDeletingName := []struct {
name string
args []string
err bool
preRun func(authorityName string, s *IntegrationTestSuite)
}{
{
"invalid request without crn",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
func(authorityName string, s *IntegrationTestSuite) {
},
},
{
"successfully delete name",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
func(authorityName string, s *IntegrationTestSuite) {
createNameRecord(authorityName, s)
},
},
}
for _, tc := range testCasesForDeletingName {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
if !tc.err {
tc.preRun(authorityName, s)
tc.args = append([]string{fmt.Sprintf("crn://%s/", authorityName)}, tc.args...)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdDeleteName()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
}
})
}
}
func (s *IntegrationTestSuite) TestGetCmdDissociateBond() {
val := s.network.Validators[0]
sr := s.Require()
testCasesForDeletingName := []struct {
name string
args []string
err bool
preRun func(s *IntegrationTestSuite) string
postRun func(recordId string, s *IntegrationTestSuite)
}{
{
"invalid request without crn",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
func(s *IntegrationTestSuite) string {
return ""
},
func(recordId string, s *IntegrationTestSuite) {
},
},
{
"successfully dissociate bond-id from record ",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
func(s *IntegrationTestSuite) string {
// create the bond
CreateBond(s)
// get the bond id from bond list
bondId := GetBondId(s)
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
args := []string{
payloadPath, bondId,
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// retrieving the record-id
args = []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
cmd = cli.GetCmdList()
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var records []nstypes.RecordType
err = json.Unmarshal(out.Bytes(), &records)
sr.NoError(err)
return records[0].Id
},
func(recordId string, s *IntegrationTestSuite) {
// checking the bond-id removed or not
clientCtx := val.ClientCtx
args := []string{recordId, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
cmd := cli.GetCmdGetResource()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var response nstypes.QueryRecordByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
record := response.GetRecord()
sr.NotNil(record)
sr.Zero(len(record.GetBondId()))
},
},
}
for _, tc := range testCasesForDeletingName {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
var recordId string
if !tc.err {
recordId = tc.preRun(s)
tc.args = append([]string{recordId}, tc.args...)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdDissociateBond()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// post-run
tc.postRun(recordId, s)
}
})
}
}
//
//func (s *IntegrationTestSuite) TestGetCmdDissociateRecords() {
// val := s.network.Validators[0]
// sr := s.Require()
// testCasesForDeletingName := []struct {
// name string
// args []string
// err bool
// preRun func(s *IntegrationTestSuite) (string, string)
// postRun func(recordId string, s *IntegrationTestSuite)
// }{
// {
// "invalid request without crn",
// []string{
// fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
// fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
// fmt.Sprintf("--%s=json", tmcli.OutputFlag),
// fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
// fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
// },
// true,
// func(s *IntegrationTestSuite) (string, string) {
// return "", ""
// },
// func(recordId string, s *IntegrationTestSuite) {
//
// },
// },
// {
// "successfully dissociate records from bond-id",
// []string{
// fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
// fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
// fmt.Sprintf("--%s=json", tmcli.OutputFlag),
// fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
// fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
// },
// false,
// func(s *IntegrationTestSuite) (string, string) {
// // create the bond
// CreateBond(s)
// // get the bond id from bond list
// bondId := GetBondId(s)
// dir, err := os.Getwd()
// sr.NoError(err)
// payloadPath := dir + "/example1.yml"
//
// args := []string{
// payloadPath, bondId,
// fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
// fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
// fmt.Sprintf("--%s=json", tmcli.OutputFlag),
// fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
// fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
// }
//
// clientCtx := val.ClientCtx
// cmd := cli.GetCmdSetRecord()
//
// out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
// sr.NoError(err)
// var d sdk.TxResponse
// err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
// sr.NoError(err)
// sr.Zero(d.Code)
//
// // retrieving the record-id
// args = []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
// cmd = cli.GetCmdList()
// out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
// sr.NoError(err)
// var records []nstypes.RecordType
// err = json.Unmarshal(out.Bytes(), &records)
// sr.NoError(err)
// for _, record := range records {
// if len(record.BondId) != 0 {
// return record.Id, record.BondId
// }
// }
// return records[0].Id, records[0].BondId
// },
// func(recordId string, s *IntegrationTestSuite) {
// // checking the bond-id removed or not
// clientCtx := val.ClientCtx
// args := []string{recordId, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
// cmd := cli.GetCmdGetResource()
// out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
// sr.NoError(err)
// var response nstypes.QueryRecordByIdResponse
// err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
// sr.NoError(err)
// record := response.GetRecord()
// sr.NotNil(record)
// sr.Zero(len(record.GetBondId()))
// },
// },
// }
//
// for _, tc := range testCasesForDeletingName {
// s.Run(fmt.Sprintf("Case %s", tc.name), func() {
// var bondId string
// var recordId string
// if !tc.err {
// recordId, bondId = tc.preRun(s)
// tc.args = append([]string{bondId}, tc.args...)
// }
// clientCtx := val.ClientCtx
// cmd := cli.GetCmdDissociateRecords()
//
// out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
// if tc.err {
// sr.Error(err)
// } else {
// sr.NoError(err)
// var d sdk.TxResponse
// err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
// sr.NoError(err)
// sr.Zero(d.Code)
// // post-run
// tc.postRun(recordId, s)
// }
// })
// }
//}
func (s *IntegrationTestSuite) TestGetCmdAssociateBond() {
val := s.network.Validators[0]
sr := s.Require()
testCasesForDeletingName := []struct {
name string
args []string
err bool
preRun func(s *IntegrationTestSuite) (string, string)
postRun func(recordId, bondId string, s *IntegrationTestSuite)
}{
{
"invalid request without crn",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
true,
func(s *IntegrationTestSuite) (string, string) {
return "", ""
},
func(recordId, bondId string, s *IntegrationTestSuite) {
},
},
{
"successfully dissociate records from bond-id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
},
false,
func(s *IntegrationTestSuite) (string, string) {
// create the bond
CreateBond(s)
// get the bond id from bond list
bondId := GetBondId(s)
dir, err := os.Getwd()
sr.NoError(err)
payloadPath := dir + "/example1.yml"
txArgs := []string{
payloadPath, bondId,
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.cfg.BondDenom)),
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdSetRecord()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, txArgs)
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// retrieving the record-id
args := []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
cmd = cli.GetCmdList()
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var records []nstypes.RecordType
err = json.Unmarshal(out.Bytes(), &records)
sr.NoError(err)
// GetCmdDissociateBond bond
cmd = cli.GetCmdDissociateBond()
txArgs = append([]string{records[0].Id}, txArgs[2:]...)
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, txArgs)
sr.NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
return records[0].Id, records[0].BondId
},
func(recordId, bondId string, s *IntegrationTestSuite) {
// checking the bond-id removed or not
clientCtx := val.ClientCtx
args := []string{recordId, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
cmd := cli.GetCmdGetResource()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
sr.NoError(err)
var response nstypes.QueryRecordByIdResponse
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)
sr.NoError(err)
record := response.GetRecord()
sr.NotNil(record)
sr.Equal(record.GetBondId(), bondId)
},
},
}
for _, tc := range testCasesForDeletingName {
s.Run(fmt.Sprintf("Case %s", tc.name), func() {
var recordId string
var bondId string
if !tc.err {
recordId, bondId = tc.preRun(s)
tc.args = append([]string{recordId, bondId}, tc.args...)
}
clientCtx := val.ClientCtx
cmd := cli.GetCmdAssociateBond()
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.err {
sr.Error(err)
} else {
sr.NoError(err)
var d sdk.TxResponse
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
sr.NoError(err)
sr.Zero(d.Code)
// post-run
tc.postRun(recordId, bondId, s)
}
})
}
}
+79
View File
@@ -0,0 +1,79 @@
package nameservice
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/nameservice/keeper"
"github.com/tharsis/ethermint/x/nameservice/types"
)
func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data types.GenesisState) []abci.ValidatorUpdate {
keeper.SetParams(ctx, data.Params)
for _, record := range data.Records {
keeper.PutRecord(ctx, record)
// Add to record expiry queue if expiry time is in the future.
expiryTime, err := time.Parse(time.RFC3339, record.ExpiryTime)
if err != nil {
panic(err)
}
if expiryTime.After(ctx.BlockTime()) {
keeper.InsertRecordExpiryQueue(ctx, record)
}
// Note: Bond genesis runs first, so bonds will already be present.
if record.BondId != "" {
keeper.AddBondToRecordIndexEntry(ctx, record.BondId, record.Id)
}
}
for _, authority := range data.Authorities {
//Only import authorities that are marked active.
if authority.Entry.Status == types.AuthorityActive {
keeper.SetNameAuthority(ctx, authority.Name, authority.Entry)
// Add authority name to expiry queue.
keeper.InsertAuthorityExpiryQueue(ctx, authority.Name, authority.Entry.ExpiryTime)
// Note: Bond genesis runs first, so bonds will already be present.
if authority.Entry.BondId != "" {
keeper.AddBondToAuthorityIndexEntry(ctx, authority.Entry.BondId, authority.Name)
}
}
}
for _, nameEntry := range data.Names {
keeper.SetNameRecord(ctx, nameEntry.Name, nameEntry.Entry.Latest.Id)
}
return []abci.ValidatorUpdate{}
}
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) types.GenesisState {
params := keeper.GetParams(ctx)
records := keeper.ListRecords(ctx)
authorities := keeper.ListNameAuthorityRecords(ctx)
var authorityEntries []types.AuthorityEntry
for name, record := range authorities {
authorityEntries = append(authorityEntries, types.AuthorityEntry{
Name: name,
Entry: &record,
})
}
names := keeper.ListNameRecords(ctx)
return types.GenesisState{
Params: params,
Records: records,
Authorities: authorityEntries,
Names: names,
}
}
@@ -0,0 +1,7 @@
record:
attr1: value1
attr2: value2
link1:
/: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
link2:
/: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
+144
View File
@@ -0,0 +1,144 @@
package helpers
import (
"bytes"
"encoding/base64"
"encoding/binary"
"encoding/gob"
"encoding/hex"
"encoding/json"
set "github.com/deckarep/golang-set"
cbor "github.com/ipfs/go-ipld-cbor"
mh "github.com/multiformats/go-multihash"
"sort"
)
func StringToBytes(val string) []byte {
return []byte(val)
}
func BytesToString(val []byte) string {
return string(val)
}
func StrArrToBytesArr(val []string) ([]byte, error) {
buffer := &bytes.Buffer{}
err := gob.NewEncoder(buffer).Encode(val)
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func BytesArrToStringArr(val []byte) ([]string, error) {
buffer := bytes.NewReader(val)
var v []string
err := gob.NewDecoder(buffer).Decode(&v)
if err != nil {
return nil, err
}
return v, nil
}
func Int64ToBytes(num int64) []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, num)
return buf.Bytes()
}
// MarshalMapToJSONBytes converts map[string]interface{} to bytes.
func MarshalMapToJSONBytes(val map[string]interface{}) (bytes []byte) {
bytes, err := json.Marshal(val)
if err != nil {
panic("Marshal error.")
}
return
}
// UnMarshalMapFromJSONBytes converts bytes to map[string]interface{}.
func UnMarshalMapFromJSONBytes(bytes []byte) map[string]interface{} {
var val map[string]interface{}
err := json.Unmarshal(bytes, &val)
if err != nil {
panic("Marshal error.")
}
return val
}
// GetCid gets the content ID.
func GetCid(content []byte) (string, error) {
node, err := cbor.FromJSON(bytes.NewReader(content), mh.SHA2_256, -1)
if err != nil {
return "", err
}
return node.Cid().String(), nil
}
// BytesToBase64 encodes a byte array as a base64 string.
func BytesToBase64(bytes []byte) string {
return base64.StdEncoding.EncodeToString(bytes)
}
// BytesFromBase64 decodes a byte array from a base64 string.
func BytesFromBase64(str string) []byte {
bytes, err := base64.StdEncoding.DecodeString(str)
if err != nil {
panic("Error decoding string to bytes.")
}
return bytes
}
// BytesToHex encodes a byte array as a hex string.
func BytesToHex(bytes []byte) string {
return hex.EncodeToString(bytes)
}
// BytesFromHex decodes a byte array from a hex string.
func BytesFromHex(str string) []byte {
bytes, err := hex.DecodeString(str)
if err != nil {
panic("Error decoding hex to bytes.")
}
return bytes
}
func SetToSlice(set set.Set) []string {
names := []string{}
for name := range set.Iter() {
if name, ok := name.(string); ok && name != "" {
names = append(names, name)
}
}
sort.SliceStable(names, func(i, j int) bool { return names[i] < names[j] })
return names
}
func SliceToSet(names []string) set.Set {
set := set.NewThreadUnsafeSet()
for _, name := range names {
if name != "" {
set.Add(name)
}
}
return set
}
func AppendUnique(list []string, element string) []string {
set := SliceToSet(list)
set.Add(element)
return SetToSlice(set)
}
+227
View File
@@ -0,0 +1,227 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// BondIDAttributeName denotes the record bond ID.
const BondIDAttributeName = "bondId"
// ExpiryTimeAttributeName denotes the record expiry time.
const ExpiryTimeAttributeName = "expiryTime"
type Querier struct {
Keeper
}
var _ types.QueryServer = Querier{}
func (q Querier) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
params := q.Keeper.GetParams(ctx)
return &types.QueryParamsResponse{Params: &params}, nil
}
func (q Querier) ListRecords(c context.Context, req *types.QueryListRecordsRequest) (*types.QueryListRecordsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
attributes := req.GetAttributes()
all := req.GetAll()
records := []types.Record{}
if len(attributes) > 0 {
records = q.Keeper.MatchRecords(ctx, func(record *types.RecordType) bool {
return MatchOnAttributes(record, attributes, all)
})
} else {
records = q.Keeper.ListRecords(ctx)
}
return &types.QueryListRecordsResponse{Records: records}, nil
}
func (q Querier) GetRecord(c context.Context, req *types.QueryRecordByIdRequest) (*types.QueryRecordByIdResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
id := req.GetId()
if !q.Keeper.HasRecord(ctx, id) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Record not found.")
}
record := q.Keeper.GetRecord(ctx, id)
return &types.QueryRecordByIdResponse{Record: record}, nil
}
func (q Querier) GetRecordByBondId(c context.Context, req *types.QueryRecordByBondIdRequest) (*types.QueryRecordByBondIdResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
records := q.recordKeeper.QueryRecordsByBond(ctx, req.GetId())
return &types.QueryRecordByBondIdResponse{Records: records}, nil
}
func (q Querier) GetNameServiceModuleBalance(c context.Context, _ *types.GetNameServiceModuleBalanceRequest) (*types.GetNameServiceModuleBalanceResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
balances := q.Keeper.GetModuleBalances(ctx)
return &types.GetNameServiceModuleBalanceResponse{
Balances: balances,
}, nil
}
func (q Querier) ListNameRecords(c context.Context, _ *types.QueryListNameRecordsRequest) (*types.QueryListNameRecordsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
nameRecords := q.Keeper.ListNameRecords(ctx)
return &types.QueryListNameRecordsResponse{Names: nameRecords}, nil
}
func (q Querier) Whois(c context.Context, request *types.QueryWhoisRequest) (*types.QueryWhoisResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
nameAuthority := q.Keeper.GetNameAuthority(ctx, request.GetName())
return &types.QueryWhoisResponse{NameAuthority: nameAuthority}, nil
}
func (q Querier) LookupCrn(c context.Context, req *types.QueryLookupCrn) (*types.QueryLookupCrnResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
crn := req.GetCrn()
if !q.Keeper.HasNameRecord(ctx, crn) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "CRN not found.")
}
nameRecord := q.Keeper.GetNameRecord(ctx, crn)
if nameRecord == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "name record not found.")
}
return &types.QueryLookupCrnResponse{Name: nameRecord}, nil
}
func (q Querier) ResolveCrn(c context.Context, req *types.QueryResolveCrn) (*types.QueryResolveCrnResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
crn := req.GetCrn()
record := q.Keeper.ResolveCRN(ctx, crn)
if record == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "record not found.")
}
return &types.QueryResolveCrnResponse{Record: record}, nil
}
func (q Querier) GetRecordExpiryQueue(c context.Context, _ *types.QueryGetRecordExpiryQueue) (*types.QueryGetRecordExpiryQueueResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
records := q.Keeper.GetRecordExpiryQueue(ctx)
return &types.QueryGetRecordExpiryQueueResponse{Records: records}, nil
}
func (q Querier) GetAuthorityExpiryQueue(c context.Context, _ *types.QueryGetAuthorityExpiryQueue) (*types.QueryGetAuthorityExpiryQueueResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
authorities := q.Keeper.GetAuthorityExpiryQueue(ctx)
return &types.QueryGetAuthorityExpiryQueueResponse{Authorities: authorities}, nil
}
func matchOnRecordField(record *types.RecordType, attr *types.QueryListRecordsRequest_KeyValueInput) (fieldFound bool, matched bool) {
fieldFound = false
matched = true
switch attr.Key {
case BondIDAttributeName:
{
fieldFound = true
if record.BondId != attr.Value.GetString_() {
matched = false
return
}
}
case ExpiryTimeAttributeName:
{
fieldFound = true
if record.ExpiryTime != attr.Value.GetString_() {
matched = false
return
}
}
}
return
}
func MatchOnAttributes(record *types.RecordType, attributes []*types.QueryListRecordsRequest_KeyValueInput, all bool) bool {
// Filter deleted records.
if record.Deleted {
return false
}
// If ONLY named records are requested, check for that condition first.
if !all && len(record.Names) == 0 {
return false
}
recAttrs := record.Attributes
for _, attr := range attributes {
// First try matching on record struct fields.
fieldFound, matched := matchOnRecordField(record, attr)
if fieldFound {
if !matched {
return false
}
continue
}
recAttrVal, recAttrFound := recAttrs[attr.Key]
if !recAttrFound {
return false
}
if attr.Value.Type == "int" {
recAttrValInt, ok := recAttrVal.(int)
if !ok || int(attr.Value.GetInt()) != recAttrValInt {
return false
}
}
if attr.Value.Type == "float" {
recAttrValFloat, ok := recAttrVal.(float64)
if !ok || attr.Value.GetFloat() != recAttrValFloat {
return false
}
}
if attr.Value.Type == "string" {
recAttrValString, ok := recAttrVal.(string)
if !ok {
return false
}
if attr.Value.GetString_() != recAttrValString {
return false
}
}
if attr.Value.Type == "boolean" {
recAttrValBool, ok := recAttrVal.(bool)
if !ok || attr.Value.GetBoolean() != recAttrValBool {
return false
}
}
if attr.Value.Type == "reference" {
obj, ok := recAttrVal.(map[string]interface{})
if !ok {
// Attr value is not an object.
return false
}
if _, ok := obj["/"].(string); !ok {
// Attr value is not a reference.
return false
}
recAttrValRefID := obj["/"].(string)
if recAttrValRefID != attr.Value.GetReference().GetId() {
return false
}
}
// TODO: Handle arrays.
}
return true
}
+272
View File
@@ -0,0 +1,272 @@
package keeper_test
import (
"context"
"fmt"
"os"
"github.com/tharsis/ethermint/x/nameservice/client/cli"
nameservicetypes "github.com/tharsis/ethermint/x/nameservice/types"
)
func (suite *KeeperTestSuite) TestGrpcQueryParams() {
grpcClient := suite.queryClient
testCases := []struct {
msg string
req *nameservicetypes.QueryParamsRequest
}{
{
"Get Params",
&nameservicetypes.QueryParamsRequest{},
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
resp, _ := grpcClient.Params(context.Background(), test.req)
defaultParams := nameservicetypes.DefaultParams()
suite.Require().Equal(defaultParams.String(), resp.GetParams().String())
})
}
}
func (suite *KeeperTestSuite) TestGrpcGetRecordLists() {
grpcClient, ctx := suite.queryClient, suite.ctx
sr := suite.Require()
var recordId string
testCases := []struct {
msg string
req *nameservicetypes.QueryListRecordsRequest
createRecord bool
expErr bool
noOfRecords int
}{
{
"Empty Records",
&nameservicetypes.QueryListRecordsRequest{},
false,
false,
0,
},
{
"List Records",
&nameservicetypes.QueryListRecordsRequest{},
true,
false,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createRecord {
dir, err := os.Getwd()
sr.NoError(err)
payload, err := cli.GetPayloadFromFile(dir + "/../helpers/examples/example1.yml")
sr.NoError(err)
record, err := suite.app.NameServiceKeeper.ProcessSetRecord(ctx, nameservicetypes.MsgSetRecord{
BondId: suite.bond.GetId(),
Signer: suite.accounts[0].String(),
Payload: payload.ToPayload(),
})
sr.NoError(err)
sr.NotNil(record.Id)
}
resp, err := grpcClient.ListRecords(context.Background(), test.req)
if test.expErr {
suite.Error(err)
} else {
sr.NoError(err)
sr.Equal(test.noOfRecords, len(resp.GetRecords()))
if test.createRecord {
recordId = resp.GetRecords()[0].GetId()
sr.NotZero(resp.GetRecords())
sr.Equal(resp.GetRecords()[0].GetBondId(), suite.bond.GetId())
}
}
})
}
// Get the records by record id
testCases1 := []struct {
msg string
req *nameservicetypes.QueryRecordByIdRequest
createRecord bool
expErr bool
noOfRecords int
}{
{
"Invalid Request without record id",
&nameservicetypes.QueryRecordByIdRequest{},
false,
true,
0,
},
{
"With Record ID",
&nameservicetypes.QueryRecordByIdRequest{
Id: recordId,
},
true,
false,
1,
},
}
for _, test := range testCases1 {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
resp, err := grpcClient.GetRecord(context.Background(), test.req)
if test.expErr {
suite.Error(err)
} else {
sr.NoError(err)
sr.NotNil(resp.GetRecord())
if test.createRecord {
sr.Equal(resp.GetRecord().BondId, suite.bond.GetId())
sr.Equal(resp.GetRecord().Id, recordId)
}
}
})
}
// Get the records by record id
testCasesByBondID := []struct {
msg string
req *nameservicetypes.QueryRecordByBondIdRequest
createRecord bool
expErr bool
noOfRecords int
}{
{
"Invalid Request without bond id",
&nameservicetypes.QueryRecordByBondIdRequest{},
false,
true,
0,
},
{
"With Bond ID",
&nameservicetypes.QueryRecordByBondIdRequest{
Id: suite.bond.GetId(),
},
true,
false,
1,
},
}
for _, test := range testCasesByBondID {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
resp, err := grpcClient.GetRecordByBondId(context.Background(), test.req)
if test.expErr {
sr.Zero(resp.GetRecords())
} else {
sr.NoError(err)
sr.NotNil(resp.GetRecords())
if test.createRecord {
sr.NotZero(resp.GetRecords())
sr.Equal(resp.GetRecords()[0].GetBondId(), suite.bond.GetId())
}
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcQueryNameserviceModuleBalance() {
grpcClient, ctx := suite.queryClient, suite.ctx
sr := suite.Require()
testCases := []struct {
msg string
req *nameservicetypes.GetNameServiceModuleBalanceRequest
createRecord bool
expErr bool
noOfRecords int
}{
{
"Get Module Balance",
&nameservicetypes.GetNameServiceModuleBalanceRequest{},
true,
false,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createRecord {
dir, err := os.Getwd()
sr.NoError(err)
payload, err := cli.GetPayloadFromFile(dir + "/../helpers/examples/example1.yml")
sr.NoError(err)
record, err := suite.app.NameServiceKeeper.ProcessSetRecord(ctx, nameservicetypes.MsgSetRecord{
BondId: suite.bond.GetId(),
Signer: suite.accounts[0].String(),
Payload: payload.ToPayload(),
})
sr.NoError(err)
sr.NotNil(record.Id)
}
resp, err := grpcClient.GetNameServiceModuleBalance(context.Background(), test.req)
if test.expErr {
suite.Error(err)
} else {
sr.NoError(err)
sr.Equal(test.noOfRecords, len(resp.GetBalances()))
if test.createRecord {
balance := resp.GetBalances()[0]
sr.Equal(balance.AccountName, nameservicetypes.RecordRentModuleAccountName)
}
}
})
}
}
func (suite *KeeperTestSuite) TestGrpcQueryWhoIS() {
grpcClient, ctx := suite.queryClient, suite.ctx
sr := suite.Require()
var authorityName = "TestGrpcQueryWhoIS"
testCases := []struct {
msg string
req *nameservicetypes.QueryWhoisRequest
createName bool
expErr bool
noOfRecords int
}{
{
"Invalid Request without name",
&nameservicetypes.QueryWhoisRequest{},
false,
true,
1,
},
{
"Success",
&nameservicetypes.QueryWhoisRequest{},
true,
false,
1,
},
}
for _, test := range testCases {
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
if test.createName {
err := suite.app.NameServiceKeeper.ProcessReserveAuthority(ctx, nameservicetypes.MsgReserveAuthority{
Name: authorityName,
Signer: suite.accounts[0].String(),
Owner: suite.accounts[0].String(),
})
sr.NoError(err)
test.req = &nameservicetypes.QueryWhoisRequest{Name: authorityName}
}
resp, err := grpcClient.Whois(context.Background(), test.req)
if test.expErr {
sr.Zero(len(resp.NameAuthority.AuctionId))
} else {
sr.NoError(err)
if test.createName {
nameAuth := resp.NameAuthority
sr.NotNil(nameAuth)
sr.Equal(nameAuth.OwnerAddress, suite.accounts[0].String())
sr.Equal(nameservicetypes.AuthorityActive, nameAuth.Status)
}
}
})
}
}
+36
View File
@@ -0,0 +1,36 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// RegisterInvariants registers all nameservice module invariants.
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
ir.RegisterRoute(types.ModuleName, "record", RecordInvariants(k))
}
// RecordInvariants checks that every record:
// (1) has a corresponding naming record &
// (2) associated bond exists, if bondID is not null.
func RecordInvariants(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
//store := ctx.KVStore(k.storeKey)
//itr := sdk.KVStorePrefixIterator(store, PrefixCIDToRecordIndex)
//defer itr.Close()
//for ; itr.Valid(); itr.Next() {
// bz := store.Get(itr.Key())
// if bz != nil {
// var obj types.RecordObj
// k.cdc.MustUnmarshalBinaryBare(bz, &obj)
// record := obj.ToRecord()
//
// if record.BondID != "" && !k.bondKeeper.HasBond(ctx, record.BondID) {
// return sdk.FormatInvariant(types.ModuleName, "record-bond", fmt.Sprintf("Bond not found for record ID: '%s'.", record.ID)), true
// }
// }
//}
return "", false
}
}
+437
View File
@@ -0,0 +1,437 @@
package keeper
import (
"bytes"
"fmt"
"sort"
"time"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/legacy"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
bondkeeper "github.com/tharsis/ethermint/x/bond/keeper"
"github.com/tharsis/ethermint/x/nameservice/helpers"
"github.com/tharsis/ethermint/x/nameservice/types"
)
var (
// PrefixCIDToRecordIndex is the prefix for CID -> Record index.
// Note: This is the primary index in the system.
// Note: Golang doesn't support const arrays.
PrefixCIDToRecordIndex = []byte{0x00}
// PrefixNameAuthorityRecordIndex is the prefix for the name -> NameAuthority index.
PrefixNameAuthorityRecordIndex = []byte{0x01}
// PrefixCRNToNameRecordIndex is the prefix for the CRN -> NamingRecord index.
PrefixCRNToNameRecordIndex = []byte{0x02}
// PrefixBondIDToRecordsIndex is the prefix for the Bond ID -> [Record] index.
PrefixBondIDToRecordsIndex = []byte{0x03}
// PrefixBlockChangesetIndex is the prefix for the block changeset index.
PrefixBlockChangesetIndex = []byte{0x04}
// PrefixAuctionToAuthorityNameIndex is the prefix for the auction ID -> authority name index.
PrefixAuctionToAuthorityNameIndex = []byte{0x05}
// PrefixBondIDToAuthoritiesIndex is the prefix for the Bond ID -> [Authority] index.
PrefixBondIDToAuthoritiesIndex = []byte{0x06}
// PrefixExpiryTimeToRecordsIndex is the prefix for the Expiry Time -> [Record] index.
PrefixExpiryTimeToRecordsIndex = []byte{0x10}
// PrefixExpiryTimeToAuthoritiesIndex is the prefix for the Expiry Time -> [Authority] index.
PrefixExpiryTimeToAuthoritiesIndex = []byte{0x11}
// PrefixCIDToNamesIndex the the reverse index for naming, i.e. maps CID -> []Names.
// TODO(ashwin): Move out of WNS once we have an indexing service.
PrefixCIDToNamesIndex = []byte{0xe0}
)
// Keeper maintains the link to storage and exposes getter/setter methods for the various parts of the state machine
type Keeper struct {
accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper
recordKeeper RecordKeeper
bondKeeper bondkeeper.Keeper
auctionKeeper auctionkeeper.Keeper
storeKey sdk.StoreKey // Unexposed key to access store from sdk.Context
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
paramSubspace paramtypes.Subspace
}
// NewKeeper creates new instances of the nameservice Keeper
func NewKeeper(cdc codec.BinaryCodec, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, recordKeeper RecordKeeper,
bondKeeper bondkeeper.Keeper, auctionKeeper auctionkeeper.Keeper, storeKey sdk.StoreKey, ps paramtypes.Subspace) Keeper {
// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}
return Keeper{
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
recordKeeper: recordKeeper,
bondKeeper: bondKeeper,
auctionKeeper: auctionKeeper,
storeKey: storeKey,
cdc: cdc,
paramSubspace: ps,
}
}
// GetRecordIndexKey Generates Bond ID -> Bond index key.
func GetRecordIndexKey(id string) []byte {
return append(PrefixCIDToRecordIndex, []byte(id)...)
}
// HasRecord - checks if a record by the given ID exists.
func (k Keeper) HasRecord(ctx sdk.Context, id string) bool {
store := ctx.KVStore(k.storeKey)
return store.Has(GetRecordIndexKey(id))
}
// GetRecord - gets a record from the store.
func (k Keeper) GetRecord(ctx sdk.Context, id string) (record types.Record) {
store := ctx.KVStore(k.storeKey)
result := store.Get(GetRecordIndexKey(id))
k.cdc.MustUnmarshal(result, &record)
return record
}
// ListRecords - get all records.
func (k Keeper) ListRecords(ctx sdk.Context) []types.Record {
var records []types.Record
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixCIDToRecordIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Record
k.cdc.MustUnmarshal(bz, &obj)
records = append(records, recordObjToRecord(store, k.cdc, obj))
}
}
return records
}
// MatchRecords - get all matching records.
func (k Keeper) MatchRecords(ctx sdk.Context, matchFn func(*types.RecordType) bool) []types.Record {
var records []types.Record
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixCIDToRecordIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var obj types.Record
k.cdc.MustUnmarshal(bz, &obj)
obj = recordObjToRecord(store, k.cdc, obj)
record := obj.ToRecordType()
if matchFn(&record) {
records = append(records, obj)
}
}
}
return records
}
func (k Keeper) GetRecordExpiryQueue(ctx sdk.Context) []*types.ExpiryQueueRecord {
var records []*types.ExpiryQueueRecord
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixExpiryTimeToRecordsIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
record, err := helpers.BytesArrToStringArr(itr.Value())
if err != nil {
return records
}
records = append(records, &types.ExpiryQueueRecord{
Id: string(itr.Key()[len(PrefixExpiryTimeToRecordsIndex):]),
Value: record,
})
}
return records
}
// ProcessSetRecord creates a record.
func (k Keeper) ProcessSetRecord(ctx sdk.Context, msg types.MsgSetRecord) (*types.RecordType, error) {
payload := msg.Payload.ToReadablePayload()
record := types.RecordType{Attributes: payload.Record, BondId: msg.BondId}
// Check signatures.
resourceSignBytes, _ := record.GetSignBytes()
cid, err := record.GetCID()
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid record JSON")
}
record.Id = cid
if exists := k.HasRecord(ctx, record.Id); exists {
// Immutable record already exists. No-op.
return &record, nil
}
record.Owners = []string{}
for _, sig := range payload.Signatures {
pubKey, err := legacy.PubKeyFromBytes(helpers.BytesFromBase64(sig.PubKey))
if err != nil {
fmt.Println("Error decoding pubKey from bytes: ", err)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Invalid public key.")
}
sigOK := pubKey.VerifySignature(resourceSignBytes, helpers.BytesFromBase64(sig.Sig))
if !sigOK {
fmt.Println("Signature mismatch: ", sig.PubKey)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Invalid signature.")
}
record.Owners = append(record.Owners, pubKey.Address().String())
}
// Sort owners list.
sort.Strings(record.Owners)
sdkErr := k.processRecord(ctx, &record, false)
if sdkErr != nil {
return nil, sdkErr
}
return &record, nil
}
func (k Keeper) processRecord(ctx sdk.Context, record *types.RecordType, isRenewal bool) error {
params := k.GetParams(ctx)
rent := params.RecordRent
err := k.bondKeeper.TransferCoinsToModuleAccount(ctx, record.BondId, types.RecordRentModuleAccountName, sdk.NewCoins(rent))
if err != nil {
return err
}
record.CreateTime = ctx.BlockHeader().Time.Format(time.RFC3339)
record.ExpiryTime = ctx.BlockHeader().Time.Add(params.RecordRentDuration).Format(time.RFC3339)
record.Deleted = false
k.PutRecord(ctx, record.ToRecordObj())
k.InsertRecordExpiryQueue(ctx, record.ToRecordObj())
// Renewal doesn't change the name and bond indexes.
if !isRenewal {
k.AddBondToRecordIndexEntry(ctx, record.BondId, record.Id)
}
return nil
}
// PutRecord - saves a record to the store and updates ID -> Record index.
func (k Keeper) PutRecord(ctx sdk.Context, record types.Record) {
store := ctx.KVStore(k.storeKey)
store.Set(GetRecordIndexKey(record.Id), k.cdc.MustMarshal(&record))
k.updateBlockChangeSetForRecord(ctx, record.Id)
}
// AddBondToRecordIndexEntry adds the Bond ID -> [Record] index entry.
func (k Keeper) AddBondToRecordIndexEntry(ctx sdk.Context, bondID string, id string) {
store := ctx.KVStore(k.storeKey)
store.Set(getBondIDToRecordsIndexKey(bondID, id), []byte{})
}
// Generates Bond ID -> Records index key.
func getBondIDToRecordsIndexKey(bondID string, id string) []byte {
return append(append(PrefixBondIDToRecordsIndex, []byte(bondID)...), []byte(id)...)
}
// getRecordExpiryQueueTimeKey gets the prefix for the record expiry queue.
func getRecordExpiryQueueTimeKey(timestamp time.Time) []byte {
timeBytes := sdk.FormatTimeBytes(timestamp)
return append(PrefixExpiryTimeToRecordsIndex, timeBytes...)
}
// SetRecordExpiryQueueTimeSlice sets a specific record expiry queue timeslice.
func (k Keeper) SetRecordExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time, cids []string) {
store := ctx.KVStore(k.storeKey)
bz, _ := helpers.StrArrToBytesArr(cids)
store.Set(getRecordExpiryQueueTimeKey(timestamp), bz)
}
// DeleteRecordExpiryQueueTimeSlice deletes a specific record expiry queue timeslice.
func (k Keeper) DeleteRecordExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
store := ctx.KVStore(k.storeKey)
store.Delete(getRecordExpiryQueueTimeKey(timestamp))
}
// GetRecordExpiryQueueTimeSlice gets a specific record queue timeslice.
// A timeslice is a slice of CIDs corresponding to records that expire at a certain time.
func (k Keeper) GetRecordExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) []string {
store := ctx.KVStore(k.storeKey)
bz := store.Get(getRecordExpiryQueueTimeKey(timestamp))
if bz == nil {
return []string{}
}
cids, err := helpers.BytesArrToStringArr(bz)
if err != nil {
return []string{}
}
return cids
}
// InsertRecordExpiryQueue inserts a record CID to the appropriate timeslice in the record expiry queue.
func (k Keeper) InsertRecordExpiryQueue(ctx sdk.Context, val types.Record) {
expiryTime, err := time.Parse(time.RFC3339, val.ExpiryTime)
if err != nil {
panic(err)
}
timeSlice := k.GetRecordExpiryQueueTimeSlice(ctx, expiryTime)
timeSlice = append(timeSlice, val.Id)
k.SetRecordExpiryQueueTimeSlice(ctx, expiryTime, timeSlice)
}
// DeleteRecordExpiryQueue deletes a record CID from the record expiry queue.
func (k Keeper) DeleteRecordExpiryQueue(ctx sdk.Context, record types.Record) {
expiryTime, err := time.Parse(time.RFC3339, record.ExpiryTime)
if err != nil {
panic(err)
}
timeSlice := k.GetRecordExpiryQueueTimeSlice(ctx, expiryTime)
var newTimeSlice []string
for _, cid := range timeSlice {
if !bytes.Equal([]byte(cid), []byte(record.Id)) {
newTimeSlice = append(newTimeSlice, cid)
}
}
if len(newTimeSlice) == 0 {
k.DeleteRecordExpiryQueueTimeSlice(ctx, expiryTime)
} else {
k.SetRecordExpiryQueueTimeSlice(ctx, expiryTime, newTimeSlice)
}
}
// RecordExpiryQueueIterator returns all the record expiry queue timeslices from time 0 until endTime.
func (k Keeper) RecordExpiryQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
rangeEndBytes := sdk.InclusiveEndBytes(getRecordExpiryQueueTimeKey(endTime))
return store.Iterator(PrefixExpiryTimeToRecordsIndex, rangeEndBytes)
}
// GetAllExpiredRecords returns a concatenated list of all the timeslices before currTime.
func (k Keeper) GetAllExpiredRecords(ctx sdk.Context, currTime time.Time) (expiredRecordCIDs []string) {
// Gets an iterator for all timeslices from time 0 until the current block header time.
itr := k.RecordExpiryQueueIterator(ctx, ctx.BlockHeader().Time)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
timeslice, err := helpers.BytesArrToStringArr(itr.Value())
if err != nil {
panic(err)
}
expiredRecordCIDs = append(expiredRecordCIDs, timeslice...)
}
return expiredRecordCIDs
}
// ProcessRecordExpiryQueue tries to renew expiring records (by collecting rent) else marks them as deleted.
func (k Keeper) ProcessRecordExpiryQueue(ctx sdk.Context) {
cids := k.GetAllExpiredRecords(ctx, ctx.BlockHeader().Time)
for _, cid := range cids {
record := k.GetRecord(ctx, cid)
// If record doesn't have an associated bond or if bond no longer exists, mark it deleted.
if record.BondId == "" || !k.bondKeeper.HasBond(ctx, record.BondId) {
record.Deleted = true
k.PutRecord(ctx, record)
k.DeleteRecordExpiryQueue(ctx, record)
return
}
// Try to renew the record by taking rent.
k.TryTakeRecordRent(ctx, record)
}
}
// TryTakeRecordRent tries to take rent from the record bond.
func (k Keeper) TryTakeRecordRent(ctx sdk.Context, record types.Record) {
params := k.GetParams(ctx)
rent := params.RecordRent
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, record.BondId, types.RecordRentModuleAccountName, sdk.NewCoins(rent))
if sdkErr != nil {
// Insufficient funds, mark record as deleted.
record.Deleted = true
k.PutRecord(ctx, record)
k.DeleteRecordExpiryQueue(ctx, record)
return
}
// Delete old expiry queue entry, create new one.
k.DeleteRecordExpiryQueue(ctx, record)
record.ExpiryTime = ctx.BlockHeader().Time.Add(params.RecordRentDuration).Format(time.RFC3339)
k.InsertRecordExpiryQueue(ctx, record)
// Save record.
record.Deleted = false
k.PutRecord(ctx, record)
k.AddBondToRecordIndexEntry(ctx, record.BondId, record.Id)
}
// GetModuleBalances gets the nameservice module account(s) balances.
func (k Keeper) GetModuleBalances(ctx sdk.Context) []*types.AccountBalance {
var balances []*types.AccountBalance
accountNames := []string{types.RecordRentModuleAccountName, types.AuthorityRentModuleAccountName}
for _, accountName := range accountNames {
moduleAddress := k.accountKeeper.GetModuleAddress(accountName)
moduleAccount := k.accountKeeper.GetAccount(ctx, moduleAddress)
if moduleAccount != nil {
accountBalance := k.bankKeeper.GetAllBalances(ctx, moduleAddress)
balances = append(balances, &types.AccountBalance{
AccountName: accountName,
Balance: accountBalance,
})
}
}
return balances
}
func recordObjToRecord(store sdk.KVStore, codec codec.BinaryCodec, record types.Record) types.Record {
reverseNameIndexKey := GetCIDToNamesIndexKey(record.Id)
if store.Has(reverseNameIndexKey) {
names, err := helpers.BytesArrToStringArr(store.Get(reverseNameIndexKey))
if err != nil {
panic(err)
}
record.Names = names
}
return record
}
+67
View File
@@ -0,0 +1,67 @@
package keeper_test
import (
"testing"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tharsis/ethermint/app"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
nameservicekeeper "github.com/tharsis/ethermint/x/nameservice/keeper"
"github.com/tharsis/ethermint/x/nameservice/types"
)
type KeeperTestSuite struct {
suite.Suite
app *app.EthermintApp
ctx sdk.Context
queryClient types.QueryClient
accounts []sdk.AccAddress
bond bondtypes.Bond
}
func (suite *KeeperTestSuite) SetupTest() {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
querier := nameservicekeeper.Querier{Keeper: testApp.NameServiceKeeper}
queryHelper := baseapp.NewQueryServerTestHelper(ctx, testApp.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, querier)
queryClient := types.NewQueryClient(queryHelper)
suite.accounts = app.CreateRandomAccounts(1)
account := suite.accounts[0]
_ = simapp.FundAccount(testApp.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
Denom: sdk.DefaultBondDenom,
Amount: sdk.NewInt(100000000000),
}))
bond, err := testApp.BondKeeper.CreateBond(ctx, account, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000000000))))
if err != nil {
return
}
suite.bond = *bond
suite.app, suite.ctx, suite.queryClient = testApp, ctx, queryClient
}
func TestParams(t *testing.T) {
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
return genesis
})
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
expParams := types.DefaultParams()
params := testApp.NameServiceKeeper.GetParams(ctx)
require.True(t, params.Equal(expParams))
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
+281
View File
@@ -0,0 +1,281 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/nameservice/types"
)
type msgServer struct {
Keeper
}
// NewMsgServerImpl returns an implementation of the bond MsgServer interface for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}
var _ types.MsgServer = msgServer{}
func (m msgServer) SetRecord(c context.Context, msg *types.MsgSetRecord) (*types.MsgSetRecordResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
record, err := m.Keeper.ProcessSetRecord(ctx, types.MsgSetRecord{
BondId: msg.GetBondId(),
Signer: msg.GetSigner(),
Payload: msg.GetPayload(),
})
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetRecord,
sdk.NewAttribute(types.AttributeKeySigner, msg.GetSigner()),
sdk.NewAttribute(types.AttributeKeyBondId, msg.GetBondId()),
sdk.NewAttribute(types.AttributeKeyPayload, msg.Payload.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgSetRecordResponse{Id: record.Id}, nil
}
func (m msgServer) SetName(c context.Context, msg *types.MsgSetName) (*types.MsgSetNameResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessSetName(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetRecord,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyCRN, msg.Crn),
sdk.NewAttribute(types.AttributeKeyCID, msg.Cid),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgSetNameResponse{}, nil
}
func (m msgServer) ReserveName(c context.Context, msg *types.MsgReserveAuthority) (*types.MsgReserveAuthorityResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
_, err = sdk.AccAddressFromBech32(msg.Owner)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessReserveAuthority(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeReserveNameAuthority,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyName, msg.Name),
sdk.NewAttribute(types.AttributeKeyOwner, msg.Owner),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgReserveAuthorityResponse{}, nil
}
func (m msgServer) SetAuthorityBond(c context.Context, msg *types.MsgSetAuthorityBond) (*types.MsgSetAuthorityBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessSetAuthorityBond(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAuthorityBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyName, msg.Name),
sdk.NewAttribute(types.AttributeKeyBondId, msg.BondId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgSetAuthorityBondResponse{}, nil
}
func (m msgServer) DeleteName(c context.Context, msg *types.MsgDeleteNameAuthority) (*types.MsgDeleteNameAuthorityResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessDeleteName(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeDeleteName,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyCRN, msg.Crn),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgDeleteNameAuthorityResponse{}, nil
}
func (m msgServer) RenewRecord(c context.Context, msg *types.MsgRenewRecord) (*types.MsgRenewRecordResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
err = m.Keeper.ProcessRenewRecord(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRenewRecord,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyRecordId, msg.RecordId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgRenewRecordResponse{}, nil
}
func (m msgServer) AssociateBond(c context.Context, msg *types.MsgAssociateBond) (*types.MsgAssociateBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessAssociateBond(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAssociateBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyRecordId, msg.RecordId),
sdk.NewAttribute(types.AttributeKeyBondId, msg.BondId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgAssociateBondResponse{}, nil
}
func (m msgServer) DissociateBond(c context.Context, msg *types.MsgDissociateBond) (*types.MsgDissociateBondResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessDissociateBond(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeDissociateBond,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyRecordId, msg.RecordId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgDissociateBondResponse{}, nil
}
func (m msgServer) DissociateRecords(c context.Context, msg *types.MsgDissociateRecords) (*types.MsgDissociateRecordsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessDissociateRecords(ctx, *msg)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeDissociateRecords,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyBondId, msg.BondId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgDissociateRecordsResponse{}, nil
}
func (m msgServer) ReAssociateRecords(c context.Context, msg *types.MsgReAssociateRecords) (*types.MsgReAssociateRecordsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
_, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return nil, err
}
err = m.Keeper.ProcessReAssociateRecords(ctx, *msg)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeReAssociateRecords,
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
sdk.NewAttribute(types.AttributeKeyOldBondId, msg.OldBondId),
sdk.NewAttribute(types.AttributeKeyNewBondId, msg.NewBondId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeySigner, msg.Signer),
),
})
return &types.MsgReAssociateRecordsResponse{}, nil
}
+723
View File
@@ -0,0 +1,723 @@
package keeper
import (
"bytes"
"fmt"
"net/url"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
"github.com/tharsis/ethermint/x/nameservice/helpers"
"github.com/tharsis/ethermint/x/nameservice/types"
)
func getAuthorityPubKey(pubKey cryptotypes.PubKey) string {
if pubKey != nil {
return helpers.BytesToBase64(pubKey.Bytes())
}
return ""
}
// GetNameAuthorityIndexKey Generates name -> NameAuthority index key.
func GetNameAuthorityIndexKey(name string) []byte {
return append(PrefixNameAuthorityRecordIndex, []byte(name)...)
}
// GetNameRecordIndexKey Generates CRN -> NameRecord index key.
func GetNameRecordIndexKey(crn string) []byte {
return append(PrefixCRNToNameRecordIndex, []byte(crn)...)
}
func GetCIDToNamesIndexKey(id string) []byte {
return append(PrefixCIDToNamesIndex, []byte(id)...)
}
func SetNameAuthority(ctx sdk.Context, store sdk.KVStore, codec codec.BinaryCodec, name string, authority *types.NameAuthority) {
store.Set(GetNameAuthorityIndexKey(name), codec.MustMarshal(authority))
updateBlockChangeSetForNameAuthority(ctx, codec, store, name)
}
// SetNameAuthority creates the NameAuthority record.
func (k Keeper) SetNameAuthority(ctx sdk.Context, name string, authority *types.NameAuthority) {
SetNameAuthority(ctx, ctx.KVStore(k.storeKey), k.cdc, name, authority)
}
func removeAuctionToAuthorityMapping(store sdk.KVStore, auctionID string) {
store.Delete(GetAuctionToAuthorityIndexKey(auctionID))
}
func (k Keeper) RemoveAuctionToAuthorityMapping(ctx sdk.Context, auctionID string) {
removeAuctionToAuthorityMapping(ctx.KVStore(k.storeKey), auctionID)
}
// GetNameAuthority - gets a name authority from the store.
func GetNameAuthority(store sdk.KVStore, codec codec.BinaryCodec, name string) types.NameAuthority {
authorityKey := GetNameAuthorityIndexKey(name)
if !store.Has(authorityKey) {
return types.NameAuthority{}
}
bz := store.Get(authorityKey)
var obj types.NameAuthority
codec.MustUnmarshal(bz, &obj)
return obj
}
// GetNameAuthority - gets a name authority from the store.
func (k Keeper) GetNameAuthority(ctx sdk.Context, name string) types.NameAuthority {
return GetNameAuthority(ctx.KVStore(k.storeKey), k.cdc, name)
}
// HasNameAuthority - checks if a name authority entry exists.
func HasNameAuthority(store sdk.KVStore, name string) bool {
return store.Has(GetNameAuthorityIndexKey(name))
}
// HasNameAuthority - checks if a name/authority exists.
func (k Keeper) HasNameAuthority(ctx sdk.Context, name string) bool {
return HasNameAuthority(ctx.KVStore(k.storeKey), name)
}
func getBondIDToAuthoritiesIndexKey(bondID string, name string) []byte {
return append(append(PrefixBondIDToAuthoritiesIndex, []byte(bondID)...), []byte(name)...)
}
// AddBondToAuthorityIndexEntry adds the Bond ID -> [Authority] index entry.
func (k Keeper) AddBondToAuthorityIndexEntry(ctx sdk.Context, bondID string, name string) {
store := ctx.KVStore(k.storeKey)
store.Set(getBondIDToAuthoritiesIndexKey(bondID, name), []byte{})
}
// RemoveBondToAuthorityIndexEntry removes the Bond ID -> [Authority] index entry.
func (k Keeper) RemoveBondToAuthorityIndexEntry(ctx sdk.Context, bondID string, name string) {
RemoveBondToAuthorityIndexEntry(ctx.KVStore(k.storeKey), bondID, name)
}
func RemoveBondToAuthorityIndexEntry(store sdk.KVStore, bondID string, name string) {
store.Delete(getBondIDToAuthoritiesIndexKey(bondID, name))
}
func (k Keeper) updateBlockChangeSetForName(ctx sdk.Context, crn string) {
changeSet := k.getOrCreateBlockChangeSet(ctx, ctx.BlockHeight())
changeSet.Names = append(changeSet.Names, crn)
k.saveBlockChangeSet(ctx, changeSet)
}
func (k Keeper) getAuthority(ctx sdk.Context, crn string) (string, *url.URL, *types.NameAuthority, error) {
parsedCRN, err := url.Parse(crn)
if err != nil {
return "", nil, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid CRN.")
}
name := parsedCRN.Host
if !k.HasNameAuthority(ctx, name) {
return name, nil, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.")
}
authority := k.GetNameAuthority(ctx, name)
return name, parsedCRN, &authority, nil
}
func (k Keeper) checkCRNAccess(ctx sdk.Context, signer sdk.AccAddress, crn string) error {
name, parsedCRN, authority, err := k.getAuthority(ctx, crn)
if err != nil {
return err
}
formattedCRN := fmt.Sprintf("crn://%s%s", name, parsedCRN.RequestURI())
if formattedCRN != crn {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid CRN.")
}
if authority.OwnerAddress != signer.String() {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied.")
}
if authority.Status != types.AuthorityActive {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Authority is not active.")
}
if authority.BondId == "" || len(authority.BondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Authority bond not found.")
}
if authority.OwnerPublicKey == "" {
// Try to set owner public key if account has it available now.
ownerAccount := k.accountKeeper.GetAccount(ctx, signer)
pubKey := ownerAccount.GetPubKey()
if pubKey != nil {
// Update public key in authority record.
authority.OwnerPublicKey = getAuthorityPubKey(pubKey)
k.SetNameAuthority(ctx, name, authority)
}
}
return nil
}
// HasNameRecord - checks if a name record exists.
func (k Keeper) HasNameRecord(ctx sdk.Context, crn string) bool {
store := ctx.KVStore(k.storeKey)
return store.Has(GetNameRecordIndexKey(crn))
}
// GetNameRecord - gets a name record from the store.
func GetNameRecord(store sdk.KVStore, codec codec.BinaryCodec, crn string) *types.NameRecord {
nameRecordKey := GetNameRecordIndexKey(crn)
if !store.Has(nameRecordKey) {
return nil
}
bz := store.Get(nameRecordKey)
var obj types.NameRecord
codec.MustUnmarshal(bz, &obj)
return &obj
}
// GetNameRecord - gets a name record from the store.
func (k Keeper) GetNameRecord(ctx sdk.Context, crn string) *types.NameRecord {
_, _, authority, err := k.getAuthority(ctx, crn)
if err != nil || authority.Status != types.AuthorityActive {
// If authority is not active (or any other error), lookup fails.
return nil
}
nameRecord := GetNameRecord(ctx.KVStore(k.storeKey), k.cdc, crn)
// Name record may not exist.
if nameRecord == nil {
return nil
}
// Name lookup should fail if the name record is stale.
// i.e. authority was registered later than the name.
if authority.Height > nameRecord.Latest.Height {
return nil
}
return nameRecord
}
// RemoveRecordToNameMapping removes a name from the record ID -> []names index.
func RemoveRecordToNameMapping(store sdk.KVStore, id string, crn string) {
reverseNameIndexKey := GetCIDToNamesIndexKey(id)
names, _ := helpers.BytesArrToStringArr(store.Get(reverseNameIndexKey))
nameSet := helpers.SliceToSet(names)
nameSet.Remove(crn)
if nameSet.Cardinality() == 0 {
// Delete as storing empty slice throws error from baseapp.
store.Delete(reverseNameIndexKey)
} else {
data, _ := helpers.StrArrToBytesArr(helpers.SetToSlice(nameSet))
store.Set(reverseNameIndexKey, data)
}
}
// AddRecordToNameMapping adds a name to the record ID -> []names index.
func AddRecordToNameMapping(store sdk.KVStore, id string, crn string) {
reverseNameIndexKey := GetCIDToNamesIndexKey(id)
var names []string
if store.Has(reverseNameIndexKey) {
names, _ = helpers.BytesArrToStringArr(store.Get(reverseNameIndexKey))
}
nameSet := helpers.SliceToSet(names)
nameSet.Add(crn)
bz, _ := helpers.StrArrToBytesArr(helpers.SetToSlice(nameSet))
store.Set(reverseNameIndexKey, bz)
}
// SetNameRecord - sets a name record.
func SetNameRecord(store sdk.KVStore, codec codec.BinaryCodec, crn string, id string, height int64) {
nameRecordIndexKey := GetNameRecordIndexKey(crn)
var nameRecord types.NameRecord
if store.Has(nameRecordIndexKey) {
bz := store.Get(nameRecordIndexKey)
codec.MustUnmarshal(bz, &nameRecord)
nameRecord.History = append(nameRecord.History, nameRecord.Latest)
// Update old CID -> []Name index.
if nameRecord.Latest.Id != "" || len(nameRecord.Latest.Id) != 0 {
RemoveRecordToNameMapping(store, nameRecord.Latest.Id, crn)
}
}
nameRecord.Latest = &types.NameRecordEntry{
Id: id,
Height: uint64(height),
}
store.Set(nameRecordIndexKey, codec.MustMarshal(&nameRecord))
// Update new CID -> []Name index.
if id != "" {
AddRecordToNameMapping(store, id, crn)
}
}
// SetNameRecord - sets a name record.
func (k Keeper) SetNameRecord(ctx sdk.Context, crn string, id string) {
SetNameRecord(ctx.KVStore(k.storeKey), k.cdc, crn, id, ctx.BlockHeight())
// Update changeSet for name.
k.updateBlockChangeSetForName(ctx, crn)
}
// ProcessSetName creates a CRN -> Record ID mapping.
func (k Keeper) ProcessSetName(ctx sdk.Context, msg types.MsgSetName) error {
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return err
}
err = k.checkCRNAccess(ctx, signerAddress, msg.Crn)
if err != nil {
return err
}
nameRecord := k.GetNameRecord(ctx, msg.Crn)
if nameRecord != nil && nameRecord.Latest.Id == msg.Cid {
return nil
}
k.SetNameRecord(ctx, msg.Crn, msg.Cid)
return nil
}
// ListNameRecords - get all name records.
func (k Keeper) ListNameRecords(ctx sdk.Context) []types.NameEntry {
var nameEntries []types.NameEntry
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixCRNToNameRecordIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var record types.NameRecord
k.cdc.MustUnmarshal(bz, &record)
nameEntries = append(nameEntries, types.NameEntry{
Name: string(itr.Key()[len(PrefixCRNToNameRecordIndex):]),
Entry: &record,
})
}
}
return nameEntries
}
// ProcessReserveSubAuthority reserves a sub-authority.
func (k Keeper) ProcessReserveSubAuthority(ctx sdk.Context, name string, msg types.MsgReserveAuthority) error {
// Get parent authority name.
names := strings.Split(name, ".")
parent := strings.Join(names[1:], ".")
// Check if parent authority exists.
if !k.HasNameAuthority(ctx, parent) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Parent authority not found.")
}
parentAuthority := k.GetNameAuthority(ctx, parent)
// Sub-authority creator needs to be the owner of the parent authority.
if parentAuthority.OwnerAddress != msg.Signer {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied.")
}
// Sub-authority owner defaults to parent authority owner.
subAuthorityOwner := msg.Signer
if len(msg.Owner) != 0 {
// Override sub-authority owner if provided in message.
subAuthorityOwner = msg.Owner
}
sdkErr := k.createAuthority(ctx, name, subAuthorityOwner, false)
if sdkErr != nil {
return sdkErr
}
return nil
}
func GetAuctionToAuthorityIndexKey(auctionID string) []byte {
return append(PrefixAuctionToAuthorityNameIndex, []byte(auctionID)...)
}
func (k Keeper) AddAuctionToAuthorityMapping(ctx sdk.Context, auctionID string, name string) {
store := ctx.KVStore(k.storeKey)
store.Set(GetAuctionToAuthorityIndexKey(auctionID), []byte(name))
}
func (k Keeper) createAuthority(ctx sdk.Context, name string, owner string, isRoot bool) error {
moduleParams := k.GetParams(ctx)
if k.HasNameAuthority(ctx, name) {
authority := k.GetNameAuthority(ctx, name)
if authority.Status != types.AuthorityExpired {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name already reserved.")
}
}
ownerAddress, err := sdk.AccAddressFromBech32(owner)
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid owner address.")
}
ownerAccount := k.accountKeeper.GetAccount(ctx, ownerAddress)
if ownerAccount == nil {
return sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "Account not found.")
}
authority := types.NameAuthority{
OwnerPublicKey: getAuthorityPubKey(ownerAccount.GetPubKey()),
OwnerAddress: owner,
Height: uint64(ctx.BlockHeight()),
Status: types.AuthorityActive,
AuctionId: "",
BondId: "",
ExpiryTime: ctx.BlockTime().Add(moduleParams.AuthorityGracePeriod),
}
if isRoot && moduleParams.AuthorityAuctionEnabled {
// If auctions are enabled, clear out owner fields. They will be set after a winner is picked.
authority.OwnerAddress = ""
authority.OwnerPublicKey = ""
// Reset bond ID if required.
if authority.BondId != "" || len(authority.BondId) != 0 {
k.RemoveBondToAuthorityIndexEntry(ctx, authority.BondId, name)
authority.BondId = ""
}
params := auctiontypes.Params{
CommitsDuration: moduleParams.AuthorityAuctionCommitsDuration,
RevealsDuration: moduleParams.AuthorityAuctionRevealsDuration,
CommitFee: moduleParams.AuthorityAuctionCommitFee,
RevealFee: moduleParams.AuthorityAuctionRevealFee,
MinimumBid: moduleParams.AuthorityAuctionMinimumBid,
}
// Create an auction.
msg := auctiontypes.NewMsgCreateAuction(params, ownerAddress)
auction, sdkErr := k.auctionKeeper.CreateAuction(ctx, msg)
if sdkErr != nil {
return sdkErr
}
// Create auction ID -> authority name index.
k.AddAuctionToAuthorityMapping(ctx, auction.Id, name)
authority.Status = types.AuthorityUnderAuction
authority.AuctionId = auction.Id
authority.ExpiryTime = auction.RevealsEndTime.Add(moduleParams.AuthorityGracePeriod)
}
k.SetNameAuthority(ctx, name, &authority)
k.InsertAuthorityExpiryQueue(ctx, name, authority.ExpiryTime)
return nil
}
// ProcessReserveAuthority reserves a name authority.
func (k Keeper) ProcessReserveAuthority(ctx sdk.Context, msg types.MsgReserveAuthority) error {
crn := fmt.Sprintf("crn://%s", msg.GetName())
parsedCrn, err := url.Parse(crn)
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name")
}
name := parsedCrn.Host
if fmt.Sprintf("crn://%s", name) != crn {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name")
}
if strings.Contains(name, ".") {
return k.ProcessReserveSubAuthority(ctx, name, msg)
}
err = k.createAuthority(ctx, name, msg.GetSigner(), true)
if err != nil {
return err
}
return nil
}
func (k Keeper) ProcessSetAuthorityBond(ctx sdk.Context, msg types.MsgSetAuthorityBond) error {
name := msg.GetName()
signer := msg.GetSigner()
if !k.HasNameAuthority(ctx, name) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.")
}
authority := k.GetNameAuthority(ctx, name)
if authority.OwnerAddress != signer {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied")
}
if !k.bondKeeper.HasBond(ctx, msg.BondId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
//
bond := k.bondKeeper.GetBond(ctx, msg.BondId)
if bond.Owner != signer {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
// No-op if bond hasn't changed.
if authority.BondId == msg.BondId {
return nil
}
// Remove old bond ID mapping, if any.
if authority.BondId != "" {
k.RemoveBondToAuthorityIndexEntry(ctx, authority.BondId, name)
}
// Update bond ID for authority.
authority.BondId = bond.Id
k.SetNameAuthority(ctx, name, &authority)
// Add new bond ID mapping.
k.AddBondToAuthorityIndexEntry(ctx, authority.BondId, name)
return nil
}
// ProcessDeleteName removes a CRN -> Record ID mapping.
func (k Keeper) ProcessDeleteName(ctx sdk.Context, msg types.MsgDeleteNameAuthority) error {
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
return err
}
err = k.checkCRNAccess(ctx, signerAddress, msg.Crn)
if err != nil {
return err
}
if !k.HasNameRecord(ctx, msg.Crn) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name not found.")
}
// Set CID to empty string.
k.SetNameRecord(ctx, msg.Crn, "")
return nil
}
func (k Keeper) GetAuthorityExpiryQueue(ctx sdk.Context) []*types.ExpiryQueueRecord {
var authorities []*types.ExpiryQueueRecord
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixExpiryTimeToAuthoritiesIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
var record []string
record, err := helpers.BytesArrToStringArr(itr.Value())
if err != nil {
return authorities
}
authorities = append(authorities, &types.ExpiryQueueRecord{
Id: string(itr.Key()[len(PrefixExpiryTimeToAuthoritiesIndex):]),
Value: record,
})
}
return authorities
}
// ResolveCRN resolves a CRN to a record.
func (k Keeper) ResolveCRN(ctx sdk.Context, crn string) *types.Record {
_, _, authority, err := k.getAuthority(ctx, crn)
if err != nil || authority.Status != types.AuthorityActive {
// If authority is not active (or any other error), resolution fails.
return nil
}
// Name should not resolve if it's stale.
// i.e. authority was registered later than the name.
record, nameRecord := ResolveCRN(ctx.KVStore(k.storeKey), crn, k, ctx)
if authority.Height > nameRecord.Latest.Height {
return nil
}
return record
}
// ResolveCRN resolves a CRN to a record.
func ResolveCRN(store sdk.KVStore, crn string, k Keeper, c sdk.Context) (*types.Record, *types.NameRecord) {
nameKey := GetNameRecordIndexKey(crn)
if store.Has(nameKey) {
bz := store.Get(nameKey)
var obj types.NameRecord
k.cdc.MustUnmarshal(bz, &obj)
recordExists := k.HasRecord(c, obj.Latest.Id)
if !recordExists || obj.Latest.Id == "" {
return nil, &obj
}
record := k.GetRecord(c, obj.Latest.Id)
return &record, &obj
}
return nil, nil
}
func getAuthorityExpiryQueueTimeKey(timestamp time.Time) []byte {
timeBytes := sdk.FormatTimeBytes(timestamp)
return append(PrefixExpiryTimeToAuthoritiesIndex, timeBytes...)
}
func (k Keeper) InsertAuthorityExpiryQueue(ctx sdk.Context, name string, expiryTime time.Time) {
timeSlice := k.GetAuthorityExpiryQueueTimeSlice(ctx, expiryTime)
timeSlice = append(timeSlice, name)
k.SetAuthorityExpiryQueueTimeSlice(ctx, expiryTime, timeSlice)
}
func (k Keeper) GetAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) []string {
store := ctx.KVStore(k.storeKey)
bz := store.Get(getAuthorityExpiryQueueTimeKey(timestamp))
if bz == nil {
return []string{}
}
names, err := helpers.BytesArrToStringArr(bz)
if err != nil {
return []string{}
}
return names
}
func (k Keeper) SetAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time, names []string) {
store := ctx.KVStore(k.storeKey)
bz, _ := helpers.StrArrToBytesArr(names)
store.Set(getAuthorityExpiryQueueTimeKey(timestamp), bz)
}
// ProcessAuthorityExpiryQueue tries to renew expiring authorities (by collecting rent) else marks them as expired.
func (k Keeper) ProcessAuthorityExpiryQueue(ctx sdk.Context) {
names := k.GetAllExpiredAuthorities(ctx, ctx.BlockHeader().Time)
for _, name := range names {
authority := k.GetNameAuthority(ctx, name)
// If authority doesn't have an associated bond or if bond no longer exists, mark it expired.
if authority.BondId == "" || !k.bondKeeper.HasBond(ctx, authority.BondId) {
authority.Status = types.AuthorityExpired
k.SetNameAuthority(ctx, name, &authority)
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
ctx.Logger().Info(fmt.Sprintf("Marking authority expired as no bond present: %s", name))
return
}
// Try to renew the authority by taking rent.
k.TryTakeAuthorityRent(ctx, name, authority)
}
}
// DeleteAuthorityExpiryQueueTimeSlice deletes a specific authority expiry queue timeslice.
func (k Keeper) DeleteAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
store := ctx.KVStore(k.storeKey)
store.Delete(getAuthorityExpiryQueueTimeKey(timestamp))
}
// DeleteAuthorityExpiryQueue deletes an authority name from the authority expiry queue.
func (k Keeper) DeleteAuthorityExpiryQueue(ctx sdk.Context, name string, authority types.NameAuthority) {
timeSlice := k.GetAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime)
newTimeSlice := []string{}
for _, existingName := range timeSlice {
if !bytes.Equal([]byte(existingName), []byte(name)) {
newTimeSlice = append(newTimeSlice, existingName)
}
}
if len(newTimeSlice) == 0 {
k.DeleteAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime)
} else {
k.SetAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime, newTimeSlice)
}
}
// GetAllExpiredAuthorities returns a concatenated list of all the timeslices before currTime.
func (k Keeper) GetAllExpiredAuthorities(ctx sdk.Context, currTime time.Time) (expiredAuthorityNames []string) {
// Gets an iterator for all timeslices from time 0 until the current block header time.
itr := k.AuthorityExpiryQueueIterator(ctx, ctx.BlockHeader().Time)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
timeslice := []string{}
timeslice, err := helpers.BytesArrToStringArr(itr.Value())
if err != nil {
panic(err)
}
expiredAuthorityNames = append(expiredAuthorityNames, timeslice...)
}
return expiredAuthorityNames
}
// AuthorityExpiryQueueIterator returns all the authority expiry queue timeslices from time 0 until endTime.
func (k Keeper) AuthorityExpiryQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
rangeEndBytes := sdk.InclusiveEndBytes(getAuthorityExpiryQueueTimeKey(endTime))
return store.Iterator(PrefixExpiryTimeToAuthoritiesIndex, rangeEndBytes)
}
// TryTakeAuthorityRent tries to take rent from the authority bond.
func (k Keeper) TryTakeAuthorityRent(ctx sdk.Context, name string, authority types.NameAuthority) {
ctx.Logger().Info(fmt.Sprintf("Trying to take rent for authority: %s", name))
params := k.GetParams(ctx)
rent := params.AuthorityRent
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, authority.BondId, types.AuthorityRentModuleAccountName, sdk.NewCoins(rent))
if sdkErr != nil {
// Insufficient funds, mark authority as expired.
authority.Status = types.AuthorityExpired
k.SetNameAuthority(ctx, name, &authority)
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
ctx.Logger().Info(fmt.Sprintf("Insufficient funds in owner account to pay authority rent, marking as expired: %s", name))
return
}
// Delete old expiry queue entry, create new one.
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
authority.ExpiryTime = ctx.BlockTime().Add(params.AuthorityRentDuration)
k.InsertAuthorityExpiryQueue(ctx, name, authority.ExpiryTime)
// Save authority.
authority.Status = types.AuthorityActive
k.SetNameAuthority(ctx, name, &authority)
k.AddBondToAuthorityIndexEntry(ctx, authority.BondId, name)
ctx.Logger().Info(fmt.Sprintf("Authority rent paid successfully: %s", name))
}
// ListNameAuthorityRecords - get all name authority records.
func (k Keeper) ListNameAuthorityRecords(ctx sdk.Context) map[string]types.NameAuthority {
nameAuthorityRecords := make(map[string]types.NameAuthority)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, PrefixNameAuthorityRecordIndex)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
bz := store.Get(itr.Key())
if bz != nil {
var record types.NameAuthority
k.cdc.MustUnmarshal(bz, &record)
nameAuthorityRecords[string(itr.Key()[len(PrefixNameAuthorityRecordIndex):])] = record
}
}
return nameAuthorityRecords
}
+17
View File
@@ -0,0 +1,17 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// GetParams - Get all parameters as types.Params.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSubspace.GetParamSet(ctx, &params)
return
}
// SetParams - set the params.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSubspace.SetParamSet(ctx, &params)
}
+306
View File
@@ -0,0 +1,306 @@
package keeper
import (
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// RecordKeeper exposes the bare minimal read-only API for other modules.
type RecordKeeper struct {
auctionKeeper auctionkeeper.Keeper
storeKey sdk.StoreKey // Unexposed key to access store from sdk.Context
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
}
func (k RecordKeeper) UsesAuction(ctx sdk.Context, auctionID string) bool {
return k.GetAuctionToAuthorityMapping(ctx, auctionID) != ""
}
func (k RecordKeeper) OnAuction(ctx sdk.Context, auctionId string) {
updateBlockChangeSetForAuction(ctx, k, auctionId)
}
func (k RecordKeeper) OnAuctionBid(ctx sdk.Context, auctionID string, bidderAddress string) {
updateBlockChangeSetForAuctionBid(ctx, k, auctionID, bidderAddress)
}
func (k RecordKeeper) OnAuctionWinnerSelected(ctx sdk.Context, auctionID string) {
// Update authority status based on auction status/winner.
name := k.GetAuctionToAuthorityMapping(ctx, auctionID)
if name == "" {
// We don't know about this auction, ignore.
ctx.Logger().Info(fmt.Sprintf("Ignoring auction notification, name mapping not found: %s", auctionID))
return
}
store := ctx.KVStore(k.storeKey)
if !HasNameAuthority(store, name) {
// We don't know about this authority, ignore.
ctx.Logger().Info(fmt.Sprintf("Ignoring auction notification, authority not found: %s", auctionID))
return
}
authority := GetNameAuthority(store, k.cdc, name)
auctionObj := k.auctionKeeper.GetAuction(ctx, auctionID)
if auctionObj.Status == auctiontypes.AuctionStatusCompleted {
store := ctx.KVStore(k.storeKey)
if auctionObj.WinnerAddress != "" {
// Mark authority owner and change status to active.
authority.OwnerAddress = auctionObj.WinnerAddress
authority.Status = types.AuthorityActive
// Reset bond ID if required, as owner has changed.
if authority.BondId != "" {
RemoveBondToAuthorityIndexEntry(store, authority.BondId, name)
authority.BondId = ""
}
// Update height for updated/changed authority (owner).
// Can be used to check if names are older than the authority itself (stale names).
authority.Height = uint64(ctx.BlockHeight())
ctx.Logger().Info(fmt.Sprintf("Winner selected, marking authority as active: %s", name))
} else {
// Mark as expired.
authority.Status = types.AuthorityExpired
ctx.Logger().Info(fmt.Sprintf("No winner, marking authority as expired: %s", name))
}
authority.AuctionId = ""
SetNameAuthority(ctx, store, k.cdc, name, &authority)
// Forget about this auction now, we no longer need it.
removeAuctionToAuthorityMapping(store, auctionID)
} else {
ctx.Logger().Info(fmt.Sprintf("Ignoring auction notification, status: %s", auctionObj.Status))
}
}
// Record keeper implements the bond usage keeper interface.
var _ bondtypes.BondUsageKeeper = (*RecordKeeper)(nil)
var _ auctiontypes.AuctionUsageKeeper = (*RecordKeeper)(nil)
// ModuleName returns the module name.
func (k RecordKeeper) ModuleName() string {
return types.ModuleName
}
func (k RecordKeeper) GetAuctionToAuthorityMapping(ctx sdk.Context, auctionID string) string {
store := ctx.KVStore(k.storeKey)
auctionToAuthorityIndexKey := GetAuctionToAuthorityIndexKey(auctionID)
if store.Has(auctionToAuthorityIndexKey) {
bz := store.Get(auctionToAuthorityIndexKey)
return string(bz)
}
return ""
}
// UsesBond returns true if the bond has associated records.
func (k RecordKeeper) UsesBond(ctx sdk.Context, bondId string) bool {
bondIDPrefix := append(PrefixBondIDToRecordsIndex, []byte(bondId)...)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, bondIDPrefix)
defer itr.Close()
return itr.Valid()
}
// RemoveBondToRecordIndexEntry removes the Bond ID -> [Record] index entry.
func (k Keeper) RemoveBondToRecordIndexEntry(ctx sdk.Context, bondID string, id string) {
store := ctx.KVStore(k.storeKey)
store.Delete(getBondIDToRecordsIndexKey(bondID, id))
}
// NewRecordKeeper creates new instances of the nameservice RecordKeeper
func NewRecordKeeper(auctionKeeper auctionkeeper.Keeper, storeKey sdk.StoreKey, cdc codec.BinaryCodec) RecordKeeper {
return RecordKeeper{
auctionKeeper: auctionKeeper,
storeKey: storeKey,
cdc: cdc,
}
}
// QueryRecordsByBond - get all records for the given bond.
func (k RecordKeeper) QueryRecordsByBond(ctx sdk.Context, bondID string) []types.Record {
var records []types.Record
bondIDPrefix := append(PrefixBondIDToRecordsIndex, []byte(bondID)...)
store := ctx.KVStore(k.storeKey)
itr := sdk.KVStorePrefixIterator(store, bondIDPrefix)
defer itr.Close()
for ; itr.Valid(); itr.Next() {
cid := itr.Key()[len(bondIDPrefix):]
bz := store.Get(append(PrefixCIDToRecordIndex, cid...))
if bz != nil {
var obj types.Record
k.cdc.MustUnmarshal(bz, &obj)
records = append(records, recordObjToRecord(store, k.cdc, obj))
}
}
return records
}
// ProcessRenewRecord renews a record.
func (k Keeper) ProcessRenewRecord(ctx sdk.Context, msg types.MsgRenewRecord) error {
if !k.HasRecord(ctx, msg.RecordId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Record not found.")
}
// Check if renewal is required (i.e. expired record marked as deleted).
record := k.GetRecord(ctx, msg.RecordId)
expiryTime, err := time.Parse(time.RFC3339, record.ExpiryTime)
if err != nil {
panic(err)
}
if !record.Deleted || expiryTime.After(ctx.BlockTime()) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Renewal not required.")
}
recordType := record.ToRecordType()
err = k.processRecord(ctx, &recordType, true)
if err != nil {
return err
}
return nil
}
// ProcessAssociateBond associates a record with a bond.
func (k Keeper) ProcessAssociateBond(ctx sdk.Context, msg types.MsgAssociateBond) error {
if !k.HasRecord(ctx, msg.RecordId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Record not found.")
}
if !k.bondKeeper.HasBond(ctx, msg.BondId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
// Check if already associated with a bond.
record := k.GetRecord(ctx, msg.RecordId)
if record.BondId != "" || len(record.BondId) != 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond already exists.")
}
// Only the bond owner can associate a record with the bond.
bond := k.bondKeeper.GetBond(ctx, msg.BondId)
if msg.Signer != bond.Owner {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
record.BondId = msg.BondId
k.PutRecord(ctx, record)
k.AddBondToRecordIndexEntry(ctx, msg.BondId, msg.RecordId)
// Required so that renewal is triggered (with new bond ID) for expired records.
if record.Deleted {
k.InsertRecordExpiryQueue(ctx, record)
}
return nil
}
// ProcessDissociateBond dissociates a record from its bond.
func (k Keeper) ProcessDissociateBond(ctx sdk.Context, msg types.MsgDissociateBond) error {
if !k.HasRecord(ctx, msg.RecordId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Record not found.")
}
// Check if associated with a bond.
record := k.GetRecord(ctx, msg.RecordId)
bondID := record.BondId
if bondID == "" || len(bondID) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond not found.")
}
// Only the bond owner can dissociate a record from the bond.
bond := k.bondKeeper.GetBond(ctx, bondID)
if msg.Signer != bond.Owner {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
// Clear bond ID.
record.BondId = ""
k.PutRecord(ctx, record)
k.RemoveBondToRecordIndexEntry(ctx, bondID, record.Id)
return nil
}
// ProcessDissociateRecords dissociates all records associated with a given bond.
func (k Keeper) ProcessDissociateRecords(ctx sdk.Context, msg types.MsgDissociateRecords) error {
if !k.bondKeeper.HasBond(ctx, msg.BondId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
}
// Only the bond owner can dissociate all records from the bond.
bond := k.bondKeeper.GetBond(ctx, msg.BondId)
if msg.Signer != bond.Owner {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
}
// Dissociate all records from the bond.
records := k.recordKeeper.QueryRecordsByBond(ctx, msg.BondId)
for _, record := range records {
// Clear bond ID.
record.BondId = ""
k.PutRecord(ctx, record)
k.RemoveBondToRecordIndexEntry(ctx, msg.BondId, record.Id)
}
return nil
}
// ProcessReAssociateRecords switches records from and old to new bond.
func (k Keeper) ProcessReAssociateRecords(ctx sdk.Context, msg types.MsgReAssociateRecords) error {
if !k.bondKeeper.HasBond(ctx, msg.OldBondId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Old bond not found.")
}
if !k.bondKeeper.HasBond(ctx, msg.NewBondId) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "New bond not found.")
}
// Only the bond owner can re-associate all records.
oldBond := k.bondKeeper.GetBond(ctx, msg.OldBondId)
if msg.Signer != oldBond.Owner {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Old bond owner mismatch.")
}
newBond := k.bondKeeper.GetBond(ctx, msg.NewBondId)
if msg.Signer != newBond.Owner {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "New bond owner mismatch.")
}
// Re-associate all records.
records := k.recordKeeper.QueryRecordsByBond(ctx, msg.OldBondId)
for _, record := range records {
// Switch bond ID.
record.BondId = msg.NewBondId
k.PutRecord(ctx, record)
k.RemoveBondToRecordIndexEntry(ctx, msg.OldBondId, record.Id)
k.AddBondToRecordIndexEntry(ctx, msg.NewBondId, record.Id)
// Required so that renewal is triggered (with new bond ID) for expired records.
if record.Deleted {
k.InsertRecordExpiryQueue(ctx, record)
}
}
return nil
}
+99
View File
@@ -0,0 +1,99 @@
package keeper
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/x/nameservice/helpers"
"github.com/tharsis/ethermint/x/nameservice/types"
)
func GetBlockChangeSetIndexKey(height int64) []byte {
return append(PrefixBlockChangesetIndex, helpers.Int64ToBytes(height)...)
}
func getOrCreateBlockChangeset(store sdk.KVStore, codec codec.BinaryCodec, height int64) *types.BlockChangeSet {
bz := store.Get(GetBlockChangeSetIndexKey(height))
if bz != nil {
var changeSet types.BlockChangeSet
err := codec.Unmarshal(bz, &changeSet)
if err != nil {
return nil
}
return &changeSet
}
return &types.BlockChangeSet{
Height: height,
Records: []string{},
Names: []string{},
Auctions: []string{},
AuctionBids: []*types.AuctionBidInfo{},
}
}
func updateBlockChangeSetForAuction(ctx sdk.Context, k RecordKeeper, id string) {
changeSet := getOrCreateBlockChangeset(ctx.KVStore(k.storeKey), k.cdc, ctx.BlockHeight())
found := false
for _, elem := range changeSet.Auctions {
if id == elem {
found = true
break
}
}
if !found {
changeSet.Auctions = append(changeSet.Auctions, id)
saveBlockChangeSet(ctx.KVStore(k.storeKey), k.cdc, changeSet)
}
}
func saveBlockChangeSet(store sdk.KVStore, codec codec.BinaryCodec, changeset *types.BlockChangeSet) {
bz := codec.MustMarshal(changeset)
store.Set(GetBlockChangeSetIndexKey(changeset.Height), bz)
}
func (k Keeper) saveBlockChangeSet(ctx sdk.Context, changeSet *types.BlockChangeSet) {
saveBlockChangeSet(ctx.KVStore(k.storeKey), k.cdc, changeSet)
}
func (k Keeper) updateBlockChangeSetForRecord(ctx sdk.Context, id string) {
changeSet := k.getOrCreateBlockChangeSet(ctx, ctx.BlockHeight())
changeSet.Records = append(changeSet.Records, id)
k.saveBlockChangeSet(ctx, changeSet)
}
func (k Keeper) getOrCreateBlockChangeSet(ctx sdk.Context, height int64) *types.BlockChangeSet {
store := ctx.KVStore(k.storeKey)
bz := store.Get(GetBlockChangeSetIndexKey(height))
if bz != nil {
var changeSet types.BlockChangeSet
err := k.cdc.Unmarshal(bz, &changeSet)
if err != nil {
return nil
}
return &changeSet
}
return &types.BlockChangeSet{
Height: height,
Records: []string{},
Names: []string{},
Auctions: []string{},
AuctionBids: []*types.AuctionBidInfo{},
}
}
func updateBlockChangeSetForAuctionBid(ctx sdk.Context, k RecordKeeper, id, bidderAddress string) {
changeSet := getOrCreateBlockChangeset(ctx.KVStore(k.storeKey), k.cdc, ctx.BlockHeight())
changeSet.AuctionBids = append(changeSet.AuctionBids, &types.AuctionBidInfo{AuctionId: id, BidderAddress: bidderAddress})
saveBlockChangeSet(ctx.KVStore(k.storeKey), k.cdc, changeSet)
}
func updateBlockChangeSetForNameAuthority(ctx sdk.Context, codec codec.BinaryCodec, store sdk.KVStore, name string) {
changeSet := getOrCreateBlockChangeset(store, codec, ctx.BlockHeight())
changeSet.Authorities = append(changeSet.Authorities, name)
saveBlockChangeSet(store, codec, changeSet)
}
+134
View File
@@ -0,0 +1,134 @@
package nameservice
import (
"context"
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/nameservice/client/cli"
"github.com/tharsis/ethermint/x/nameservice/keeper"
"github.com/tharsis/ethermint/x/nameservice/types"
)
// type check to ensure the interface is properly implemented
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)
// AppModuleBasic _ app module Basics object
type AppModuleBasic struct{}
func (a AppModuleBasic) Name() string {
return types.ModuleName
}
func (a AppModuleBasic) RegisterLegacyAminoCodec(amino *codec.LegacyAmino) {
types.RegisterLegacyAminoCodec(amino)
}
func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
types.RegisterInterfaces(registry)
}
func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
return cdc.MustMarshalJSON(types.DefaultGenesisState())
}
func (a AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, message json.RawMessage) error {
var data types.GenesisState
if err := cdc.UnmarshalJSON(message, &data); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}
return types.ValidateGenesis(data)
}
func (a AppModuleBasic) RegisterRESTRoutes(context client.Context, router *mux.Router) {
}
func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
if err != nil {
panic(err)
}
}
func (a AppModuleBasic) GetTxCmd() *cobra.Command {
return cli.NewTxCmd()
}
func (a AppModuleBasic) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd()
}
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper
}
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate {
var genesisState types.GenesisState
cdc.MustUnmarshalJSON(message, &genesisState)
return InitGenesis(ctx, am.keeper, genesisState)
}
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return cdc.MustMarshalJSON(&gs)
}
func (am AppModule) RegisterInvariants(registry sdk.InvariantRegistry) {
keeper.RegisterInvariants(registry, am.keeper)
}
func (am AppModule) Route() sdk.Route {
return sdk.Route{}
}
func (am AppModule) QuerierRoute() string {
return types.QuerierRoute
}
func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier {
return nil
}
func (am AppModule) RegisterServices(cfg module.Configurator) {
querier := keeper.Querier{Keeper: am.keeper}
types.RegisterQueryServer(cfg.QueryServer(), querier)
msgServer := keeper.NewMsgServerImpl(am.keeper)
types.RegisterMsgServer(cfg.MsgServer(), msgServer)
}
func (am AppModule) ConsensusVersion() uint64 {
return 1
}
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)
}
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
}
// NewAppModule creates a new AppModule Object
func NewAppModule(k keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: k,
}
}
+53
View File
@@ -0,0 +1,53 @@
package types
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/msgservice"
)
// RegisterLegacyAminoCodec registers the necessary x/bond interfaces and concrete types
// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgSetName{}, "nameservice/SetName", nil)
cdc.RegisterConcrete(&MsgReserveAuthority{}, "nameservice/ReserveAuthority", nil)
cdc.RegisterConcrete(&MsgDeleteNameAuthority{}, "nameservice/DeleteAuthority", nil)
cdc.RegisterConcrete(&MsgSetAuthorityBond{}, "nameservice/SetAuthorityBond", nil)
cdc.RegisterConcrete(&MsgSetRecord{}, "nameservice/SetRecord", nil)
cdc.RegisterConcrete(&MsgRenewRecord{}, "nameservice/RenewRecord", nil)
cdc.RegisterConcrete(&MsgAssociateBond{}, "nameservice/AssociateBond", nil)
cdc.RegisterConcrete(&MsgDissociateBond{}, "nameservice/DissociateBond", nil)
cdc.RegisterConcrete(&MsgDissociateRecords{}, "nameservice/DissociateRecords", nil)
cdc.RegisterConcrete(&MsgReAssociateRecords{}, "nameservice/ReassociateRecords", nil)
}
func RegisterInterfaces(registry types.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgSetName{},
&MsgReserveAuthority{},
&MsgDeleteNameAuthority{},
&MsgSetAuthorityBond{},
&MsgSetRecord{},
&MsgRenewRecord{},
&MsgAssociateBond{},
&MsgDissociateBond{},
&MsgDissociateRecords{},
&MsgReAssociateRecords{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
var (
amino = codec.NewLegacyAmino()
ModuleCdc = codec.NewAminoCodec(amino)
)
func init() {
RegisterLegacyAminoCodec(amino)
cryptocodec.RegisterCrypto(amino)
amino.Seal()
}
+25
View File
@@ -0,0 +1,25 @@
package types
const (
EventTypeSetRecord = "set"
EventTypeDeleteName = "delete-name"
EventTypeReserveNameAuthority = "reserve-authority"
EventTypeAuthorityBond = "authority-bond"
EventTypeRenewRecord = "renew-record"
EventTypeAssociateBond = "associate-bond"
EventTypeDissociateBond = "dissociate-bond"
EventTypeDissociateRecords = "dissociate-record"
EventTypeReAssociateRecords = "re-associate-records"
AttributeKeySigner = "signer"
AttributeKeyOwner = "owner"
AttributeKeyBondId = "bond-id"
AttributeKeyPayload = "payload"
AttributeKeyOldBondId = "old-bond-id"
AttributeKeyNewBondId = "new-bond-id"
AttributeKeyCID = "cid"
AttributeKeyName = "name"
AttributeKeyCRN = "crn"
AttributeKeyRecordId = "record-id"
AttributeValueCategory = ModuleName
)
+27
View File
@@ -0,0 +1,27 @@
package types
func NewGenesisState(params Params, records []Record, authorities []AuthorityEntry, names []NameEntry) GenesisState {
return GenesisState{
Params: params,
Records: records,
Authorities: authorities,
Names: names,
}
}
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
// chain config values.
func DefaultGenesisState() *GenesisState {
return &GenesisState{
Params: DefaultParams(),
}
}
func ValidateGenesis(data GenesisState) error {
err := data.Params.Validate()
if err != nil {
return err
}
return nil
}
+522
View File
@@ -0,0 +1,522 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: vulcanize/nameservice/v1beta1/genesis.proto
package types
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the nameservice module's genesis state.
type GenesisState struct {
// params defines all the params of nameservice module.
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// records
Records []Record `protobuf:"bytes,2,rep,name=records,proto3" json:"records" json:"records" yaml:"records"`
// authorities
Authorities []AuthorityEntry `protobuf:"bytes,3,rep,name=authorities,proto3" json:"authorities" json:"authorities" yaml:"authorities"`
// names
Names []NameEntry `protobuf:"bytes,4,rep,name=names,proto3" json:"names" json:"names" yaml:"names"`
}
func (m *GenesisState) Reset() { *m = GenesisState{} }
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
func (*GenesisState) ProtoMessage() {}
func (*GenesisState) Descriptor() ([]byte, []int) {
return fileDescriptor_fe7037a2b22e67ef, []int{0}
}
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GenesisState) XXX_Merge(src proto.Message) {
xxx_messageInfo_GenesisState.Merge(m, src)
}
func (m *GenesisState) XXX_Size() int {
return m.Size()
}
func (m *GenesisState) XXX_DiscardUnknown() {
xxx_messageInfo_GenesisState.DiscardUnknown(m)
}
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
func (m *GenesisState) GetParams() Params {
if m != nil {
return m.Params
}
return Params{}
}
func (m *GenesisState) GetRecords() []Record {
if m != nil {
return m.Records
}
return nil
}
func (m *GenesisState) GetAuthorities() []AuthorityEntry {
if m != nil {
return m.Authorities
}
return nil
}
func (m *GenesisState) GetNames() []NameEntry {
if m != nil {
return m.Names
}
return nil
}
func init() {
proto.RegisterType((*GenesisState)(nil), "vulcanize.nameservice.v1beta1.GenesisState")
}
func init() {
proto.RegisterFile("vulcanize/nameservice/v1beta1/genesis.proto", fileDescriptor_fe7037a2b22e67ef)
}
var fileDescriptor_fe7037a2b22e67ef = []byte{
// 347 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0xd2, 0xb1, 0x4a, 0xfb, 0x40,
0x1c, 0x07, 0xf0, 0xe4, 0xdf, 0xfe, 0x2b, 0xa4, 0x4e, 0xc1, 0x21, 0x16, 0x9a, 0xd6, 0x42, 0xa1,
0x20, 0xcd, 0x59, 0xdd, 0xdc, 0x8c, 0x88, 0xe0, 0x20, 0x12, 0x37, 0xb7, 0x6b, 0xfc, 0x99, 0x9c,
0x34, 0xb9, 0x72, 0xf7, 0x6b, 0x31, 0x0e, 0x3e, 0x83, 0x4f, 0xe0, 0xf3, 0x74, 0xec, 0xe8, 0x54,
0xa4, 0x7d, 0x03, 0x9f, 0x40, 0x7a, 0x97, 0x68, 0x5c, 0x5a, 0xb7, 0x5c, 0xf8, 0x7e, 0xbf, 0x9f,
0x40, 0xce, 0x3a, 0x9c, 0x4e, 0x46, 0x21, 0x4d, 0xd9, 0x33, 0x90, 0x94, 0x26, 0x20, 0x41, 0x4c,
0x59, 0x08, 0x64, 0x3a, 0x18, 0x02, 0xd2, 0x01, 0x89, 0x20, 0x05, 0xc9, 0xa4, 0x37, 0x16, 0x1c,
0xb9, 0xdd, 0xfc, 0x0e, 0x7b, 0xa5, 0xb0, 0x97, 0x87, 0x1b, 0x7b, 0x11, 0x8f, 0xb8, 0x4a, 0x92,
0xf5, 0x93, 0x2e, 0x35, 0xc8, 0x66, 0xa1, 0x3c, 0xa4, 0x0a, 0x9d, 0xb7, 0x8a, 0xb5, 0x7b, 0xa9,
0xdd, 0x5b, 0xa4, 0x08, 0xf6, 0xb9, 0x55, 0x1b, 0x53, 0x41, 0x13, 0xe9, 0x98, 0x6d, 0xb3, 0x57,
0x3f, 0xee, 0x7a, 0x1b, 0xbf, 0xc3, 0xbb, 0x51, 0x61, 0xbf, 0x3a, 0x5b, 0xb4, 0x8c, 0x20, 0xaf,
0xda, 0x0f, 0xd6, 0x8e, 0x80, 0x90, 0x8b, 0x7b, 0xe9, 0xfc, 0x6b, 0x57, 0xfe, 0xb0, 0x12, 0xa8,
0xb4, 0xdf, 0x5d, 0xaf, 0x7c, 0x2e, 0x5a, 0xcd, 0x47, 0xc9, 0xd3, 0xd3, 0x4e, 0xbe, 0xd1, 0x69,
0x67, 0x34, 0x19, 0xfd, 0x1c, 0x83, 0x62, 0xdc, 0x7e, 0xb1, 0xea, 0x74, 0x82, 0x31, 0x17, 0x0c,
0x19, 0x48, 0xa7, 0xa2, 0xac, 0xfe, 0x16, 0xeb, 0x2c, 0x6f, 0x64, 0x17, 0x29, 0x8a, 0xcc, 0xef,
0xe7, 0x66, 0x57, 0x9b, 0xa5, 0xbd, 0xc2, 0x2d, 0xbf, 0x0a, 0xca, 0xa0, 0x4d, 0xad, 0xff, 0x4a,
0x70, 0xaa, 0x4a, 0xee, 0x6d, 0x91, 0xaf, 0x69, 0x02, 0x1a, 0x3d, 0xc8, 0xd1, 0x7d, 0x8d, 0xaa,
0x70, 0xc1, 0xe9, 0x43, 0xa0, 0x97, 0xfd, 0xab, 0xd9, 0xd2, 0x35, 0xe7, 0x4b, 0xd7, 0xfc, 0x58,
0xba, 0xe6, 0xeb, 0xca, 0x35, 0xe6, 0x2b, 0xd7, 0x78, 0x5f, 0xb9, 0xc6, 0xdd, 0x51, 0xc4, 0x30,
0x9e, 0x0c, 0xbd, 0x90, 0x27, 0x04, 0x63, 0x2a, 0x24, 0x93, 0x04, 0x30, 0x06, 0x91, 0xb0, 0x14,
0xc9, 0xd3, 0xaf, 0x0b, 0x80, 0xd9, 0x18, 0xe4, 0xb0, 0xa6, 0xfe, 0xf9, 0xc9, 0x57, 0x00, 0x00,
0x00, 0xff, 0xff, 0xbe, 0x6b, 0x6e, 0x5b, 0x88, 0x02, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Names) > 0 {
for iNdEx := len(m.Names) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Names[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x22
}
}
if len(m.Authorities) > 0 {
for iNdEx := len(m.Authorities) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Authorities[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
if len(m.Records) > 0 {
for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Records[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
{
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.Params.Size()
n += 1 + l + sovGenesis(uint64(l))
if len(m.Records) > 0 {
for _, e := range m.Records {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if len(m.Authorities) > 0 {
for _, e := range m.Authorities {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if len(m.Names) > 0 {
for _, e := range m.Names {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Records = append(m.Records, Record{})
if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Authorities", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Authorities = append(m.Authorities, AuthorityEntry{})
if err := m.Authorities[len(m.Authorities)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Names", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Names = append(m.Names, NameEntry{})
if err := m.Names[len(m.Names)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)
+21
View File
@@ -0,0 +1,21 @@
package types
const (
// ModuleName is the name of the staking module
ModuleName = "nameservice"
// RecordRentModuleAccountName is the name of the module account that keeps track of record rents paid.
RecordRentModuleAccountName = "record_rent"
// AuthorityRentModuleAccountName is the name of the module account that keeps track of authority rents paid.
AuthorityRentModuleAccountName = "authority_rent"
// StoreKey is the string store representation
StoreKey = ModuleName
// QuerierRoute is the querier route for the staking module
QuerierRoute = ModuleName
// RouterKey is the msg router key for the staking module
RouterKey = ModuleName
)
+189
View File
@@ -0,0 +1,189 @@
package types
import (
"net/url"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
_ sdk.Msg = &MsgSetName{}
_ sdk.Msg = &MsgReserveAuthority{}
_ sdk.Msg = &MsgSetAuthorityBond{}
_ sdk.Msg = &MsgDeleteNameAuthority{}
)
// NewMsgSetName is the constructor function for MsgSetName.
func NewMsgSetName(crn string, cid string, signer sdk.AccAddress) MsgSetName {
return MsgSetName{
Crn: crn,
Cid: cid,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgSetName) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgSetName) Type() string { return "set-name" }
// ValidateBasic Implements Msg.
func (msg MsgSetName) ValidateBasic() error {
if msg.Crn == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "CRN is required.")
}
if msg.Cid == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "CID is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer")
}
return nil
}
// GetSignBytes gets the sign bytes for the msg MsgSetName
func (msg MsgSetName) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgSetName) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgReserveAuthority is the constructor function for MsgReserveName.
func NewMsgReserveAuthority(name string, signer sdk.AccAddress, owner sdk.AccAddress) MsgReserveAuthority {
return MsgReserveAuthority{
Name: name,
Owner: owner.String(),
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgReserveAuthority) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgReserveAuthority) Type() string { return "reserve-authority" }
// ValidateBasic Implements Msg.
func (msg MsgReserveAuthority) ValidateBasic() error {
if len(msg.Name) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer")
}
return nil
}
// GetSignBytes gets the sign bytes for the msg MsgSetName
func (msg MsgReserveAuthority) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgReserveAuthority) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgSetAuthorityBond is the constructor function for MsgSetAuthorityBond.
func NewMsgSetAuthorityBond(name string, bondId string, signer sdk.AccAddress) MsgSetAuthorityBond {
return MsgSetAuthorityBond{
Name: name,
Signer: signer.String(),
BondId: bondId,
}
}
// Route Implements Msg.
func (msg MsgSetAuthorityBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgSetAuthorityBond) Type() string { return "authority-bond" }
// ValidateBasic Implements Msg.
func (msg MsgSetAuthorityBond) ValidateBasic() error {
if len(msg.Name) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
if len(msg.BondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "bond id is required.")
}
return nil
}
// GetSignBytes gets the sign bytes for the msg MsgSetName
func (msg MsgSetAuthorityBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgSetAuthorityBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgDeleteNameAuthority is the constructor function for MsgDeleteNameAuthority.
func NewMsgDeleteNameAuthority(crn string, signer sdk.AccAddress) MsgDeleteNameAuthority {
return MsgDeleteNameAuthority{
Crn: crn,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgDeleteNameAuthority) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgDeleteNameAuthority) Type() string { return "delete-name" }
// ValidateBasic Implements Msg.
func (msg MsgDeleteNameAuthority) ValidateBasic() error {
if len(msg.Crn) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "crn is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
_, err := url.Parse(msg.Crn)
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid crn.")
}
return nil
}
// GetSignBytes gets the sign bytes for the msg MsgSetName
func (msg MsgDeleteNameAuthority) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgDeleteNameAuthority) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
File diff suppressed because it is too large Load Diff
+239
View File
@@ -0,0 +1,239 @@
package types
import (
"bytes"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"time"
)
// Default parameter values.
var (
// DefaultRecordRent is the default record rent for 1 time period (see expiry time).
DefaultRecordRent = sdk.NewInt(1000000)
// DefaultRecordExpiryTime is the default record expiry time (1 year).
DefaultRecordExpiryTime = time.Hour * 24 * 365
DefaultAuthorityRent = sdk.NewInt(1000000)
DefaultAuthorityExpiryTime = time.Hour * 24 * 365
DefaultAuthorityGracePeriod = time.Hour * 24 * 2
DefaultAuthorityAuctionEnabled = false
DefaultCommitsDuration = time.Hour * 24
DefaultRevealsDuration = time.Hour * 24
DefaultCommitFee = sdk.NewInt(1000000)
DefaultRevealFee = sdk.NewInt(1000000)
DefaultMinimumBid = sdk.NewInt(5000000)
)
// Keys for parameter access
var (
KeyRecordRent = []byte("RecordRent")
KeyRecordRentDuration = []byte("RecordRentDuration")
KeyAuthorityRent = []byte("AuthorityRent")
KeyAuthorityRentDuration = []byte("AuthorityRentDuration")
KeyAuthorityGracePeriod = []byte("AuthorityGracePeriod")
KeyAuthorityAuctionEnabled = []byte("AuthorityAuctionEnabled")
KeyCommitsDuration = []byte("AuthorityAuctionCommitsDuration")
KeyRevealsDuration = []byte("AuthorityAuctionRevealsDuration")
KeyCommitFee = []byte("AuthorityAuctionCommitFee")
KeyRevealFee = []byte("AuthorityAuctionRevealFee")
KeyMinimumBid = []byte("AuthorityAuctionMinimumBid")
)
var _ paramtypes.ParamSet = &Params{}
// ParamKeyTable ParamTable for staking module
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}
// ParamSetPairs returns the parameter set pairs.
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(KeyRecordRent, &p.RecordRent, validateRecordRent),
paramtypes.NewParamSetPair(KeyRecordRentDuration, &p.RecordRentDuration, validateRecordRentDuration),
paramtypes.NewParamSetPair(KeyAuthorityRent, &p.AuthorityRent, validateAuthorityRent),
paramtypes.NewParamSetPair(KeyAuthorityRentDuration, &p.AuthorityRentDuration, validateAuthorityRentDuration),
paramtypes.NewParamSetPair(KeyAuthorityGracePeriod, &p.AuthorityGracePeriod, validateAuthorityGracePeriod),
paramtypes.NewParamSetPair(KeyAuthorityAuctionEnabled, &p.AuthorityAuctionEnabled, validateAuthorityAuctionEnabled),
paramtypes.NewParamSetPair(KeyCommitsDuration, &p.AuthorityAuctionCommitsDuration, validateCommitsDuration),
paramtypes.NewParamSetPair(KeyRevealsDuration, &p.AuthorityAuctionRevealsDuration, validateRevealsDuration),
paramtypes.NewParamSetPair(KeyCommitFee, &p.AuthorityAuctionCommitFee, validateCommitFee),
paramtypes.NewParamSetPair(KeyRevealFee, &p.AuthorityAuctionRevealFee, validateRevealFee),
paramtypes.NewParamSetPair(KeyMinimumBid, &p.AuthorityAuctionMinimumBid, validateMinimumBid),
}
}
// NewParams creates a new Params instance
func NewParams(recordRent sdk.Coin, recordRentDuration time.Duration,
authorityRent sdk.Coin, authorityRentDuration time.Duration, authorityGracePeriod time.Duration,
authorityAuctionEnabled bool, commitsDuration time.Duration, revealsDuration time.Duration,
commitFee sdk.Coin, revealFee sdk.Coin, minimumBid sdk.Coin) Params {
return Params{
RecordRent: recordRent,
RecordRentDuration: recordRentDuration,
AuthorityRent: authorityRent,
AuthorityRentDuration: authorityRentDuration,
AuthorityGracePeriod: authorityGracePeriod,
AuthorityAuctionEnabled: authorityAuctionEnabled,
AuthorityAuctionCommitsDuration: commitsDuration,
AuthorityAuctionRevealsDuration: revealsDuration,
AuthorityAuctionCommitFee: commitFee,
AuthorityAuctionRevealFee: revealFee,
AuthorityAuctionMinimumBid: minimumBid,
}
}
// Equal returns a boolean determining if two Params types are identical.
func (p Params) Equal(p2 Params) bool {
bz1 := ModuleCdc.MustMarshalLengthPrefixed(&p)
bz2 := ModuleCdc.MustMarshalLengthPrefixed(&p2)
return bytes.Equal(bz1, bz2)
}
// DefaultParams returns a default set of parameters.
func DefaultParams() Params {
return NewParams(
sdk.NewCoin(sdk.DefaultBondDenom, DefaultRecordRent), DefaultRecordExpiryTime,
sdk.NewCoin(sdk.DefaultBondDenom, DefaultAuthorityRent),
DefaultAuthorityExpiryTime, DefaultAuthorityGracePeriod, DefaultAuthorityAuctionEnabled, DefaultCommitsDuration,
DefaultRevealsDuration,
sdk.NewCoin(sdk.DefaultBondDenom, DefaultCommitFee),
sdk.NewCoin(sdk.DefaultBondDenom, DefaultRevealFee),
sdk.NewCoin(sdk.DefaultBondDenom, DefaultMinimumBid),
)
}
func validateAmount(name string, i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.Amount.IsNegative() {
return fmt.Errorf("%s can't be negative", name)
}
return nil
}
func validateDuration(name string, i interface{}) error {
v, ok := i.(time.Duration)
if !ok {
return fmt.Errorf("%s invalid parameter type: %T", name, i)
}
if v <= 0 {
return fmt.Errorf("%s must be a positive integer", name)
}
return nil
}
func validateRecordRent(i interface{}) error {
return validateAmount("RecordRent", i)
}
func validateRecordRentDuration(i interface{}) error {
return validateDuration("RecordRentDuration", i)
}
func validateAuthorityRent(i interface{}) error {
return validateAmount("AuthorityRent", i)
}
func validateAuthorityRentDuration(i interface{}) error {
return validateDuration("AuthorityRentDuration", i)
}
func validateAuthorityGracePeriod(i interface{}) error {
return validateDuration("AuthorityGracePeriod", i)
}
func validateAuthorityAuctionEnabled(i interface{}) error {
_, ok := i.(bool)
if !ok {
return fmt.Errorf("%s invalid parameter type: %T", "AuthorityAuctionEnabled", i)
}
return nil
}
func validateCommitsDuration(i interface{}) error {
return validateDuration("AuthorityCommitsDuration", i)
}
func validateRevealsDuration(i interface{}) error {
return validateDuration("AuthorityRevealsDuration", i)
}
func validateCommitFee(i interface{}) error {
return validateAmount("AuthorityCommitFee", i)
}
func validateRevealFee(i interface{}) error {
return validateAmount("AuthorityRevealFee", i)
}
func validateMinimumBid(i interface{}) error {
return validateAmount("AuthorityMinimumBid", i)
}
// Validate a set of params.
func (p Params) Validate() error {
if err := validateRecordRent(p.RecordRent); err != nil {
return err
}
if err := validateRecordRentDuration(p.RecordRentDuration); err != nil {
return err
}
if err := validateAuthorityRent(p.AuthorityRent); err != nil {
return err
}
if err := validateAuthorityRentDuration(p.AuthorityRentDuration); err != nil {
return err
}
if err := validateAuthorityGracePeriod(p.AuthorityGracePeriod); err != nil {
return err
}
if err := validateAuthorityAuctionEnabled(p.AuthorityAuctionEnabled); err != nil {
return err
}
if err := validateCommitsDuration(p.AuthorityAuctionCommitsDuration); err != nil {
return err
}
if err := validateRevealsDuration(p.AuthorityAuctionRevealsDuration); err != nil {
return err
}
if err := validateCommitFee(p.AuthorityAuctionCommitFee); err != nil {
return err
}
if err := validateRevealFee(p.AuthorityAuctionRevealFee); err != nil {
return err
}
if err := validateMinimumBid(p.AuthorityAuctionMinimumBid); err != nil {
return err
}
return nil
}
+6272
View File
File diff suppressed because it is too large Load Diff
+1002
View File
File diff suppressed because it is too large Load Diff
+257
View File
@@ -0,0 +1,257 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
_ sdk.Msg = &MsgSetRecord{}
_ sdk.Msg = &MsgRenewRecord{}
_ sdk.Msg = &MsgAssociateBond{}
_ sdk.Msg = &MsgDissociateBond{}
_ sdk.Msg = &MsgDissociateRecords{}
_ sdk.Msg = &MsgReAssociateRecords{}
)
// NewMsgSetRecord is the constructor function for MsgSetRecord.
func NewMsgSetRecord(payload Payload, bondID string, signer sdk.AccAddress) MsgSetRecord {
return MsgSetRecord{
Payload: payload,
BondId: bondID,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgSetRecord) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgSetRecord) Type() string { return "set-record" }
func (msg MsgSetRecord) ValidateBasic() error {
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer)
}
owners := msg.Payload.Record.Owners
for _, owner := range owners {
if owner == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Record owner not set.")
}
}
if len(msg.BondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond ID is required.")
}
return nil
}
func (msg MsgSetRecord) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// GetSignBytes gets the sign bytes for the msg MsgCreateBond
func (msg MsgSetRecord) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// NewMsgRenewRecord is the constructor function for MsgRenewRecord.
func NewMsgRenewRecord(recordId string, signer sdk.AccAddress) MsgRenewRecord {
return MsgRenewRecord{
RecordId: recordId,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgRenewRecord) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgRenewRecord) Type() string { return "renew-record" }
// ValidateBasic Implements Msg.
func (msg MsgRenewRecord) ValidateBasic() error {
if len(msg.RecordId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
return nil
}
// GetSignBytes gets the sign bytes for Msg
func (msg MsgRenewRecord) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgRenewRecord) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgAssociateBond is the constructor function for MsgAssociateBond.
func NewMsgAssociateBond(recordId, bondId string, signer sdk.AccAddress) MsgAssociateBond {
return MsgAssociateBond{
BondId: bondId,
RecordId: recordId,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgAssociateBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgAssociateBond) Type() string { return "associate-bond" }
// ValidateBasic Implements Msg.
func (msg MsgAssociateBond) ValidateBasic() error {
if len(msg.RecordId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.")
}
if len(msg.BondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bond id is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
return nil
}
// GetSignBytes gets the sign bytes for Msg
func (msg MsgAssociateBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgAssociateBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgDissociateBond is the constructor function for MsgDissociateBond.
func NewMsgDissociateBond(recordId string, signer sdk.AccAddress) MsgDissociateBond {
return MsgDissociateBond{
RecordId: recordId,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgDissociateBond) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgDissociateBond) Type() string { return "dissociate-bond" }
// ValidateBasic Implements Msg.
func (msg MsgDissociateBond) ValidateBasic() error {
if len(msg.RecordId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
return nil
}
// GetSignBytes gets the sign bytes for Msg
func (msg MsgDissociateBond) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgDissociateBond) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgDissociateRecords is the constructor function for MsgDissociateRecords.
func NewMsgDissociateRecords(bondId string, signer sdk.AccAddress) MsgDissociateRecords {
return MsgDissociateRecords{
BondId: bondId,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgDissociateRecords) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgDissociateRecords) Type() string { return "dissociate-records" }
// ValidateBasic Implements Msg.
func (msg MsgDissociateRecords) ValidateBasic() error {
if len(msg.BondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "bond id is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
return nil
}
// GetSignBytes gets the sign bytes for Msg
func (msg MsgDissociateRecords) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgDissociateRecords) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
// NewMsgReAssociateRecords is the constructor function for MsgReAssociateRecords.
func NewMsgReAssociateRecords(oldBondId, newBondId string, signer sdk.AccAddress) MsgReAssociateRecords {
return MsgReAssociateRecords{
OldBondId: oldBondId,
NewBondId: newBondId,
Signer: signer.String(),
}
}
// Route Implements Msg.
func (msg MsgReAssociateRecords) Route() string { return RouterKey }
// Type Implements Msg.
func (msg MsgReAssociateRecords) Type() string { return "reassociate-records" }
// ValidateBasic Implements Msg.
func (msg MsgReAssociateRecords) ValidateBasic() error {
if len(msg.OldBondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "old-bond-id is required.")
}
if len(msg.NewBondId) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "new-bond-id is required.")
}
if len(msg.Signer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.")
}
return nil
}
// GetSignBytes gets the sign bytes for Msg
func (msg MsgReAssociateRecords) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(&msg)
return sdk.MustSortJSON(bz)
}
// GetSigners Implements Msg.
func (msg MsgReAssociateRecords) GetSigners() []sdk.AccAddress {
accAddr, _ := sdk.AccAddressFromBech32(msg.Signer)
return []sdk.AccAddress{accAddr}
}
+4643
View File
File diff suppressed because it is too large Load Diff
+131
View File
@@ -0,0 +1,131 @@
package types
import (
"crypto/sha256"
canonicalJson "github.com/gibson042/canonicaljson-go"
"github.com/tharsis/ethermint/x/nameservice/helpers"
)
const (
AuthorityActive = "active"
AuthorityExpired = "expired"
AuthorityUnderAuction = "auction"
)
// PayloadType represents a signed record payload that can be serialized from/to YAML.
type PayloadType struct {
Record map[string]interface{} `json:"record"`
Signatures []Signature `json:"signatures"`
}
// ToPayload converts PayloadType to Payload object.
// Why? Because go-amino can't handle maps: https://github.com/tendermint/go-amino/issues/4.
func (payloadObj *PayloadType) ToPayload() Payload {
var payload = Payload{
Record: &Record{
Deleted: false,
Owners: nil,
Attributes: helpers.BytesToBase64(helpers.MarshalMapToJSONBytes(payloadObj.Record)),
},
Signatures: payloadObj.Signatures,
}
return payload
}
// ToReadablePayload converts Payload to PayloadType
// It will unmarshal with record attributes
func (payload Payload) ToReadablePayload() PayloadType {
var payloadType PayloadType
payloadType.Record = helpers.UnMarshalMapFromJSONBytes(helpers.BytesFromBase64(payload.Record.Attributes))
payloadType.Signatures = payload.Signatures
return payloadType
}
// Record to Record Type for human-readable attributes
func (r *Record) ToRecordType() RecordType {
var resourceObj RecordType
resourceObj.Id = r.Id
resourceObj.BondId = r.BondId
resourceObj.CreateTime = r.CreateTime
resourceObj.ExpiryTime = r.ExpiryTime
resourceObj.Deleted = r.Deleted
resourceObj.Owners = r.Owners
resourceObj.Names = r.Names
resourceObj.Attributes = helpers.UnMarshalMapFromJSONBytes(helpers.BytesFromBase64(r.Attributes))
return resourceObj
}
// RecordType represents a WNS record.
type RecordType struct {
Id string `json:"id,omitempty"`
Names []string `json:"names,omitempty"`
BondId string `json:"bondId,omitempty"`
CreateTime string `json:"createTime,omitempty"`
ExpiryTime string `json:"expiryTime,omitempty"`
Deleted bool `json:"deleted,omitempty"`
Owners []string `json:"owners,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"`
}
// ToRecordObj converts Record to RecordObj.
// Why? Because go-amino can't handle maps: https://github.com/tendermint/go-amino/issues/4.
func (r *RecordType) ToRecordObj() Record {
var resourceObj Record
resourceObj.Id = r.Id
resourceObj.BondId = r.BondId
resourceObj.CreateTime = r.CreateTime
resourceObj.ExpiryTime = r.ExpiryTime
resourceObj.Deleted = r.Deleted
resourceObj.Owners = r.Owners
resourceObj.Attributes = helpers.BytesToBase64(helpers.MarshalMapToJSONBytes(r.Attributes))
return resourceObj
}
// CanonicalJSON returns the canonical JSON representation of the record.
func (r *RecordType) CanonicalJSON() []byte {
bytes, err := canonicalJson.Marshal(r.Attributes)
if err != nil {
panic("Record marshal error.")
}
return bytes
}
// GetSignBytes generates a record hash to be signed.
func (r *RecordType) GetSignBytes() ([]byte, []byte) {
// Double SHA256 hash.
// Input to the first round of hashing.
bytes := r.CanonicalJSON()
// First round.
first := sha256.New()
first.Write(bytes)
firstHash := first.Sum(nil)
// Second round of hashing takes as input the output of the first round.
second := sha256.New()
second.Write(firstHash)
secondHash := second.Sum(nil)
return secondHash, bytes
}
// GetCID gets the record CID.
func (r *RecordType) GetCID() (string, error) {
id, err := helpers.GetCid(r.CanonicalJSON())
if err != nil {
return "", err
}
return id, nil
}