package deviantfactions import ( "context" "github.com/galacticship/terra/cosmos" "github.com/galacticship/terra" "github.com/pkg/errors" "github.com/shopspring/decimal" ) type Market struct { *terra.Contract } func NewMarket(q *terra.Querier) (*Market, error) { contract, err := terra.NewContract(q, "terra1t37vatdcsmg4qlyy8n4fgapecce5g4gw5mlzlt") if err != nil { return nil, errors.Wrap(err, "init contract object") } return &Market{ Contract: contract, }, nil } type Listing struct { Owner string TokenId string AskToken terra.Token Price decimal.Decimal BlockCreated int64 BlockExpires int64 } func (m *Market) AllListedTokens(ctx context.Context, collectionIds []string) ([]Listing, error) { var res []Listing startAfter := "" for { tmp, err := m.allListedTokensPage(ctx, collectionIds, 30, startAfter) if err != nil { return nil, errors.Wrapf(err, "getting page with startafter %s", startAfter) } res = append(res, tmp...) if len(tmp) < 30 { break } startAfter = tmp[len(tmp)-1].TokenId } return res, nil } func (m *Market) allListedTokensPage(ctx context.Context, collectionIds []string, limit int, startAfter string) ([]Listing, error) { var q struct { AllListedTokens struct { CollectionIds []string `json:"collection_ids"` Limit int `json:"limit"` StartAfter string `json:"start_after"` } `json:"all_listed_tokens"` } q.AllListedTokens.CollectionIds = collectionIds q.AllListedTokens.Limit = limit q.AllListedTokens.StartAfter = startAfter var r struct { Listings []struct { Owner string `json:"owner"` TokenId string `json:"token_id"` Ask struct { Denom string `json:"denom"` Amount decimal.Decimal `json:"amount"` } `json:"ask"` BlockCreated int64 `json:"block_created"` BlockExpires int64 `json:"block_expires"` } `json:"listings"` } err := m.QueryStore(ctx, q, &r) if err != nil { return nil, errors.Wrap(err, "querying store") } var res []Listing for _, listing := range r.Listings { token := terra.NativeTokenFromDenom(listing.Ask.Denom) res = append(res, Listing{ Owner: listing.Owner, TokenId: listing.TokenId, AskToken: token, Price: token.ValueFromTerra(listing.Ask.Amount), BlockCreated: listing.BlockCreated, BlockExpires: listing.BlockExpires, }) } return res, nil } func (m *Market) ListedTokensByUser(ctx context.Context, address cosmos.AccAddress) ([]string, error) { var res []string startAfter := "" for { tmp, err := m.listedTokensByUserPage(ctx, address, startAfter) if err != nil { return nil, errors.Wrapf(err, "getting page with startafter %s", startAfter) } if len(tmp) == 0 { break } res = append(res, tmp...) startAfter = tmp[len(tmp)-1] } return res, nil } func (m *Market) listedTokensByUserPage(ctx context.Context, address cosmos.AccAddress, startAfter string) ([]string, error) { var q struct { ListedTokens struct { Owner string `json:"owner"` StartAfter string `json:"start_after"` } `json:"listed_tokens"` } q.ListedTokens.Owner = address.String() q.ListedTokens.StartAfter = startAfter var r struct { Tokens []string `json:"tokens"` } err := m.QueryStore(ctx, q, &r) if err != nil { return nil, errors.Wrap(err, "querying store") } return r.Tokens, nil } func (m *Market) TokensByUser(ctx context.Context, address cosmos.AccAddress) ([]string, error) { var res []string startAfter := "" for { tmp, err := m.tokensByUserPage(ctx, address, 30, startAfter) if err != nil { return nil, errors.Wrapf(err, "getting page with startafter %s", startAfter) } if len(tmp) == 0 { break } res = append(res, tmp...) startAfter = tmp[len(tmp)-1] } return res, nil } func (m *Market) tokensByUserPage(ctx context.Context, address cosmos.AccAddress, limit int, startAfter string) ([]string, error) { var q struct { Tokens struct { Owner string `json:"owner"` Limit int `json:"limit"` StartAfter string `json:"start_after"` } `json:"tokens"` } q.Tokens.Owner = address.String() q.Tokens.Limit = limit q.Tokens.StartAfter = startAfter var r struct { Tokens []string `json:"tokens"` } err := m.QueryStore(ctx, q, &r) if err != nil { return nil, errors.Wrap(err, "querying store") } return r.Tokens, nil } func (m *Market) NewCancelTokenListingMessage(sender cosmos.AccAddress, tokenId string) (cosmos.Msg, error) { var q struct { CancelTokenListing struct { TokenId string `json:"token_id"` } `json:"cancel_token_listing"` } q.CancelTokenListing.TokenId = tokenId return m.NewMsgExecuteContract(sender, q) } func (m *Market) NewListTokenMessage(sender cosmos.AccAddress, tokenId string, AskToken terra.NativeToken, AskPrice decimal.Decimal, BlocksToListFor int64) (cosmos.Msg, error) { var q struct { ListToken struct { TokenId string `json:"token_id"` Ask struct { Denom string `json:"denom"` Amount decimal.Decimal `json:"amount"` } `json:"ask"` BlocksToListFor int64 `json:"blocks_to_list_for"` } `json:"list_token"` } q.ListToken.TokenId = tokenId q.ListToken.Ask.Denom = AskToken.Denom() q.ListToken.Ask.Amount = AskToken.ValueToTerra(AskPrice) q.ListToken.BlocksToListFor = BlocksToListFor return m.NewMsgExecuteContract(sender, q) }