Skip to content

Commit

Permalink
feat: implementation of MsgBuyDataAccessNFT Tx (#306)
Browse files Browse the repository at this point in the history
* remove contract related tx and query
add code id and contract address to genesis params

* change README

* fix test

* fix lint and add validation of params

* feat: add query params

* fix

* fix

* feat: add MsgBuyDataAccessNFT Tx

* add genesis of white list

* add test of BuyDataAccessNFT Tx

* merge

* review applied

* change name

* add TODO: pagination

* apply changed design

* refactor errors

* rename tx

* fix
  • Loading branch information
0xHansLee authored Apr 25, 2022
1 parent 2c1ecbe commit d0f76dc
Show file tree
Hide file tree
Showing 20 changed files with 476 additions and 259 deletions.
10 changes: 4 additions & 6 deletions proto/panacea/datapool/v2/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import "panacea/datapool/v2/pool.proto";

// GenesisState defines the datapool module's genesis state.
message GenesisState {
repeated panacea.datapool.v2.DataValidator data_validators = 1;
uint64 next_pool_number = 2;
repeated Pool pools = 3;
Params params = 4 [
(gogoproto.nullable) = false
];
repeated DataValidator data_validators = 1 [(gogoproto.nullable) = false];
uint64 next_pool_number = 2;
repeated Pool pools = 3 [(gogoproto.nullable) = false];
Params params = 4 [(gogoproto.nullable) = false];
}

// Params define parameters of datapool module
Expand Down
12 changes: 6 additions & 6 deletions proto/panacea/datapool/v2/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ service Msg {
// SellData defines a method for selling data
rpc SellData(MsgSellData) returns (MsgSellDataResponse);

// BuyDataAccessNFT defines a method for buying data access NFT
rpc BuyDataAccessNFT(MsgBuyDataAccessNFT) returns (MsgBuyDataAccessNFTResponse);
// BuyDataPass defines a method for buying data access NFT
rpc BuyDataPass(MsgBuyDataPass) returns (MsgBuyDataPassResponse);

// RedeemDataAccessNFT defines a method for redeeming data access NFT to get data
rpc RedeemDataAccessNFT(MsgRedeemDataAccessNFT) returns (MsgRedeemDataAccessNFTResponse);
Expand Down Expand Up @@ -75,16 +75,16 @@ message MsgSellDataResponse {
cosmos.base.v1beta1.Coin accum_pool_share_token = 1; // denom: DP-{pood-id}
}

// MsgBuyDataAccessNFT defines the Msg/BuyDataAccessNFT request type.
message MsgBuyDataAccessNFT {
// MsgBuyDataPass defines the Msg/BuyDataPass request type.
message MsgBuyDataPass {
uint64 pool_id = 1;
uint64 round = 2;
cosmos.base.v1beta1.Coin payment = 3;
string buyer = 4; // 'panacea1' address of buyer
}

// MsgBuyDataAccessNFTResponse defines the Msg/BuyDataAccessNFT response type.
message MsgBuyDataAccessNFTResponse {
// MsgBuyDataPassResponse defines the Msg/BuyDataAccessNFT response type.
message MsgBuyDataPassResponse {
uint64 pool_id = 1;
uint64 round = 2;
uint64 nft_id = 3;
Expand Down
10 changes: 2 additions & 8 deletions types/testsuite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/medibloc/panacea-core/v2/types/assets"
aolkeeper "github.com/medibloc/panacea-core/v2/x/aol/keeper"
aoltypes "github.com/medibloc/panacea-core/v2/x/aol/types"
burnkeeper "github.com/medibloc/panacea-core/v2/x/burn/keeper"
Expand Down Expand Up @@ -243,13 +242,8 @@ func (suite *TestSuite) SetupTest() {
)
suite.DataPoolMsgServer = datapoolkeeper.NewMsgServerImpl(suite.DataPoolKeeper)

dataPoolGenState := datapooltypes.GenesisState{
DataValidators: []*datapooltypes.DataValidator{},
NextPoolNumber: 1,
Pools: []*datapooltypes.Pool{},
Params: datapooltypes.Params{DataPoolDeposit: sdk.NewCoin(assets.MicroMedDenom, sdk.NewInt(1000000))},
}
datapool.InitGenesis(suite.Ctx, suite.DataPoolKeeper, dataPoolGenState)
dataPoolGenState := datapooltypes.DefaultGenesis()
datapool.InitGenesis(suite.Ctx, suite.DataPoolKeeper, *dataPoolGenState)
}

func (suite *TestSuite) BeforeTest(suiteName, testName string) {
Expand Down
2 changes: 2 additions & 0 deletions x/datapool/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(CmdUpdateDataValidator())
cmd.AddCommand(CmdCreatePool())
cmd.AddCommand(CmdSellData())
cmd.AddCommand(CmdBuyDataAccessNFT())

return cmd
}
48 changes: 47 additions & 1 deletion x/datapool/client/cli/txPool.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"strconv"
"time"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -176,4 +177,49 @@ func readCertificateFromFile(file string) (*types.DataValidationCertificate, err
}

return &cert, nil
}
}
func CmdBuyDataAccessNFT() *cobra.Command {
cmd := &cobra.Command{
Use: "buy-data-access-nft [pool ID] [round] [payment]",
Short: "buy data access NFT",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

buyer := clientCtx.GetFromAddress()

poolID, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

round, err := strconv.ParseUint(args[1], 10, 64)
if err != nil {
return err
}

payment, err := sdk.ParseCoinNormalized(args[2])
if err != nil {
return err
}

msg := &types.MsgBuyDataPass{
PoolId: poolID,
Round: round,
Payment: &payment,
Buyer: buyer.String(),
}

if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)
return cmd
}
13 changes: 5 additions & 8 deletions x/datapool/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
k.SetPoolNumber(ctx, genState.NextPoolNumber)

for _, dataValidator := range genState.DataValidators {
err := k.SetDataValidator(ctx, *dataValidator)
err := k.SetDataValidator(ctx, dataValidator)
if err != nil {
panic(err)
}
}

for _, pool := range genState.Pools {
k.SetPool(ctx, pool)
k.SetPool(ctx, &pool)
}

// this line is used by starport scaffolding # genesis/module/init

// this line is used by starport scaffolding # ibc/genesis/init
Expand All @@ -38,18 +39,14 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
panic(err)
}

for _, val := range dataValidators {
genesis.DataValidators = append(genesis.DataValidators, &val)
}
genesis.DataValidators = append(genesis.DataValidators, dataValidators...)

pools, err := k.GetAllPools(ctx)
if err != nil {
panic(err)
}

for _, pool := range pools {
genesis.Pools = append(genesis.Pools, &pool)
}
genesis.Pools = append(genesis.Pools, pools...)

genesis.Params = k.GetParams(ctx)

Expand Down
25 changes: 13 additions & 12 deletions x/datapool/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var (
curator = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
NFTPrice = sdk.NewCoin(assets.MicroMedDenom, sdk.NewInt(10000000))
downloadPeriod = time.Duration(time.Second * 100000000)
poolID = uint64(1)
)

type genesisTestSuite struct {
Expand All @@ -31,15 +32,15 @@ func TestGenesisTestSuite(t *testing.T) {
}

func (suite genesisTestSuite) TestDataPoolInitGenesis() {
var dataValidators []*types.DataValidator
var dataValidators []types.DataValidator

dataValidator := makeSampleDataValidator()

dataValidators = append(dataValidators, dataValidator)

pool := makeSamplePool()

pools := []*types.Pool{pool}
pools := []types.Pool{pool}

params := types.DefaultParams()

Expand All @@ -55,15 +56,15 @@ func (suite genesisTestSuite) TestDataPoolInitGenesis() {
// check data validator
dataValidatorFromKeeper, err := suite.DataPoolKeeper.GetDataValidator(suite.Ctx, dataVal)
suite.Require().NoError(err)
suite.Require().Equal(*dataValidator, dataValidatorFromKeeper)
suite.Require().Equal(dataValidator, dataValidatorFromKeeper)

// check the next pool number
suite.Require().Equal(uint64(2), suite.DataPoolKeeper.GetNextPoolNumber(suite.Ctx))

// check pool
poolFromKeeper, err := suite.DataPoolKeeper.GetPool(suite.Ctx, uint64(1))
suite.Require().NoError(err)
suite.Require().Equal(pool, poolFromKeeper)
suite.Require().Equal(pool, *poolFromKeeper)

// check params
paramsFromKeeper := suite.DataPoolKeeper.GetParams(suite.Ctx)
Expand All @@ -73,12 +74,12 @@ func (suite genesisTestSuite) TestDataPoolInitGenesis() {
func (suite genesisTestSuite) TestDataPoolExportGenesis() {
// register data validator
dataValidator := makeSampleDataValidator()
err := suite.DataPoolKeeper.SetDataValidator(suite.Ctx, *dataValidator)
err := suite.DataPoolKeeper.SetDataValidator(suite.Ctx, dataValidator)
suite.Require().NoError(err)

// create pool
pool := makeSamplePool()
suite.DataPoolKeeper.SetPool(suite.Ctx, pool)
suite.DataPoolKeeper.SetPool(suite.Ctx, &pool)
suite.DataPoolKeeper.SetPoolNumber(suite.Ctx, uint64(2))

// set params
Expand All @@ -91,21 +92,21 @@ func (suite genesisTestSuite) TestDataPoolExportGenesis() {
suite.Require().Len(genesisState.DataValidators, 1)
}

func makeSampleDataValidator() *types.DataValidator {
return &types.DataValidator{
func makeSampleDataValidator() types.DataValidator {
return types.DataValidator{
Address: dataVal.String(),
Endpoint: "https://my-validator.org",
}
}

func makeSamplePool() *types.Pool {
return &types.Pool{
PoolId: 1,
func makeSamplePool() types.Pool {
return types.Pool{
PoolId: poolID,
PoolAddress: types.NewPoolAddress(uint64(1)).String(),
Round: 1,
PoolParams: makeSamplePoolParams(),
CurNumData: 0,
NumIssuedNfts: 0,
NumIssuedNfts: 1,
Status: types.PENDING,
Curator: curator.String(),
}
Expand Down
3 changes: 3 additions & 0 deletions x/datapool/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgCreatePool:
res, err := msgServer.CreatePool(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgBuyDataPass:
res, err := msgServer.BuyDataPass(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgSellData:
res, err := msgServer.SellData(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
Expand Down
16 changes: 14 additions & 2 deletions x/datapool/keeper/msg_server_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,20 @@ func (m msgServer) SellData(goCtx context.Context, msg *types.MsgSellData) (*typ
}, nil
}

func (m msgServer) BuyDataAccessNFT(goCtx context.Context, msg *types.MsgBuyDataAccessNFT) (*types.MsgBuyDataAccessNFTResponse, error) {
return &types.MsgBuyDataAccessNFTResponse{}, nil
func (m msgServer) BuyDataPass(goCtx context.Context, msg *types.MsgBuyDataPass) (*types.MsgBuyDataPassResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

buyer, err := sdk.AccAddressFromBech32(msg.Buyer)
if err != nil {
return nil, err
}

err = m.Keeper.BuyDataPass(ctx, buyer, msg.PoolId, msg.Round, *msg.Payment)
if err != nil {
return nil, err
}

return &types.MsgBuyDataPassResponse{PoolId: msg.PoolId, Round: msg.Round}, nil
}

func (m msgServer) RedeemDataAccessNFT(goCtx context.Context, msg *types.MsgRedeemDataAccessNFT) (*types.MsgRedeemDataAccessNFTResponse, error) {
Expand Down
Loading

0 comments on commit d0f76dc

Please sign in to comment.