remove slightly unecessary ID type

This commit is contained in:
rhuairahrighairigh 2020-01-01 14:11:19 +00:00
parent db3c39aaa5
commit 983de010df
14 changed files with 65 additions and 80 deletions

View File

@ -7,8 +7,8 @@ import (
// EndBlocker runs at the end of every block.
func EndBlocker(ctx sdk.Context, k Keeper) {
var expiredAuctions []ID
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id ID) bool {
var expiredAuctions []uint64
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) bool {
expiredAuctions = append(expiredAuctions, id)
return false
})

View File

@ -22,7 +22,6 @@ const (
var (
// functions aliases
NewIDFromString = types.NewIDFromString
NewForwardAuction = types.NewForwardAuction
NewReverseAuction = types.NewReverseAuction
NewForwardReverseAuction = types.NewForwardReverseAuction
@ -46,7 +45,6 @@ var (
type (
Auction = types.Auction
BaseAuction = types.BaseAuction
ID = types.ID
ForwardAuction = types.ForwardAuction
ReverseAuction = types.ReverseAuction
ForwardReverseAuction = types.ForwardReverseAuction

View File

@ -2,6 +2,7 @@ package cli
import (
"fmt"
"strconv"
"github.com/kava-labs/kava/x/auction/types"
"github.com/spf13/cobra"
@ -39,7 +40,7 @@ func GetCmdPlaceBid(cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
id, err := types.NewIDFromString(args[0])
id, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
fmt.Printf("invalid auction id - %s \n", string(args[0]))
return err

View File

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
@ -45,7 +46,7 @@ func bidHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
strBid := vars[restBid]
strLot := vars[restLot]
auctionID, err := types.NewIDFromString(strAuctionID)
auctionID, err := strconv.ParseUint(strAuctionID, 10, 64)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return

View File

@ -10,7 +10,7 @@ import (
)
// StartForwardAuction starts a normal auction that mints the sold coins.
func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (types.ID, sdk.Error) {
func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (uint64, sdk.Error) {
// create auction
auction := types.NewForwardAuction(seller, lot, bidDenom, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
@ -28,7 +28,7 @@ func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin
}
// StartReverseAuction starts an auction where sellers compete by offering decreasing prices.
func (k Keeper) StartReverseAuction(ctx sdk.Context, buyer string, bid sdk.Coin, initialLot sdk.Coin) (types.ID, sdk.Error) {
func (k Keeper) StartReverseAuction(ctx sdk.Context, buyer string, bid sdk.Coin, initialLot sdk.Coin) (uint64, sdk.Error) {
// create auction
auction := types.NewReverseAuction(buyer, bid, initialLot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
@ -46,7 +46,7 @@ func (k Keeper) StartReverseAuction(ctx sdk.Context, buyer string, bid sdk.Coin,
}
// StartForwardReverseAuction starts an auction where bidders bid up to a maxBid, then switch to bidding down on price.
func (k Keeper) StartForwardReverseAuction(ctx sdk.Context, seller string, lot sdk.Coin, maxBid sdk.Coin, lotReturnAddrs []sdk.AccAddress, lotReturnWeights []sdk.Int) (types.ID, sdk.Error) {
func (k Keeper) StartForwardReverseAuction(ctx sdk.Context, seller string, lot sdk.Coin, maxBid sdk.Coin, lotReturnAddrs []sdk.AccAddress, lotReturnWeights []sdk.Int) (uint64, sdk.Error) {
// create auction
weightedAddresses, err := types.NewWeightedAddresses(lotReturnAddrs, lotReturnWeights)
if err != nil {
@ -69,7 +69,7 @@ func (k Keeper) StartForwardReverseAuction(ctx sdk.Context, seller string, lot s
// PlaceBid places a bid on any auction.
// TODO passing bid and lot is weird when only one needed
func (k Keeper) PlaceBid(ctx sdk.Context, auctionID types.ID, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) sdk.Error {
func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) sdk.Error {
// get auction from store
auction, found := k.GetAuction(ctx, auctionID)
@ -261,7 +261,7 @@ func (k Keeper) PlaceBidReverse(ctx sdk.Context, a types.ReverseAuction, bidder
}
// CloseAuction closes an auction and distributes funds to the highest bidder.
func (k Keeper) CloseAuction(ctx sdk.Context, auctionID types.ID) sdk.Error {
func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) sdk.Error {
// get the auction from the store
auction, found := k.GetAuction(ctx, auctionID)

View File

@ -220,7 +220,7 @@ func TestStartForwardAuction(t *testing.T) {
// check auction in store and is correct
require.True(t, found)
expectedAuction := types.Auction(types.ForwardAuction{BaseAuction: types.BaseAuction{
ID: types.ID(0),
ID: 0,
Initiator: tc.args.seller,
Lot: tc.args.lot,
Bidder: nil,

View File

@ -30,21 +30,21 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, supplyKeeper types.Suppl
}
// SetNextAuctionID stores an ID to be used for the next created auction
func (k Keeper) SetNextAuctionID(ctx sdk.Context, id types.ID) {
func (k Keeper) SetNextAuctionID(ctx sdk.Context, id uint64) {
store := ctx.KVStore(k.storeKey)
store.Set(types.NextAuctionIDKey, id.Bytes())
store.Set(types.NextAuctionIDKey, types.Uint64ToBytes(id))
}
// GetNextAuctionID reads the next available global ID from store
// TODO might be nicer to convert not found error to a panic, it's not an error that can be recovered from
func (k Keeper) GetNextAuctionID(ctx sdk.Context) (types.ID, sdk.Error) {
func (k Keeper) GetNextAuctionID(ctx sdk.Context) (uint64, sdk.Error) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.NextAuctionIDKey)
if bz == nil {
//return 0, types.ErrInvalidGenesis(k.codespace, "initial auction ID hasn't been set") // TODO create error
return 0, sdk.ErrInternal("initial auction ID hasn't been set")
}
return types.NewIDFromBytes(bz), nil
return types.Uint64FromBytes(bz), nil
}
// incrementNextAuctionID increments the global ID in the store by 1
@ -58,7 +58,7 @@ func (k Keeper) IncrementNextAuctionID(ctx sdk.Context) sdk.Error {
}
// StoreNewAuction stores an auction, adding a new ID
func (k Keeper) StoreNewAuction(ctx sdk.Context, auction types.Auction) (types.ID, sdk.Error) {
func (k Keeper) StoreNewAuction(ctx sdk.Context, auction types.Auction) (uint64, sdk.Error) {
newAuctionID, err := k.GetNextAuctionID(ctx)
if err != nil {
return 0, err
@ -93,7 +93,7 @@ func (k Keeper) SetAuction(ctx sdk.Context, auction types.Auction) {
}
// getAuction gets an auction from the store by auctionID
func (k Keeper) GetAuction(ctx sdk.Context, auctionID types.ID) (types.Auction, bool) {
func (k Keeper) GetAuction(ctx sdk.Context, auctionID uint64) (types.Auction, bool) {
var auction types.Auction
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionKeyPrefix)
@ -107,7 +107,7 @@ func (k Keeper) GetAuction(ctx sdk.Context, auctionID types.ID) (types.Auction,
}
// DeleteAuction removes an auction from the store without any validation
func (k Keeper) DeleteAuction(ctx sdk.Context, auctionID types.ID) {
func (k Keeper) DeleteAuction(ctx sdk.Context, auctionID uint64) {
// remove from index
auction, found := k.GetAuction(ctx, auctionID)
if found {
@ -120,13 +120,13 @@ func (k Keeper) DeleteAuction(ctx sdk.Context, auctionID types.ID) {
}
// InsertIntoIndex adds an auction ID and end time into the byTime index
func (k Keeper) InsertIntoIndex(ctx sdk.Context, endTime time.Time, auctionID types.ID) {
func (k Keeper) InsertIntoIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
store.Set(types.GetAuctionByTimeKey(endTime, auctionID), auctionID.Bytes())
store.Set(types.GetAuctionByTimeKey(endTime, auctionID), types.Uint64ToBytes(auctionID)) // TODO
}
// RemoveFromIndex removes an auction ID and end time from the byTime index
func (k Keeper) RemoveFromIndex(ctx sdk.Context, endTime time.Time, auctionID types.ID) {
func (k Keeper) RemoveFromIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
store.Delete(types.GetAuctionByTimeKey(endTime, auctionID))
}
@ -134,7 +134,7 @@ func (k Keeper) RemoveFromIndex(ctx sdk.Context, endTime time.Time, auctionID ty
// IterateAuctionByTime provides an iterator over auctions ordered by auction.EndTime.
// For each auction cb will be callled. If cb returns true the iterator will close and stop.
// TODO can the cutoff time be removed in favour of caller specifying cutoffs in the callback?
func (k Keeper) IterateAuctionsByTime(ctx sdk.Context, inclusiveCutoffTime time.Time, cb func(auctionID types.ID) (stop bool)) {
func (k Keeper) IterateAuctionsByTime(ctx sdk.Context, inclusiveCutoffTime time.Time, cb func(auctionID uint64) (stop bool)) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
iterator := store.Iterator(
nil, // start at the very start of the prefix store
@ -144,7 +144,7 @@ func (k Keeper) IterateAuctionsByTime(ctx sdk.Context, inclusiveCutoffTime time.
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
// TODO get the auction ID - either read from store, or extract from key
auctionID := types.NewIDFromBytes(iterator.Value())
auctionID := types.Uint64FromBytes(iterator.Value())
if cb(auctionID) {
break

View File

@ -17,7 +17,7 @@ func SetGetDeleteAuction(t *testing.T) {
keeper := tApp.GetAuctionKeeper()
ctx := tApp.NewContext(true, abci.Header{})
someTime := time.Date(43, time.January, 1, 0, 0, 0, 0, time.UTC) // need to specify UTC as tz info is lost on unmarshal
id := types.ID(5)
var id uint64 = 5
auction := types.NewForwardAuction("some_module", c("usdx", 100), "kava", someTime).WithID(id)
// write and read from store
@ -28,7 +28,7 @@ func SetGetDeleteAuction(t *testing.T) {
require.True(t, found)
require.Equal(t, auction, readAuction)
// check auction is in the index
keeper.IterateAuctionsByTime(ctx, auction.GetEndTime(), func(readID types.ID) bool {
keeper.IterateAuctionsByTime(ctx, auction.GetEndTime(), func(readID uint64) bool {
require.Equal(t, auction.GetID(), readID)
return false
})
@ -40,7 +40,7 @@ func SetGetDeleteAuction(t *testing.T) {
_, found = keeper.GetAuction(ctx, id)
require.False(t, found)
// check auction not in index
keeper.IterateAuctionsByTime(ctx, time.Unix(999999999, 0), func(readID types.ID) bool {
keeper.IterateAuctionsByTime(ctx, time.Unix(999999999, 0), func(readID uint64) bool {
require.Fail(t, "index should be empty", " found auction ID '%s", readID)
return false
})
@ -53,7 +53,7 @@ func TestIncrementNextAuctionID(t *testing.T) {
ctx := tApp.NewContext(true, abci.Header{})
// store id
id := types.ID(123456)
var id uint64 = 123456
keeper.SetNextAuctionID(ctx, id)
require.NoError(t, keeper.IncrementNextAuctionID(ctx))
@ -101,7 +101,7 @@ func TestIterateAuctionsByTime(t *testing.T) {
// setup byTime index
byTimeIndex := []struct {
endTime time.Time
auctionID types.ID
auctionID uint64
}{
{time.Date(0, time.January, 1, 0, 0, 0, 0, time.UTC), 9999}, // distant past
{time.Date(1998, time.January, 1, 11, 59, 59, 999999999, time.UTC), 1}, // just before cutoff
@ -118,15 +118,15 @@ func TestIterateAuctionsByTime(t *testing.T) {
// read out values from index up to a cutoff time and check they are as expected
cutoffTime := time.Date(1998, time.January, 1, 12, 0, 0, 0, time.UTC)
var expectedIndex []types.ID
var expectedIndex []uint64
for _, v := range byTimeIndex {
if v.endTime.Before(cutoffTime) || v.endTime.Equal(cutoffTime) { // endTime ≤ cutoffTime
expectedIndex = append(expectedIndex, v.auctionID)
}
}
var readIndex []types.ID
keeper.IterateAuctionsByTime(ctx, cutoffTime, func(id types.ID) bool {
var readIndex []uint64
keeper.IterateAuctionsByTime(ctx, cutoffTime, func(id uint64) bool {
readIndex = append(readIndex, id)
return false
})

View File

@ -1,41 +1,17 @@
package types
import (
"encoding/binary"
"fmt"
"strconv"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/supply"
)
// ID type for auction IDs
type ID uint64
// TODO can this be removed?
// NewIDFromString generate new auction ID from a string
func NewIDFromString(s string) (ID, error) {
n, err := strconv.ParseUint(s, 10, 64) // copied from how the gov module rest handler's parse proposal IDs
if err != nil {
return 0, err
}
return ID(n), nil
}
func NewIDFromBytes(bz []byte) ID {
return ID(binary.BigEndian.Uint64(bz))
}
func (id ID) Bytes() []byte {
bz := make([]byte, 8)
binary.BigEndian.PutUint64(bz, uint64(id))
return bz
}
// Auction is an interface to several types of auction.
type Auction interface {
GetID() ID
WithID(ID) Auction
GetID() uint64
WithID(uint64) Auction
GetBidder() sdk.AccAddress
GetBid() sdk.Coin
GetLot() sdk.Coin
@ -44,7 +20,7 @@ type Auction interface {
// BaseAuction type shared by all Auctions
type BaseAuction struct {
ID ID
ID uint64
Initiator string // Module that starts the auction. Giving away Lot (aka seller in a forward auction). Restricted to being a module account name rather than any account.
Lot sdk.Coin // Amount of coins up being given by initiator (FA - amount for sale by seller, RA - cost of good by buyer (bid))
Bidder sdk.AccAddress // Person who bids in the auction. Receiver of Lot. (aka buyer in forward auction, seller in RA)
@ -54,7 +30,7 @@ type BaseAuction struct {
}
// GetID getter for auction ID
func (a BaseAuction) GetID() ID { return a.ID }
func (a BaseAuction) GetID() uint64 { return a.ID }
// GetBid getter for auction bid
func (a BaseAuction) GetBidder() sdk.AccAddress { return a.Bidder }
@ -88,7 +64,7 @@ type ForwardAuction struct {
}
// WithID returns an auction with the ID set
func (a ForwardAuction) WithID(id ID) Auction { a.ID = id; return a }
func (a ForwardAuction) WithID(id uint64) Auction { a.ID = id; return a }
// NewForwardAuction creates a new forward auction
func NewForwardAuction(seller string, lot sdk.Coin, bidDenom string, endTime time.Time) ForwardAuction {
@ -110,7 +86,7 @@ type ReverseAuction struct {
}
// WithID returns an auction with the ID set
func (a ReverseAuction) WithID(id ID) Auction { a.ID = id; return a }
func (a ReverseAuction) WithID(id uint64) Auction { a.ID = id; return a }
// NewReverseAuction creates a new reverse auction
func NewReverseAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, EndTime time.Time) ReverseAuction {
@ -138,7 +114,7 @@ type ForwardReverseAuction struct {
}
// WithID returns an auction with the ID set
func (a ForwardReverseAuction) WithID(id ID) Auction { a.ID = id; return a }
func (a ForwardReverseAuction) WithID(id uint64) Auction { a.ID = id; return a }
func (a ForwardReverseAuction) String() string {
return fmt.Sprintf(`Auction %d:

View File

@ -9,13 +9,13 @@ type GenesisAuctions []Auction
// GenesisState - auction state that must be provided at genesis
type GenesisState struct {
NextAuctionID ID
NextAuctionID uint64 `json:"next_auction_id" yaml:"next_auction_id"`
AuctionParams AuctionParams `json:"auction_params" yaml:"auction_params"`
Auctions GenesisAuctions `json:"genesis_auctions" yaml:"genesis_auctions"`
}
// NewGenesisState returns a new genesis state object for auctions module
func NewGenesisState(nextID ID, ap AuctionParams, ga GenesisAuctions) GenesisState {
func NewGenesisState(nextID uint64, ap AuctionParams, ga GenesisAuctions) GenesisState {
return GenesisState{
NextAuctionID: nextID,
AuctionParams: ap,
@ -25,7 +25,7 @@ func NewGenesisState(nextID ID, ap AuctionParams, ga GenesisAuctions) GenesisSta
// DefaultGenesisState defines default genesis state for auction module
func DefaultGenesisState() GenesisState {
return NewGenesisState(ID(0), DefaultAuctionParams(), GenesisAuctions{})
return NewGenesisState(0, DefaultAuctionParams(), GenesisAuctions{})
}
// Equal checks whether two GenesisState structs are equivalent

View File

@ -1,6 +1,7 @@
package types
import (
"encoding/binary"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -28,10 +29,20 @@ var (
NextAuctionIDKey = []byte{0x02}
)
func GetAuctionKey(auctionID ID) []byte {
return auctionID.Bytes()
func GetAuctionKey(auctionID uint64) []byte {
return Uint64ToBytes(auctionID)
}
func GetAuctionByTimeKey(endTime time.Time, auctionID ID) []byte {
return append(sdk.FormatTimeBytes(endTime), auctionID.Bytes()...)
func GetAuctionByTimeKey(endTime time.Time, auctionID uint64) []byte {
return append(sdk.FormatTimeBytes(endTime), Uint64ToBytes(auctionID)...)
}
func Uint64FromBytes(bz []byte) uint64 {
return binary.BigEndian.Uint64(bz)
}
func Uint64ToBytes(id uint64) []byte {
bz := make([]byte, 8)
binary.BigEndian.PutUint64(bz, uint64(id))
return bz
}

View File

@ -4,14 +4,14 @@ import sdk "github.com/cosmos/cosmos-sdk/types"
// MsgPlaceBid is the message type used to place a bid on any type of auction.
type MsgPlaceBid struct {
AuctionID ID
AuctionID uint64
Bidder sdk.AccAddress // This can be a buyer (who increments bid), or a seller (who decrements lot) TODO rename to be clearer?
Bid sdk.Coin
Lot sdk.Coin
}
// NewMsgPlaceBid returns a new MsgPlaceBid.
func NewMsgPlaceBid(auctionID ID, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) MsgPlaceBid {
func NewMsgPlaceBid(auctionID uint64, bidder sdk.AccAddress, bid sdk.Coin, lot sdk.Coin) MsgPlaceBid {
return MsgPlaceBid{
AuctionID: auctionID,
Bidder: bidder,

View File

@ -5,7 +5,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params/subspace"
"github.com/kava-labs/kava/x/auction"
"github.com/kava-labs/kava/x/liquidator/types"
)
@ -33,7 +32,7 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, paramstore subspace.Subs
// SeizeAndStartCollateralAuction pulls collateral out of a CDP and sells it in an auction for stable coin. Excess collateral goes to the original CDP owner.
// Known as Cat.bite in maker
// result: stable coin is transferred to module account, collateral is transferred from module account to buyer, (and any excess collateral is transferred to original CDP owner)
func (k Keeper) SeizeAndStartCollateralAuction(ctx sdk.Context, owner sdk.AccAddress, collateralDenom string) (auction.ID, sdk.Error) {
func (k Keeper) SeizeAndStartCollateralAuction(ctx sdk.Context, owner sdk.AccAddress, collateralDenom string) (uint64, sdk.Error) {
// Get CDP
cdp, found := k.cdpKeeper.GetCDP(ctx, owner, collateralDenom)
if !found {
@ -73,7 +72,7 @@ func (k Keeper) SeizeAndStartCollateralAuction(ctx sdk.Context, owner sdk.AccAdd
// StartDebtAuction sells off minted gov coin to raise set amounts of stable coin.
// Known as Vow.flop in maker
// result: minted gov coin moved to highest bidder, stable coin moved to moduleAccount
func (k Keeper) StartDebtAuction(ctx sdk.Context) (auction.ID, sdk.Error) {
func (k Keeper) StartDebtAuction(ctx sdk.Context) (uint64, sdk.Error) {
// Ensure amount of seized stable coin is 0 (ie Joy = 0)
stableCoins := k.bankKeeper.GetCoins(ctx, k.cdpKeeper.GetLiquidatorAccountAddress()).AmountOf(k.cdpKeeper.GetStableDenom())
@ -107,7 +106,7 @@ func (k Keeper) StartDebtAuction(ctx sdk.Context) (auction.ID, sdk.Error) {
// StartSurplusAuction sells off excess stable coin in exchange for gov coin, which is burned
// Known as Vow.flap in maker
// result: stable coin removed from module account (eventually to buyer), gov coin transferred to module account
// func (k Keeper) StartSurplusAuction(ctx sdk.Context) (auction.ID, sdk.Error) {
// func (k Keeper) StartSurplusAuction(ctx sdk.Context) (uint64, sdk.Error) {
// // TODO ensure seized debt is 0

View File

@ -3,7 +3,6 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/auction"
"github.com/kava-labs/kava/x/cdp"
)
@ -26,7 +25,7 @@ type BankKeeper interface {
// AuctionKeeper expected interface for the auction keeper
type AuctionKeeper interface {
StartForwardAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin) (auction.ID, sdk.Error)
StartReverseAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin) (auction.ID, sdk.Error)
StartForwardReverseAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin, sdk.AccAddress) (auction.ID, sdk.Error)
StartForwardAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin) (uint64, sdk.Error)
StartReverseAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin) (uint64, sdk.Error)
StartForwardReverseAuction(sdk.Context, sdk.AccAddress, sdk.Coin, sdk.Coin, sdk.AccAddress) (uint64, sdk.Error)
}